hurx 2 mēneši atpakaļ
vecāks
revīzija
f58e66b779

+ 8 - 0
src/api/order/deliverProduct/types.ts

@@ -36,6 +36,10 @@ export interface DeliverProductVO {
    */
   deliverNum: number;
 
+  orderPrice: number;
+
+  subtotal: number;
+
   dataSource: string;
 
   /**
@@ -82,6 +86,10 @@ export interface DeliverProductForm extends BaseEntity {
    */
   deliverNum?: number;
 
+  orderPrice: number;
+
+  subtotal: number;
+
   dataSource?: string;
 
   /**

+ 34 - 0
src/api/order/orderDeliver/index.ts

@@ -75,3 +75,37 @@ export const queryTrack = (query?: OrderDeliverQuery): AxiosPromise<OrderDeliver
     params: query
   });
 };
+
+/**
+ * 根据客户ID查询发货单(分页)
+ * @param customerId 客户ID
+ * @param pageQuery 分页参数
+ */
+export const getCustomerDeliverOrders = (customerId: string | number, pageQuery?: { pageNum?: number; pageSize?: number }) => {
+  return request({
+    url: '/order/orderDeliver/getCustomerDeliverOrders/' + customerId,
+    method: 'get',
+    params: pageQuery
+  });
+};
+
+/**
+ * 根据多个订单ID查询对应的订单商品列表
+ * @param orderIds
+ */
+export function getCustomerOrderProductList(orderIds: (string | number)[]) {
+  if (!Array.isArray(orderIds) || orderIds.length === 0) {
+    return Promise.reject(new Error('订单ID不能为空'));
+  }
+
+  // 手动构造查询参数,确保格式为 orderId=1&orderId=2&orderId=3
+  const params = new URLSearchParams();
+  orderIds.forEach((id) => {
+    params.append('orderId', String(id));
+  });
+
+  return request({
+    url: '/order/orderDeliver/getCustomerOrderProductList?' + params.toString(),
+    method: 'get'
+  });
+}

+ 0 - 5
src/views/bill/statementInvoice/addDrawer.vue

@@ -87,11 +87,6 @@
               {{ scope.row.unitPrice ? Number(scope.row.unitPrice).toFixed(2) : '0.00' }}
             </template>
           </el-table-column>
-          <el-table-column label="金额" align="center">
-            <template #default="scope">
-              {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}
-            </template>
-          </el-table-column>
           <el-table-column label="小计" align="center">
             <template #default="scope">
               {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}

+ 0 - 5
src/views/bill/statementInvoice/detailDrawer.vue

@@ -90,11 +90,6 @@
               {{ scope.row.unitPrice ? Number(scope.row.unitPrice).toFixed(2) : '0.00' }}
             </template>
           </el-table-column>
-          <el-table-column label="金额" align="center">
-            <template #default="scope">
-              {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}
-            </template>
-          </el-table-column>
           <el-table-column label="小计" align="center">
             <template #default="scope">
               {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}

+ 53 - 34
src/views/bill/statementInvoice/index.vue

@@ -78,39 +78,11 @@
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
           <template #default="scope">
-            <el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['bill:statementInvoice:edit']">查看</el-button>
-            <el-button
-              link
-              type="primary"
-              @click="handleUpdate(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementInvoice:edit']"
-              >编辑</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleSend(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementInvoice:edit']"
-              >发送对账单</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleWithdraw(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementInvoice:edit']"
-              >撤回</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleObsolete(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementInvoice:remove']"
-              >作废</el-button
-            >
+            <template v-for="btn in getAvailableButtons(scope.row.invoiceStatus)" :key="btn.action">
+              <el-button link type="primary" @click="btn.handler(scope.row)" v-hasPermi="[btn.permission]">
+                {{ btn.label }}
+              </el-button>
+            </template>
           </template>
         </el-table-column>
       </el-table>
@@ -153,6 +125,22 @@ const dialog = reactive<DialogOption>({
   title: ''
 });
 
+// 发票单状态枚举
+enum InvoiceStatus {
+  DRAFT = 0, // 待确认
+  PENDING = 1, // 待对账
+  CONFIRMED = 2, // 已对账
+  OBSOLETE = 3 // 已作废
+}
+
+// 按钮配置类型
+interface ActionButton {
+  action: string;
+  label: string;
+  handler: (row: StatementInvoiceVO) => void;
+  permission: string;
+}
+
 const initFormData: StatementInvoiceForm = {
   id: undefined,
   statementInvoiceNo: undefined,
@@ -314,11 +302,42 @@ const handleObsolete = async (row?: StatementInvoiceVO) => {
   const _no = row?.statementInvoiceNo;
   const oldValue = row.invoiceStatus; // 保存旧值
   await proxy?.$modal.confirm('是否作废当前发票编号【' + _no + '】吗?').finally(() => (loading.value = false));
-  await changeStatus(row.id, '4'); // 传新值 4 - 作废
+  await changeStatus(row.id, '3'); // 传新值 3 - 作废
   proxy?.$modal.msgSuccess('作废成功');
   await getList();
 };
 
+// 按钮配置映射:状态 -> 可用按钮列表
+const buttonConfigMap: Record<number, ActionButton[]> = {
+  [InvoiceStatus.DRAFT]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementInvoice:edit' },
+    { action: 'edit', label: '编辑', handler: handleUpdate, permission: 'bill:statementInvoice:edit' },
+    { action: 'send', label: '发送对账单', handler: handleSend, permission: 'bill:statementInvoice:edit' },
+    { action: 'withdraw', label: '撤回', handler: handleWithdraw, permission: 'bill:statementInvoice:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementInvoice:remove' }
+  ],
+  [InvoiceStatus.PENDING]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementInvoice:edit' },
+    { action: 'edit', label: '编辑', handler: handleUpdate, permission: 'bill:statementInvoice:edit' },
+    { action: 'withdraw', label: '撤回', handler: handleWithdraw, permission: 'bill:statementInvoice:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementInvoice:remove' }
+  ],
+  [InvoiceStatus.CONFIRMED]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementInvoice:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementInvoice:remove' }
+  ],
+  [InvoiceStatus.OBSOLETE]: [{ action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementInvoice:edit' }]
+};
+
+/**
+ * 根据对发票状态获取可用按钮列表
+ * @param status 发票单状态
+ * @returns 可用按钮配置数组
+ */
+const getAvailableButtons = (status: number): ActionButton[] => {
+  return buttonConfigMap[status] || [{ action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementInvoice:edit' }];
+};
+
 /** 导出按钮操作 */
 const handleExport = () => {
   proxy?.download(

+ 15 - 18
src/views/bill/statementOrder/addDrawer.vue

@@ -114,6 +114,7 @@
         <el-table :data="form.detailList" border style="width: 100%; margin-bottom: 20px">
           <el-table-column type="index" label="序号" width="60" align="center" />
           <el-table-column prop="orderNo" label="订单编号" min-width="150" align="center" />
+          <el-table-column prop="deliverCode" label="发货单编号" min-width="150" align="center" />
           <el-table-column prop="amount" label="金额" min-width="120" align="center" />
           <el-table-column prop="orderTime" label="下单日期" min-width="120" align="center" />
           <el-table-column prop="userName" label="下单人" min-width="100" align="center" />
@@ -147,11 +148,6 @@
               {{ scope.row.unitPrice ? Number(scope.row.unitPrice).toFixed(2) : '0.00' }}
             </template>
           </el-table-column>
-          <el-table-column label="金额" width="120" align="center">
-            <template #default="scope">
-              {{ Number(scope.row.subtotal || 0).toFixed(2) }}
-            </template>
-          </el-table-column>
           <el-table-column label="小计" width="120" align="center">
             <template #default="scope">
               {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}
@@ -226,11 +222,12 @@ import { getListBycustomerName } from '@/api/customer/customerFile/customerInfo'
 import { CustomerInfoVO } from '@/api/customer/customerFile/customerInfo/types';
 import { listOrderMain, getOrderMain } from '@/api/order/orderMain';
 import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import { OrderDeliverVO } from '@/api/order/orderDeliver/types';
 import { listComStaff } from '@/api/company/comStaff';
 import { ComStaffVO, ComStaffQuery } from '@/api/company/comStaff/types';
 import OrderMainDrawer from './orderMainDrawer.vue';
 import FileSelector from '@/components/FileSelector/index.vue';
-import { any } from 'vue-types';
+import { getCustomerDeliverOrders } from '@/api/order/orderDeliver';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { statement_status, invoice_issuance_status, payment_status } = toRefs<any>(
@@ -248,8 +245,8 @@ const initFormData: StatementOrderForm = {
   statementSelf: undefined,
   statementSelfPhone: undefined,
   statementStatus: undefined,
-  isPaymentStatus: undefined,
-  isInvoiceStatus: undefined,
+  isPaymentStatus: '1',
+  isInvoiceStatus: '0',
   statementDate: undefined,
   annexAddress: undefined,
   rejectRemark: undefined,
@@ -303,8 +300,8 @@ const staffOptions = ref<ComStaffVO[]>([]);
 const orderMainDrawerRef = ref<any>();
 const fileSelectorRef = ref<any>();
 const fileSelectorVisible = ref(false);
-const currentSelectedOrders = ref<OrderMainVO[]>([]);
-const preloadedOrders = ref<OrderMainVO[]>([]); // 预加载的订单列表
+const currentSelectedOrders = ref<OrderDeliverVO[]>([]);
+const preloadedOrders = ref<OrderDeliverVO[]>([]); // 预加载的订单列表
 
 /** 计算当前页的商品列表 */
 const pagedProductList = computed(() => {
@@ -378,6 +375,9 @@ const reset = () => {
   productPage.pageSize = 10;
   productPage.total = 0;
   customerOptions.value = [];
+  currentSelectedOrders.value = [];
+  preloadedOrders.value = [];
+  preloadedTotal.value = 0;
   formRef.value?.clearValidate();
 };
 
@@ -419,12 +419,7 @@ const handleCustomerChange = async (customerId: string | number) => {
 /** 预加载订单列表 */
 const preloadOrders = async (customerId: string | number) => {
   try {
-    const params: OrderMainQuery = {
-      pageNum: 1,
-      pageSize: 10,
-      customerId: customerId
-    };
-    const res = await listOrderMain(params);
+    const res = await getCustomerDeliverOrders(customerId);
     preloadedOrders.value = res.rows || [];
     preloadedTotal.value = res.total || 0;
   } catch (error) {
@@ -492,10 +487,11 @@ const handleOrderSelected = (data: any) => {
     orders.forEach((order: any) => {
       totalAmount += Number(order.totalAmount || 0);
 
-      const detail: StatementDetailForm = {
+      const detail: any = {
         id: undefined,
         statementOrderId: undefined,
-        orderNo: order.orderNo,
+        orderNo: order.orderCode,
+        deliverCode: order.deliverCode || '',
         orderTime: order.orderTime || '',
         amount: order.totalAmount,
         type: order.orderType || '',
@@ -634,6 +630,7 @@ const handlePreviewFile = (file: any) => {
 /** 提交表单 */
 const handleSubmit = async () => {
   if (!formRef.value) return;
+  console.log(form.value);
 
   await formRef.value.validate(async (valid) => {
     if (valid) {

+ 0 - 5
src/views/bill/statementOrder/detailDrawer.vue

@@ -127,11 +127,6 @@
               {{ scope.row.unitPrice ? Number(scope.row.unitPrice).toFixed(2) : '0.00' }}
             </template>
           </el-table-column>
-          <el-table-column label="金额" width="120" align="center">
-            <template #default="scope">
-              {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}
-            </template>
-          </el-table-column>
           <el-table-column label="小计" width="120" align="center">
             <template #default="scope">
               {{ (Number(scope.row.quantity || 0) * Number(scope.row.unitPrice || 0)).toFixed(2) }}

+ 59 - 33
src/views/bill/statementOrder/index.vue

@@ -75,39 +75,11 @@
 
         <el-table-column label="操作" align="center" width="300" fixed="right">
           <template #default="scope">
-            <el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['bill:statementOrder:edit']">查看</el-button>
-            <el-button
-              link
-              type="primary"
-              @click="handleUpdate(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementOrder:edit']"
-              >编辑</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleSend(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementOrder:edit']"
-              >发送对账单</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleWithdraw(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementOrder:edit']"
-              >撤回</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              @click="handleObsolete(scope.row)"
-              v-if="scope.row.statementStatus != 4"
-              v-hasPermi="['bill:statementOrder:remove']"
-              >作废</el-button
-            >
+            <template v-for="btn in getAvailableButtons(scope.row.statementStatus)" :key="btn.action">
+              <el-button link type="primary" @click="btn.handler(scope.row)" v-hasPermi="[btn.permission]">
+                {{ btn.label }}
+              </el-button>
+            </template>
           </template>
         </el-table-column>
       </el-table>
@@ -195,6 +167,23 @@ const data = reactive<PageData<StatementOrderForm, StatementOrderQuery>>({
 
 const { queryParams, form, rules } = toRefs(data);
 
+// 对账单状态枚举
+enum StatementStatus {
+  DRAFT = 0, // 待确认
+  PENDING = 1, // 待对账
+  CONFIRMED = 2, // 已对账
+  REJECTED = 3, // 已驳回
+  OBSOLETE = 4 // 已作废
+}
+
+// 按钮配置类型
+interface ActionButton {
+  action: string;
+  label: string;
+  handler: (row: StatementOrderVO) => void;
+  permission: string;
+}
+
 /** 查询对账单主列表 */
 const getList = async () => {
   loading.value = true;
@@ -308,6 +297,43 @@ const handleExport = () => {
   );
 };
 
+// 按钮配置映射:状态 -> 可用按钮列表
+const buttonConfigMap: Record<number, ActionButton[]> = {
+  [StatementStatus.DRAFT]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' },
+    { action: 'edit', label: '编辑', handler: handleUpdate, permission: 'bill:statementOrder:edit' },
+    { action: 'send', label: '发送对账单', handler: handleSend, permission: 'bill:statementOrder:edit' },
+    { action: 'withdraw', label: '撤回', handler: handleWithdraw, permission: 'bill:statementOrder:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementOrder:remove' }
+  ],
+  [StatementStatus.PENDING]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' },
+    { action: 'edit', label: '编辑', handler: handleUpdate, permission: 'bill:statementOrder:edit' },
+    { action: 'withdraw', label: '撤回', handler: handleWithdraw, permission: 'bill:statementOrder:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementOrder:remove' }
+  ],
+  [StatementStatus.CONFIRMED]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementOrder:remove' }
+  ],
+  [StatementStatus.REJECTED]: [
+    { action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' },
+    { action: 'edit', label: '编辑', handler: handleUpdate, permission: 'bill:statementOrder:edit' },
+    { action: 'send', label: '发送对账单', handler: handleSend, permission: 'bill:statementOrder:edit' },
+    { action: 'obsolete', label: '作废', handler: handleObsolete, permission: 'bill:statementOrder:remove' }
+  ],
+  [StatementStatus.OBSOLETE]: [{ action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' }]
+};
+
+/**
+ * 根据对账单状态获取可用按钮列表
+ * @param status 对账单状态
+ * @returns 可用按钮配置数组
+ */
+const getAvailableButtons = (status: number): ActionButton[] => {
+  return buttonConfigMap[status] || [{ action: 'detail', label: '查看', handler: handleDetail, permission: 'bill:statementOrder:edit' }];
+};
+
 onMounted(() => {
   getList();
 });

+ 54 - 16
src/views/bill/statementOrder/orderMainDrawer.vue

@@ -4,7 +4,8 @@
     <div class="drawer-content">
       <el-table ref="tableRef" v-loading="loading" :data="orderList" border @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column prop="orderNo" label="订单编号" min-width="150" align="center" />
+        <el-table-column prop="orderCode" label="订单编号" min-width="150" align="center" />
+        <el-table-column prop="deliverCode" label="发货单编号" min-width="150" align="center" />
         <el-table-column prop="totalAmount" label="金额" min-width="100" align="center">
           <template #default="scope">
             {{ scope.row.totalAmount ? Number(scope.row.totalAmount).toFixed(2) : '0.00' }}
@@ -28,7 +29,8 @@
 </template>
 
 <script setup name="OrderMainDrawer" lang="ts">
-import { listOrderMain, getCustomerOrderProductList } from '@/api/order/orderMain';
+import { listOrderMain } from '@/api/order/orderMain';
+import { getCustomerDeliverOrders, getCustomerOrderProductList } from '@/api/order/orderDeliver';
 import { OrderMainVO, OrderMainQuery } from '@/api/order/orderMain/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -46,6 +48,7 @@ const selectedOrders = ref<OrderMainVO[]>([]);
 const mergedProductList = ref<any[]>([]);
 const total = ref(0);
 const tableRef = ref<any>();
+const custId = ref<string | number>();
 
 const queryParams = ref<OrderMainQuery>({
   pageNum: 1,
@@ -61,10 +64,9 @@ const open = async (
   preloadedOrderList?: OrderMainVO[],
   preloadedTotalCount?: number
 ) => {
-  // 先保存预选数据
-  const tempSelectedOrders = preSelectedOrders || [];
-  const tempProductList = preProductList || [];
+  custId.value = customerId;
 
+  // 先重置所有状态(包括表格选中)
   reset();
   queryParams.value.customerId = customerId;
   drawer.visible = true;
@@ -79,31 +81,67 @@ const open = async (
     await getList();
   }
 
-  // 恢复之前选中的订单和产品列表
-  if (tempSelectedOrders.length > 0) {
-    selectedOrders.value = [...tempSelectedOrders];
-    mergedProductList.value = [...tempProductList];
+  // 只有当传入了preSelectedOrders且非空时,才恢复选中状态
+  if (preSelectedOrders && preSelectedOrders.length > 0) {
+    selectedOrders.value = [...preSelectedOrders];
+    mergedProductList.value = preProductList ? [...preProductList] : [];
 
     // 恢复表格选中状态
     await nextTick();
-    restoreSelection(tempSelectedOrders);
+    restoreSelection(preSelectedOrders);
   }
 };
 
 /** 获取订单列表 */
 const getList = async () => {
+  if (!custId.value) {
+    console.error('customerId为空');
+    return;
+  }
+
   loading.value = true;
   try {
-    const res = await listOrderMain(queryParams.value);
-    orderList.value = res.rows || [];
-    total.value = res.total || 0;
+    const res = await getCustomerDeliverOrders(custId.value, {
+      pageNum: queryParams.value.pageNum,
+      pageSize: queryParams.value.pageSize
+    });
+
+    // 解析数据 - 支持多种返回格式
+    let rows: any[] = [];
+    let totalCount = 0;
+
+    if (res.rows) {
+      rows = res.rows;
+      totalCount = res.total || 0;
+    } else if (res.data && res.data.rows) {
+      rows = res.data.rows;
+      totalCount = res.data.total || 0;
+    } else if (res.data && Array.isArray(res.data)) {
+      rows = res.data;
+      totalCount = res.data.length;
+    } else if (Array.isArray(res)) {
+      rows = res;
+      totalCount = res.length;
+    }
+
+    orderList.value = rows;
+    total.value = totalCount;
+
+    // 数据加载完成后,清空表格选中状态(避免自动恢复之前的选中)
+    await nextTick();
+    tableRef.value?.clearSelection();
   } catch (error) {
-    console.error(error);
+    console.error('加载数据失败:', error);
+    orderList.value = [];
+    total.value = 0;
   } finally {
     loading.value = false;
   }
 };
 
+/** 加载数据 */
+const loadData = async () => {};
+
 /** 恢复选中状态 */
 const restoreSelection = (preSelectedOrders: OrderMainVO[]) => {
   if (!tableRef.value || !orderList.value.length) {
@@ -156,13 +194,13 @@ const mergeProductList = async () => {
         productNo: item.productNo || item.skuNo || item.productCode || '',
         itemName: item.productName || item.skuName || item.itemName || item.productFullName || '',
         specifications: item.specifications || item.spec || item.model || item.specModel || '',
-        quantity: item.quantity || item.num || item.orderQuantity,
+        quantity: item.deliverNum,
         unitPrice: item.price || item.unitPrice || item.salePrice || item.orderPrice,
         productUnit: item.productUnit || item.unitName || '',
         subtotal: item.subtotal,
         unitName: item.productUnit || item.unitName || '',
         type: item.productType || item.type || '',
-        orderId: item.orderId,
+        orderId: item.deliverId,
         categoryId: item.categoryId,
         categoryNo: item.categoryNo || '',
         productId: item.productId || item.id,

+ 1 - 1
src/views/order/orderDeliver/index.vue

@@ -76,7 +76,7 @@
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-button link type="primary" @click="handleDeliver(scope.row)">发货</el-button>
+            <el-button link type="primary" v-if="scope.row.orderStatus != '4'" @click="handleDeliver(scope.row)">发货</el-button>
             <el-button link type="primary" @click="handleReview(scope.row)">查看发货信息</el-button>
             <el-button link type="primary">取消订单</el-button>
           </template>

+ 15 - 1
src/views/order/orderMain/components/chooseAddress.vue

@@ -1,6 +1,13 @@
 <template>
   <el-dialog v-model="visible" title="选择地址" width="800px" @close="handleClose">
-    <el-table :data="addressList" border style="width: 100%" highlight-current-row @current-change="handleCurrentChange">
+    <el-table
+      :data="addressList"
+      border
+      style="width: 100%"
+      highlight-current-row
+      @current-change="handleCurrentChange"
+      @row-dblclick="handleRowDblClick"
+    >
       <el-table-column label="选择" width="80" align="center">
         <template #default="scope">
           <el-radio v-model="selectedAddressId" :value="scope.row.id">
@@ -71,6 +78,13 @@ const handleCurrentChange = (row: ShippingAddressVO | null) => {
   }
 };
 
+// 双击行直接确认
+const handleRowDblClick = (row: ShippingAddressVO) => {
+  selectedAddress.value = row;
+  selectedAddressId.value = row.id;
+  handleConfirm();
+};
+
 // 关闭对话框
 const handleClose = () => {
   emit('update:modelValue', false);

+ 39 - 3
src/views/order/orderMain/index.vue

@@ -165,9 +165,15 @@
           <!-- 第八行 -->
           <el-col :span="24">
             <el-form-item label="附件" prop="attachmentPath">
-              <el-upload class="upload-demo" action="#" :auto-upload="false">
-                <el-button type="primary" plain>上传附件</el-button>
-              </el-upload>
+              <div class="attachment-upload">
+                <el-button type="primary" plain @click="showFileSelectorDialog = true">选择附件</el-button>
+                <span v-if="attachmentList.length > 0" class="ml-2">已选择 {{ attachmentList.length }} 个文件</span>
+                <div v-if="attachmentList.length > 0" class="attachment-list mt-2">
+                  <el-tag v-for="(file, index) in attachmentList" :key="index" closable @close="removeAttachment(index)" class="mr-2 mb-2">
+                    {{ file.fileName }}
+                  </el-tag>
+                </div>
+              </div>
             </el-form-item>
           </el-col>
         </el-row>
@@ -314,12 +320,16 @@
 
     <!-- 查询商品明细对话框 -->
     <SelectProductDetail v-model="showProductDetailDialog" :product-data="currentProductDetail" />
+
+    <!-- 文件选择器对话框 -->
+    <FileSelector v-model="showFileSelectorDialog" :multiple="true" :allowed-types="[1, 2, 3, 4, 5]" title="选择附件" @confirm="handleFileConfirm" />
   </div>
 </template>
 
 <script setup name="OrderMain" lang="ts">
 import { listOrderMain, getOrderMain, delOrderMain, addOrderMain, updateOrderMain } from '@/api/order/orderMain';
 import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import FileSelector from '@/components/FileSelector/index.vue';
 import { listCompany } from '@/api/company/company';
 import { listCustomerDept } from '@/api/system/dept';
 import { CompanyVO } from '@/api/company/company/types';
@@ -373,6 +383,11 @@ const showProductDialog = ref(false);
 const showProductDetailDialog = ref(false);
 const currentProductDetail = ref({});
 
+// 文件选择器对话框
+const showFileSelectorDialog = ref(false);
+// 附件列表
+const attachmentList = ref<any[]>([]);
+
 // 计算商品总数(所有商品的数量之和)
 const totalQuantity = computed(() => {
   return productList.value.reduce((sum, item) => {
@@ -733,6 +748,12 @@ const handleAddProduct = () => {
 
 /** 确认选择商品 */
 const handleProductConfirm = (product: any) => {
+  // 检查商品是否已存在
+  const existingProduct = productList.value.find((item) => item.id === product.id);
+  if (existingProduct) {
+    proxy?.$modal.msgWarning('该商品已存在,请勿重复添加');
+    return;
+  }
   // 将商品添加到商品列表,按照新的字段映射
   const newProduct = {
     id: product.id,
@@ -759,6 +780,21 @@ const handleDeleteProduct = (index: number) => {
   proxy?.$modal.msgSuccess('删除成功');
 };
 
+/** 确认选择文件 */
+const handleFileConfirm = (files: any[]) => {
+  attachmentList.value = files;
+  // 将文件路径拼接成字符串保存到form.attachmentPath
+  form.value.attachmentPath = files.map((file) => file.filePath).join(',');
+  proxy?.$modal.msgSuccess(`成功选择${files.length}个附件`);
+};
+
+/** 删除附件 */
+const removeAttachment = (index: number) => {
+  attachmentList.value.splice(index, 1);
+  // 更新form.attachmentPath
+  form.value.attachmentPath = attachmentList.value.map((file) => file.filePath).join(',');
+};
+
 /** 查询商品明细 */
 const handleSelect = (index: number) => {
   if (form.value.warehouseId === undefined) {

+ 4 - 1
src/views/order/saleOrder/deliverDialog.vue

@@ -69,6 +69,7 @@
       <el-table-column prop="categoryName" label="类别" width="120" />
       <el-table-column prop="productUnit" label="单位" width="80" />
       <el-table-column prop="orderQuantity" label="商品总数" width="100" />
+      <el-table-column prop="orderPrice" label="商品单价" width="100" />
       <el-table-column prop="quantitySent" label="已发货数量" width="100" />
       <el-table-column prop="unsentQuantity" label="未发货数量" width="100" />
       <el-table-column label="发货数量">
@@ -262,6 +263,7 @@ const loadProductList = async () => {
       deliverNum: 0,
       productNo: item.productNo,
       productId: item.productId,
+      orderPrice: item.orderPrice,
       productUnit: item.productUnit,
       productUnitId: item.productUnitId
     }));
@@ -359,7 +361,8 @@ const handleSubmit = async () => {
         productName: item.productName,
         productUnitId: item.productUnitId,
         productUnit: item.productUnit,
-        deliverNum: item.deliverNum
+        deliverNum: item.deliverNum,
+        orderPrice: item.orderPrice
       }))
     };
 

+ 74 - 20
src/views/order/saleOrder/index.vue

@@ -118,26 +118,9 @@
 
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-button link type="primary" v-if="scope.row.orderStatus === '0'" @click="handleReview(scope.row)">查看</el-button>
-            <el-button link type="primary" v-if="scope.row.checkStatus === '0'" @click="handleCheck(scope.row)">审核</el-button>
-            <el-button link type="primary" v-if="scope.row.orderStatus === '2' || scope.row.orderStatus === '3'" @click="handleDeliver(scope.row)"
-              >发货</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              v-if="scope.row.orderStatus === '2' || scope.row.orderStatus === '3' || scope.row.orderStatus === '4' || scope.row.orderStatus === '5'"
-              @click="handleReview(scope.row)"
-              >查看订单信息</el-button
-            >
-            <el-button
-              link
-              type="primary"
-              v-if="scope.row.orderStatus === '4' || scope.row.orderStatus === '5'"
-              @click="handleViewLogistics(scope.row)"
-              >查看物流</el-button
-            >
-            <el-button link type="primary" @click="handleCancel(scope.row)" v-if="scope.row.orderStatus != '7'">取消订单</el-button>
+            <template v-for="btn in getActionButtons(scope.row)" :key="btn.label">
+              <el-button link type="primary" @click="btn.handler(scope.row)">{{ btn.label }}</el-button>
+            </template>
           </template>
         </el-table-column>
       </el-table>
@@ -565,6 +548,77 @@ const handleCloseOrder = async (row?: OrderMainVO) => {
   await getList();
 };
 
+// 订单状态枚举
+enum OrderStatus {
+  PENDING_PAYMENT = '0', // 待支付
+  PENDING_CONFIRM = '1', // 待确认
+  PENDING_SHIPMENT = '2', // 待发货
+  PARTIAL_SHIPMENT = '3', // 部分发货
+  SHIPMENT_COMPLETED = '4', // 发货完成
+  COMPLETED = '5', // 已完成
+  CLOSED = '6', // 已关闭
+  CANCELLED = '7' // 已取消
+}
+
+// 审核状态枚举
+enum CheckStatus {
+  PENDING = '0', // 待审核
+  APPROVED = '1', // 审核通过
+  REJECTED = '2' // 已驳回
+}
+
+// 按钮配置类型
+interface ActionButton {
+  label: string;
+  handler: (row: OrderMainVO) => void;
+}
+
+// 按钮配置映射:根据订单状态和审核状态返回可用按钮
+const getButtonsByStatus = (orderStatus: string, checkStatus: string): ActionButton[] => {
+  const buttons: ActionButton[] = [];
+
+  // 待支付状态:显示查看按钮
+  if (orderStatus === OrderStatus.PENDING_PAYMENT) {
+    buttons.push({ label: '查看', handler: handleReview });
+  }
+
+  // 待审核:显示审核按钮
+  if (checkStatus === CheckStatus.PENDING) {
+    buttons.push({ label: '审核', handler: handleCheck });
+  }
+
+  // 待发货或部分发货:显示发货按钮
+  if (orderStatus === OrderStatus.PENDING_SHIPMENT || orderStatus === OrderStatus.PARTIAL_SHIPMENT) {
+    buttons.push({ label: '发货', handler: handleDeliver });
+  }
+
+  // 待发货、部分发货、发货完成、已完成:显示查看订单信息按钮
+  if (
+    [OrderStatus.PENDING_SHIPMENT, OrderStatus.PARTIAL_SHIPMENT, OrderStatus.SHIPMENT_COMPLETED, OrderStatus.COMPLETED].includes(
+      orderStatus as OrderStatus
+    )
+  ) {
+    buttons.push({ label: '查看订单信息', handler: handleReview });
+  }
+
+  // 发货完成或已完成:显示查看物流按钮
+  if (orderStatus === OrderStatus.SHIPMENT_COMPLETED || orderStatus === OrderStatus.COMPLETED) {
+    buttons.push({ label: '查看物流', handler: handleViewLogistics });
+  }
+
+  // 非已取消和已关闭状态:显示取消订单按钮
+  if (orderStatus !== OrderStatus.CANCELLED && orderStatus !== OrderStatus.CLOSED) {
+    buttons.push({ label: '取消订单', handler: handleCancel });
+  }
+
+  return buttons;
+};
+
+// 根据订单状态获取可用的操作按钮
+const getActionButtons = (row: OrderMainVO): ActionButton[] => {
+  return getButtonsByStatus(row.orderStatus, row.checkStatus);
+};
+
 /** 导出按钮操作 */
 const handleExport = () => {
   proxy?.download(