Răsfoiți Sursa

feat(order): 添加订单发货管理功能

- 新增一键确认订单、导入发货数据、导出发货信息等API接口
- 在销售订单页面添加批量确认订单、导入发货、导出发货单按钮
- 实现导入发货对话框组件,支持文件上传和模板下载
- 完善物流详情查询,增加物流公司编码和收货人手机号参数
- 修复订单确认页面扩展信息查询逻辑错误
- 更新订单状态日志类型定义,添加承运物流公司编码字段
肖路 1 săptămână în urmă
părinte
comite
c3a826c769

+ 49 - 0
src/api/order/orderMainCrrcExt/index.ts

@@ -72,3 +72,52 @@ export const exportOrderMainCrrcExt = (query?: OrderMainCrrcExtQuery) => {
     params: query
   });
 };
+
+/**
+ * 一键确定订单
+ * @param orderIds 订单ID列表,多个用逗号分隔
+ */
+export const oneKeyConfirmOrder = (orderIds: string) => {
+  return request({
+    url: '/order/mainCrrcExt/oneKeyConfirmOrder/' + orderIds,
+    method: 'post'
+  });
+};
+
+/**
+ * 导入订单发货数据
+ * @param file 导入文件
+ */
+export const importDeliverData = (file: File) => {
+  const formData = new FormData();
+  formData.append('file', file);
+  return request({
+    url: '/order/mainCrrcExt/importDeliverData',
+    method: 'post',
+    data: formData,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  });
+};
+
+/**
+ * 获取订单发货导入模板
+ */
+export const importDeliverTemplate = () => {
+  return request({
+    url: '/order/mainCrrcExt/importDeliverTemplate',
+    method: 'post',
+    responseType: 'blob'
+  });
+};
+/**
+ * 导出发货信息
+ */
+export const exportOrderDeliverInfo = () => {
+  return request({
+    url: '/order/mainCrrcExt/exportOrderDeliverInfo',
+    method: 'post',
+    responseType: 'blob'
+  });
+};

+ 10 - 0
src/api/order/orderStatusLog/types.ts

