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 @@
+
+
+
+
+
+
+
+
+
+
+ {{ title || t("message.confirm") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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") }}
-
-