From 11466cb56eddc6acfa976bcc20989eb681e3407e Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 24 Apr 2026 09:26:31 +0800 Subject: [PATCH] up --- .workbuddy/memory/2026-04-24.md | 21 ++++ backend/my_work/routers/apiPurchase.go | 106 +++++++++++++++-- frontend/ops_vue_js/src/api/purchase.js | 5 + .../src/views/purchase/ShowOrder.vue | 111 +++++++++++++++++- 4 files changed, 232 insertions(+), 11 deletions(-) create mode 100644 .workbuddy/memory/2026-04-24.md diff --git a/.workbuddy/memory/2026-04-24.md b/.workbuddy/memory/2026-04-24.md new file mode 100644 index 0000000..9397002 --- /dev/null +++ b/.workbuddy/memory/2026-04-24.md @@ -0,0 +1,21 @@ +# 2026-04-24 工作日志 + +## 采购订单详情页增加关联工单功能 + +**后端(apiPurchase.go):** +- `getorder` 接口新增返回字段 `workOrders`:通过 `TabWorkOrderPurchaseOrderBind` 表查询关联的工单列表(去重),包含 id/title/status +- 新增 `/purchase/search_work_orders` 接口:支持按 ID 精确匹配或标题/描述模糊搜索工单,返回最新的若干条结果 + +**前端 API(purchase.js):** +- 新增 `searchWorkOrders(search, limit)` 方法 + +**前端 ShowOrder.vue(采购订单详情页):** +- 增加关联工单展示卡片(位于图片备注与状态记录之间) +- 显示所有关联工单列表(点击跳转工单详情) +- 右上角"新增工单"按钮,跳转到新增工单页面并预填采购订单信息(存 localStorage) +- 工单状态颜色/文字与 ShowWorkOrder 保持一致 + +## 其他本次 session 改动(从 git 状态推断) +- 采购列表后端排序改为 `updated_at DESC, id DESC`(apiPurchase.go) +- 物品详情"关联工单"按钮文本改为 i18n `work_order.add`(WarehouseItemDetail.vue) +- 关联工单列表图标从 IconPackage 改为 IconFile(WarehouseItemDetail.vue) diff --git a/backend/my_work/routers/apiPurchase.go b/backend/my_work/routers/apiPurchase.go index 245d8c2..0b057e8 100644 --- a/backend/my_work/routers/apiPurchase.go +++ b/backend/my_work/routers/apiPurchase.go @@ -234,16 +234,49 @@ func ApiPurchase(r *gin.RouterGroup) { commitResps = append(commitResps, resp) } - // 判断当前用户是否可以修改 - canModify := canModifyPurchase(user.ID, order.UserID) + // 查询关联工单(通过 TabWorkOrderPurchaseOrderBind 表) + type WorkOrderInfo struct { + ID uint `json:"id"` + Title string `json:"title"` + CurrentStatus string `json:"status"` + } + var linkedWorkOrders []WorkOrderInfo + var woBinds []TabWorkOrderPurchaseOrderBind + models.DB.Where("purchase_order_id = ?", from.ID).Find(&woBinds) + if len(woBinds) > 0 { + woIDSet := make(map[uint]bool) + var woIDs []uint + for _, wb := range woBinds { + if !woIDSet[wb.WorkOrderID] { + woIDSet[wb.WorkOrderID] = true + woIDs = append(woIDs, wb.WorkOrderID) + } + } + var workOrders []TabWorkOrder + models.DB.Where("id IN ?", woIDs).Find(&workOrders) + for _, wo := range workOrders { + linkedWorkOrders = append(linkedWorkOrders, WorkOrderInfo{ + ID: wo.ID, + Title: wo.Title, + CurrentStatus: wo.CurrentStatus, + }) + } + } + if linkedWorkOrders == nil { + linkedWorkOrders = []WorkOrderInfo{} + } - ReturnJson(ctx, "apiOK", gin.H{ - "order": order, - "canModify": canModify, - "costs": costs, - "photos": files, - "commits": commitResps, - }) + // 判断当前用户是否可以修改 + canModify := canModifyPurchase(user.ID, order.UserID) + + ReturnJson(ctx, "apiOK", gin.H{ + "order": order, + "canModify": canModify, + "costs": costs, + "photos": files, + "commits": commitResps, + "workOrders": linkedWorkOrders, + }) }) // 更新订单状态(可附带评论) @@ -800,4 +833,59 @@ func ApiPurchase(r *gin.RouterGroup) { }) }) + // 搜索工单(用于采购订单关联) + r.POST("/search_work_orders", func(ctx *gin.Context) { + isAuth, _, data := AuthenticationAuthority(ctx) + if !isAuth { + ReturnJson(ctx, "userCookieError", nil) + return + } + + type FromSearch struct { + Search string `json:"search"` + Limit int `json:"limit"` + } + var from FromSearch + if err := decodeJSON(data, &from); err != nil { + ReturnJson(ctx, "jsonErr", nil) + return + } + if from.Limit <= 0 || from.Limit > 20 { + from.Limit = 5 + } + + query := models.DB.Model(&TabWorkOrder{}) + if from.Search != "" { + var id uint + if _, err := parsefmt.Sscanf(from.Search, "%d", &id); err == nil && id > 0 { + query = query.Where("id = ?", id) + } else { + query = query.Where("title LIKE ? OR description LIKE ?", + "%"+from.Search+"%", "%"+from.Search+"%") + } + } + + var orders []TabWorkOrder + query.Order("updated_at DESC, id DESC").Limit(from.Limit).Find(&orders) + + type WorkOrderInfo struct { + ID uint `json:"id"` + Title string `json:"title"` + Status string `json:"status"` + } + var result []WorkOrderInfo + for _, o := range orders { + result = append(result, WorkOrderInfo{ + ID: o.ID, + Title: o.Title, + Status: o.CurrentStatus, + }) + } + if result == nil { + result = []WorkOrderInfo{} + } + + ReturnJson(ctx, "apiOK", gin.H{"orders": result}) + }) + } diff --git a/frontend/ops_vue_js/src/api/purchase.js b/frontend/ops_vue_js/src/api/purchase.js index 165e1d6..0abbae1 100644 --- a/frontend/ops_vue_js/src/api/purchase.js +++ b/frontend/ops_vue_js/src/api/purchase.js @@ -40,4 +40,9 @@ export const purchaseApi = { deleteCommit(orderId, commitId) { return api.post('/purchase/delete_commit', { orderId, commitId }) }, + + /** 搜索工单(用于采购订单关联) */ + searchWorkOrders(search = '', limit = 5) { + return api.post('/purchase/search_work_orders', { search, limit }) + }, } diff --git a/frontend/ops_vue_js/src/views/purchase/ShowOrder.vue b/frontend/ops_vue_js/src/views/purchase/ShowOrder.vue index 47337d4..d40be28 100644 --- a/frontend/ops_vue_js/src/views/purchase/ShowOrder.vue +++ b/frontend/ops_vue_js/src/views/purchase/ShowOrder.vue @@ -1,5 +1,5 @@