@@ -125,6 +125,11 @@ export interface OrderStatusLogForm extends BaseEntity {
    */
   logisticNos?: string;
 
+  /**
+   * 承运物流公司编码
+   */
+  logisticsCompanyCode?: string;
+
   /**
    * 下一审批人
    */
@@ -192,6 +197,11 @@ export interface OrderStatusLogQuery extends PageQuery {
    */
   logisticNos?: string;
 
+  /**
+   * 承运物流公司编码
+   */
+  logisticsCompanyCode?: string;
+
   /**
    * 下一审批人
    */

+ 127 - 0
src/views/order/saleOrder/index.vue

@@ -51,6 +51,9 @@
           <span style="font-size: 16px; font-weight: 500">销售订单信息列表</span>
 
           <div style="display: flex; flex-wrap: nowrap; gap: 10px">
+            <el-button type="primary" @click="handleBatchConfirm()" :disabled="!ids.length" plain>批量确认订单</el-button>
+            <el-button type="primary" @click="showImportDialog = true" plain>导入发货</el-button>
+            <el-button type="primary" @click="handleExportDeliver()" :loading="exportDeliverLoading" plain>导出发货单</el-button>
             <el-button type="primary" @click="handleCloseOrder()" :disabled="!ids.length" plain>关闭订单</el-button>
             <el-button type="primary" @click="handleDelete()" :disabled="!ids.length" plain>删除订单</el-button>
             <el-button type="primary" :disabled="!ids.length" plain>导出订单</el-button>
@@ -139,6 +142,32 @@
 
     <!-- 物流详情对话框 -->
     <LogisticsDetail v-model="showLogisticsDialog" :order-id="logisticsOrderId" />
+
+    <!-- 导入发货对话框 -->
+    <el-dialog v-model="showImportDialog" title="导入订单发货数据" width="500px" append-to-body>
+      <div style="margin-bottom: 16px">
+        <el-button type="primary" link @click="handleDownloadTemplate">下载导入模板</el-button>
+      </div>
+      <el-upload
+        ref="uploadRef"
+        :auto-upload="false"
+        :limit="1"
+        :on-change="handleImportFileChange"
+        :on-exceed="handleImportExceed"
+        accept=".xlsx,.xls"
+        drag
+      >
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+        <template #tip>
+          <div class="el-upload__tip">仅允许上传 .xlsx / .xls 格式文件</div>
+        </template>
+      </el-upload>
+      <template #footer>
+        <el-button @click="showImportDialog = false">取消</el-button>
+        <el-button type="primary" :loading="importLoading" @click="handleImportSubmit">确认导入</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -155,6 +184,7 @@ import {
   changeCheckStatus
 } from '@/api/order/orderMain';
 import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import { oneKeyConfirmOrder, importDeliverData, importDeliverTemplate, exportOrderDeliverInfo } from '@/api/order/orderMainCrrcExt';
 import DeliverDialog from './deliverDialog.vue';
 import LogisticsDetail from './logisticsDetail.vue';
 
@@ -185,6 +215,15 @@ const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
 const showLogisticsDialog = ref(false);
 const logisticsOrderId = ref<string | number>();
 
+// 导入发货对话框
+const showImportDialog = ref(false);
+const importFileList = ref<any[]>([]);
+const importLoading = ref(false);
+const uploadRef = ref();
+
+// 导出发货单加载状态
+const exportDeliverLoading = ref(false);
+
 const dialog = reactive<DialogOption>({
   visible: false,
   title: ''
@@ -648,6 +687,94 @@ const handleExport = () => {
   );
 };
 
+/** 批量确认订单 */
+const handleBatchConfirm = async () => {
+  if (!ids.value.length) {
+    proxy?.$modal.msgWarning('请先选择需要确认的订单');
+    return;
+  }
+  await proxy?.$modal.confirm('是否确认批量确认选中的 ' + ids.value.length + ' 条订单?');
+  try {
+    loading.value = true;
+    await oneKeyConfirmOrder(ids.value.join(','));
+    proxy?.$modal.msgSuccess('批量确认成功');
+    await getList();
+  } catch (error) {
+    console.error('批量确认订单失败:', error);
+  } finally {
+    loading.value = false;
+  }
+};
+
+/** 下载导入模板 */
+const handleDownloadTemplate = async () => {
+  try {
+    const res = await importDeliverTemplate();
+    const blob = new Blob([res as any], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = '订单发货导入模板.xlsx';
+    link.click();
+    window.URL.revokeObjectURL(url);
+  } catch (error) {
+    proxy?.$modal.msgError('下载模板失败');
+  }
+};
+
+/** 导入文件变更 */
+const handleImportFileChange = (file: any) => {
+  importFileList.value = [file];
+};
+
+/** 超出文件数量限制 */
+const handleImportExceed = () => {
+  proxy?.$modal.msgWarning('只能上传一个文件,请先移除已有文件');
+};
+
+/** 导出发货单 */
+const handleExportDeliver = async () => {
+  try {
+    exportDeliverLoading.value = true;
+    const res = await exportOrderDeliverInfo();
+    const blob = new Blob([res as any], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = `发货单_${new Date().getTime()}.xlsx`;
+    link.click();
+    window.URL.revokeObjectURL(url);
+    proxy?.$modal.msgSuccess('导出成功');
+  } catch (error) {
+    console.error('导出发货单失败:', error);
+    proxy?.$modal.msgError('导出发货单失败');
+  } finally {
+    exportDeliverLoading.value = false;
+  }
+};
+
+/** 确认导入发货数据 */
+const handleImportSubmit = async () => {
+  if (!importFileList.value.length) {
+    proxy?.$modal.msgWarning('请先选择要导入的文件');
+    return;
+  }
+  try {
+    importLoading.value = true;
+    const file = importFileList.value[0].raw;
+    const res = await importDeliverData(file);
+    proxy?.$modal.msgSuccess(res.msg || '导入成功');
+    showImportDialog.value = false;
+    importFileList.value = [];
+    uploadRef.value?.clearFiles();
+    await getList();
+  } catch (error) {
+    console.error('导入发货数据失败:', error);
+  } finally {
+    importLoading.value = false;
+  }
+};
+
 onMounted(() => {
   getList();
 });

+ 4 - 0
src/views/order/saleOrder/logisticsDetail.vue

@@ -124,6 +124,9 @@ const handleLogisticNoChange = async (logisticNo: string) => {
     if (selected) {
       const res = await queryTrack({
         logisticNo: logisticNo,
+        logisticsCompanyCode: selected.logisticsCompanyCode,
+        //先使用送货人手机号其实应该是收货人手机号
+        phone: selected.consigneePhone,
         pageNum: 1,
         pageSize: 100
       });
@@ -150,6 +153,7 @@ const handleLogisticNoChange = async (logisticNo: string) => {
       await listOrderStatusLog({
         orderId: props.orderId,
         logisticNos: form.value.selectedLogisticNo,
+        logisticsCompanyCode: selected?.logisticsCompanyCode,
         pageNum: 1,
         pageSize: 100
       }).then((res) => {

+ 2 - 2
src/views/order/saleOrder/orderAffirm.vue

@@ -443,14 +443,14 @@ const getOrderDetail = async (orderId: string | number) => {
     //如果data.parentOrderId存在,则使用data.parentOrderId查询,否则使用data.id查询
     if (data?.parentOrderId) {
       try {
-        const extRes = await getOrderMainCrrcExt(orderDetail.value.parentOrderId);
+        const extRes = await getOrderMainCrrcExt(data.parentOrderId);
         crrcExtInfo.value = extRes.data || ({} as OrderMainCrrcExtVO);
       } catch (error) {
         console.error('获取中车订单扩展信息失败:', error);
       }
     } else if (data?.id) {
       try {
-        const extRes = await getOrderMainCrrcExt(orderDetail.value.parentOrderId);
+        const extRes = await getOrderMainCrrcExt(data.id);
         crrcExtInfo.value = extRes.data || ({} as OrderMainCrrcExtVO);
       } catch (error) {
         console.error('获取中车订单扩展信息失败:', error);