From 3a38c34ea09b275b9d7155a9df0c1508b5cd6a5c 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 15:54:15 +0800 Subject: [PATCH] up --- .workbuddy/expert-history.json | 2 +- backend/my_work/routers/apiPurchase.go | 56 ++++++- frontend/ops_vue_js/src/api/purchase.js | 5 + .../src/components/ConfirmDialog.vue | 142 ++++++++++++++++++ frontend/ops_vue_js/src/i18n/en.json | 7 + frontend/ops_vue_js/src/i18n/zh-CN.json | 7 + .../src/views/purchase/PurchaseList.vue | 31 +++- .../src/views/purchase/editorder.vue | 60 +++++++- 8 files changed, 288 insertions(+), 22 deletions(-) create mode 100644 frontend/ops_vue_js/src/components/ConfirmDialog.vue diff --git a/.workbuddy/expert-history.json b/.workbuddy/expert-history.json index 3c1209f..0768fd6 100644 --- a/.workbuddy/expert-history.json +++ b/.workbuddy/expert-history.json @@ -13,5 +13,5 @@ } ] }, - "lastUpdated": 1776148343594 + "lastUpdated": 1776153171221 } \ No newline at end of file diff --git a/backend/my_work/routers/apiPurchase.go b/backend/my_work/routers/apiPurchase.go index ca85de9..6e8e380 100644 --- a/backend/my_work/routers/apiPurchase.go +++ b/backend/my_work/routers/apiPurchase.go @@ -317,6 +317,7 @@ func ApiPurchase(r *gin.RouterGroup) { type From_purchase_getorders struct { Search string + Status string Entries int Page int } @@ -336,14 +337,20 @@ func ApiPurchase(r *gin.RouterGroup) { if is_data_ok { - //读取有多少条目 - var count int64 - models.DB.Model(TabPurchaseOrder{}).Count(&count) - //fmt.Println(count) + //读取有多少条目 + var count int64 + query := models.DB.Model(TabPurchaseOrder{}) + if jsondata.Search != "" { + query = query.Where("title LIKE ?", "%"+jsondata.Search+"%") + } + if jsondata.Status != "" { + query = query.Where("order_status = ?", jsondata.Status) + } + query.Count(&count) - //读取条目 - var getorders []TabPurchaseOrder - models.DB.Order("created_at DESC").Offset(jsondata.Entries * (jsondata.Page - 1)).Limit(jsondata.Entries).Find(&getorders) + //读取条目 + var getorders []TabPurchaseOrder + query.Order("created_at DESC").Offset(jsondata.Entries * (jsondata.Page - 1)).Limit(jsondata.Entries).Find(&getorders) ReturnJson(ctx, "apiOK", map[string]interface{}{ "all_count": count, @@ -611,4 +618,39 @@ func ApiPurchase(r *gin.RouterGroup) { ReturnJson(ctx, "apiOK", nil) }) + // 删除订单 + r.POST("/deleteorder", func(ctx *gin.Context) { + isAuth, _, data := AuthenticationAuthority(ctx) + if !isAuth { + ReturnJson(ctx, "userCookieError", nil) + return + } + + type FromDeleteOrder struct { + ID uint `json:"id"` + } + var from FromDeleteOrder + if err := decodeJSON(data, &from); err != nil || from.ID == 0 { + ReturnJson(ctx, "jsonErr", 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 + } + + // 关联删除(硬删,不保留) + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseCosts{}) + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseFileBind{}) + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseCommit{}) + models.DB.Where("order_id = ?", from.ID).Delete(&TabPurchaseLog{}) + + // 软删除订单本身 + models.DB.Delete(&order) + + 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 7c83efc..6c22164 100644 --- a/frontend/ops_vue_js/src/api/purchase.js +++ b/frontend/ops_vue_js/src/api/purchase.js @@ -25,4 +25,9 @@ export const purchaseApi = { updateOrder(id, data) { return api.post('/purchase/updateorder', { id, ...data }) }, + + /** 删除订单 */ + deleteOrder(id) { + return api.post('/purchase/deleteorder', { id }) + }, } diff --git a/frontend/ops_vue_js/src/components/ConfirmDialog.vue b/frontend/ops_vue_js/src/components/ConfirmDialog.vue new file mode 100644 index 0000000..704bae7 --- /dev/null +++ b/frontend/ops_vue_js/src/components/ConfirmDialog.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/frontend/ops_vue_js/src/i18n/en.json b/frontend/ops_vue_js/src/i18n/en.json index 6e42966..1101c30 100644 --- a/frontend/ops_vue_js/src/i18n/en.json +++ b/frontend/ops_vue_js/src/i18n/en.json @@ -66,6 +66,7 @@ "created_at": "Created At", "updated_at": "Updated At", "status": "Status", + "filter_all": "All", "status_pending": "Pending", "status_ordered": "Ordered", "status_arrived": "Arrived", @@ -82,8 +83,11 @@ "There_are_a_total_of": ",There are a total of", "items": "orders.", "order_detail": "Order Detail", + "back": "Back", "back_to_list": "Back to List", "order_not_found": "Order Not Found", + "delete_order": "Delete Order", + "confirm_delete": "Are you sure you want to delete this order? This action cannot be undone.", "order_info": "Order Information", "cost_detail": "Cost Details", "photo_remarks": "Photos", @@ -227,12 +231,15 @@ "administrator": "Administrator", "select_date": "Select a date", "save_ok": "Saved successfully", + "delete_ok": "Deleted successfully", "change_ok": "Changed successfully", "type_old_pass": "Enter old password", "type_new_pass": "Enter new password", "type_cof_pass": "Confirm new password", "old_pass_incorrect": "Old password is incorrect", "confirm_password_incorrect": "Confirm password is incorrect", + "confirm": "Confirm", + "cancel": "Cancel", "save_success": "Saved successfully", "submit": "Submit", "loading": "Loading..." diff --git a/frontend/ops_vue_js/src/i18n/zh-CN.json b/frontend/ops_vue_js/src/i18n/zh-CN.json index c188d0b..48c575e 100644 --- a/frontend/ops_vue_js/src/i18n/zh-CN.json +++ b/frontend/ops_vue_js/src/i18n/zh-CN.json @@ -66,6 +66,7 @@ "created_at": "创建日期", "updated_at": "更新日期", "status": "状态", + "filter_all": "全部", "status_pending": "待处理", "status_ordered": "已下单", "status_arrived": "已到达", @@ -82,8 +83,11 @@ "There_are_a_total_of": ",一共", "items": "个订单", "order_detail": "订单详情", + "back": "返回", "back_to_list": "返回列表", "order_not_found": "订单不存在", + "delete_order": "删除订单", + "confirm_delete": "确定要删除此订单吗?此操作不可撤销。", "order_info": "订单信息", "cost_detail": "费用明细", "photo_remarks": "图片备注", @@ -233,6 +237,9 @@ "type_cof_pass": "确认新密码", "old_pass_incorrect": "旧密码不正确", "confirm_password_incorrect": "确认密码不正确", + "confirm": "确认", + "cancel": "取消", + "delete_ok": "删除成功", "save_success": "保存成功", "submit": "提交", "loading": "加载中..." diff --git a/frontend/ops_vue_js/src/views/purchase/PurchaseList.vue b/frontend/ops_vue_js/src/views/purchase/PurchaseList.vue index ca15403..f36bdc2 100644 --- a/frontend/ops_vue_js/src/views/purchase/PurchaseList.vue +++ b/frontend/ops_vue_js/src/views/purchase/PurchaseList.vue @@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n' import { useToastStore } from '@/stores/toast' import { usePageTitle } from '@/composables/usePageTitle' import { purchaseApi } from '@/api/purchase' -import { IconPlus, IconChevronLeftPipe, IconChevronRightPipe, IconChevronsLeft, IconChevronsRight, IconSearch } from '@tabler/icons-vue' +import { IconPlus, IconChevronLeftPipe, IconChevronRightPipe, IconChevronsLeft, IconChevronsRight } from '@tabler/icons-vue' usePageTitle('appname.purchase') const { t, locale } = useI18n() @@ -16,9 +16,19 @@ const orders = ref([]) const totalCount = ref(0) const pageSize = ref(10) const currentPage = ref(1) -const searchQuery = ref('') +const statusFilter = ref('') const loading = ref(false) +const statusOptions = [ + { value: '', labelKey: 'purchase.filter_all' }, + { value: 'pending', labelKey: 'purchase.status_pending' }, + { value: 'ordered', labelKey: 'purchase.status_ordered' }, + { value: 'arrived', labelKey: 'purchase.status_arrived' }, + { value: 'received', labelKey: 'purchase.status_received' }, + { value: 'lost', labelKey: 'purchase.status_lost' }, + { value: 'returned', labelKey: 'purchase.status_returned' }, +] + const totalPages = computed(() => Math.ceil(totalCount.value / pageSize.value) || 1) const pageRange = computed(() => { @@ -34,7 +44,7 @@ async function fetchOrders() { loading.value = true try { const { errCode, data } = await purchaseApi.getOrders({ - search: searchQuery.value, + status: statusFilter.value, entries: pageSize.value, page: currentPage.value, }) @@ -107,11 +117,16 @@ onMounted(fetchOrders) {{ t('purchase.add_part') }} - - -
- - + +
diff --git a/frontend/ops_vue_js/src/views/purchase/editorder.vue b/frontend/ops_vue_js/src/views/purchase/editorder.vue index 3a9e51a..3588954 100644 --- a/frontend/ops_vue_js/src/views/purchase/editorder.vue +++ b/frontend/ops_vue_js/src/views/purchase/editorder.vue @@ -17,6 +17,7 @@ import { useValidation } from "@/composables"; import { purchaseApi } from "@/api/purchase"; import tagadder from "@/components/tagadder.vue"; import useDropzone from "@/components/useDropzone.vue"; +import ConfirmDialog from "@/components/ConfirmDialog.vue"; usePageTitle("purchase_addorder.edit_order"); @@ -96,6 +97,7 @@ watch( // ==================== 图片上传 ==================== const dropzoneRef = ref(null); +const showDeleteConfirm = ref(false); function getPhotoHashes() { return dropzoneRef.value?.return_files().map((f) => f.hash) ?? []; @@ -152,6 +154,30 @@ onMounted(async () => { } }); +// ==================== 提交 ==================== +// ==================== 删除订单 ==================== +async function handleDelete() { + showDeleteConfirm.value = true; +} + +async function doDelete() { + + loading.value = true; + try { + const res = await purchaseApi.deleteOrder(orderId); + if (res.errCode === 0) { + toast.success(t("message.delete_ok")); + router.replace("/purchase"); + } else { + toast.error(t("message.server_error")); + } + } catch { + toast.error(t("message.server_error")); + } finally { + loading.value = false; + } +} + // ==================== 提交 ==================== async function handleSubmit() { clearErrors(); @@ -241,11 +267,24 @@ async function handleSubmit() {

{{ t("purchase_addorder.edit_order") }}

- - + + + @@ -532,4 +572,12 @@ async function handleSubmit() { + + +