From 126e15dfa92c31fd6f3a4c5483e958deedde469d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=87=E5=B3=B0?= Date: Tue, 14 Apr 2026 12:14:45 +0800 Subject: [PATCH] up --- .workbuddy/expert-history.json | 2 +- .workbuddy/memory/2026-04-14.md | 12 + backend/my_work/routers/apiPurchase.go | 109 ++++++ frontend/ops_vue_js/src/api/purchase.js | 5 + .../src/components/PurchaseOrderForm.vue | 323 ++++++++++++++++++ frontend/ops_vue_js/src/i18n/en.json | 9 +- frontend/ops_vue_js/src/i18n/zh-CN.json | 9 +- frontend/ops_vue_js/src/router/index.js | 5 + .../src/views/purchase/ShowOrder.vue | 17 +- .../src/views/purchase/addorder.vue | 12 +- .../src/views/purchase/editorder.vue | 195 +++++++++++ 11 files changed, 684 insertions(+), 14 deletions(-) create mode 100644 .workbuddy/memory/2026-04-14.md create mode 100644 frontend/ops_vue_js/src/components/PurchaseOrderForm.vue create mode 100644 frontend/ops_vue_js/src/views/purchase/editorder.vue diff --git a/.workbuddy/expert-history.json b/.workbuddy/expert-history.json index b044854..d295549 100644 --- a/.workbuddy/expert-history.json +++ b/.workbuddy/expert-history.json @@ -13,5 +13,5 @@ } ] }, - "lastUpdated": 1776135998489 + "lastUpdated": 1776136244169 } \ No newline at end of file diff --git a/.workbuddy/memory/2026-04-14.md b/.workbuddy/memory/2026-04-14.md new file mode 100644 index 0000000..b99443f --- /dev/null +++ b/.workbuddy/memory/2026-04-14.md @@ -0,0 +1,12 @@ +# 2026-04-14 + +## 修复 mapstructure IgnoreUntaggedField 编译错误 +- `DecoderConfig` 不存在 `IgnoreUntaggedField` 字段,移除后改为 JSON 中转方案(`json.Marshal` + `json.Unmarshal`),绕过 mapstructure 字段名匹配问题,编译通过。 + +## 新增订单编辑功能 +- 抽取公共组件 `src/components/PurchaseOrderForm.vue`,供 addorder/editorder 共用(标题/备注/链接/款式标签/费用明细/图片上传) +- 创建 `src/views/purchase/editorder.vue`:路由参数 `:id` 加载订单 → 回填 → 调用 `/purchase/updateorder` 保存 +- 后端新增 `POST /purchase/updateorder` 接口:更新基本字段 + 重建费用明细 + 重建图片绑定 + 写操作日志,编译通过 +- 前端 `purchase.js` 新增 `updateOrder(id, data)` 方法 +- 注册路由 `purchase/editorder/:id`,ShowOrder.vue 顶部加编辑按钮 +- i18n 补充:`purchase.edit_order`、`purchase_addorder.edit_order`、`message.loading`(中英双语) diff --git a/backend/my_work/routers/apiPurchase.go b/backend/my_work/routers/apiPurchase.go index 07b13cb..d212aa8 100644 --- a/backend/my_work/routers/apiPurchase.go +++ b/backend/my_work/routers/apiPurchase.go @@ -502,4 +502,113 @@ func ApiPurchase(r *gin.RouterGroup) { //ReturnJson(ctx, "apiErr", nil) }) + // 编辑订单基本信息 + r.POST("/updateorder", func(ctx *gin.Context) { + isAuth, user, data := AuthenticationAuthority(ctx) + if !isAuth { + ReturnJson(ctx, "userCookieError", nil) + return + } + + type FromUpdateOrder struct { + ID uint `json:"id"` + Title string `json:"title"` + Remark string `json:"remark"` + Link string `json:"link"` + Styles string `json:"styles"` + Photos []string `json:"photos"` + Costs []CostItem `json:"costs"` + } + var from FromUpdateOrder + if err := decodeJSON(data, &from); err != nil || from.ID == 0 { + ReturnJson(ctx, "jsonErr", nil) + return + } + if from.Title == "" { + ReturnJson(ctx, "jsonErr_1", nil) + return + } + + // 校验图片哈希 + for _, hash := range from.Photos { + if models.IsContainsSpecialChar(hash) { + ReturnJson(ctx, "photo_hash_invalid", nil) + return + } + } + // 校验费用 + for _, c := range from.Costs { + if c.Cost <= 0 || c.Int <= 0 { + ReturnJson(ctx, "jsonErr_1", nil) + return + } + } + + var order TabPurchaseOrder + if err := models.DB.Where("id = ?", from.ID).First(&order).Error; err != nil { + ReturnJson(ctx, "order_not_found", nil) + return + } + + // 记录旧数据 + oldContent, _ := json.Marshal(order) + + // 更新基本字段 + if err := models.DB.Model(&order).Updates(map[string]interface{}{ + "title": from.Title, + "remark": from.Remark, + "link": from.Link, + "styles": from.Styles, + }).Error; err != nil { + ReturnJson(ctx, "apiErr", nil) + return + } + + // 重建费用明细:先删旧,再插新 + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseCosts{}) + for _, c := range from.Costs { + ct := c.CurrencyType + if ct <= 0 { + ct = 1 + } + ctype := c.Type + if ctype <= 0 { + ctype = 1 + } + models.DB.Create(&TabPurchaseCosts{ + Price: c.Cost, + Quantity: c.Int, + UserID: user.ID, + OrderID: from.ID, + CurrencyType: ct, + CostType: ctype, + }) + } + + // 重建图片绑定:先删旧,再插新 + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseFileBind{}) + for _, hash := range from.Photos { + findFile := models.TabFileInfo_{Sha256: hash, Type: "image"} + if models.DB.Where(&findFile).First(&findFile).Error == nil { + models.DB.Create(&TabPurchaseFileBind{ + OrderID: from.ID, + FileID: findFile.ID, + }) + } + } + + // 写操作日志 + newContent, _ := json.Marshal(from) + models.DB.Create(&TabPurchaseLog{ + UserID: user.ID, + OrderID: from.ID, + ActionType: "update", + OldContent: string(oldContent), + NewContent: string(newContent), + IP: ctx.ClientIP(), + }) + + ReturnJson(ctx, "apiOK", nil) + }) + } diff --git a/frontend/ops_vue_js/src/api/purchase.js b/frontend/ops_vue_js/src/api/purchase.js index e3ec4fd..7c83efc 100644 --- a/frontend/ops_vue_js/src/api/purchase.js +++ b/frontend/ops_vue_js/src/api/purchase.js @@ -20,4 +20,9 @@ export const purchaseApi = { updateOrderStatus(id, status, comment = '', photos = []) { return api.post('/purchase/updatestatus', { id, status, comment, photos }) }, + + /** 编辑订单基本信息(标题/备注/链接/款式/费用/图片) */ + updateOrder(id, data) { + return api.post('/purchase/updateorder', { id, ...data }) + }, } diff --git a/frontend/ops_vue_js/src/components/PurchaseOrderForm.vue b/frontend/ops_vue_js/src/components/PurchaseOrderForm.vue new file mode 100644 index 0000000..d6a4dad --- /dev/null +++ b/frontend/ops_vue_js/src/components/PurchaseOrderForm.vue @@ -0,0 +1,323 @@ + + +