hurx hace 3 semanas
padre
commit
64a9ef3d23

+ 50 - 55
src/views/bill/statementInvoice/addInvoiceDialog.vue

@@ -52,29 +52,22 @@
 
       <el-row :gutter="20">
         <el-col :span="24">
-          <el-form-item label="发票附件" prop="invoiceAttachment">
-            <el-button type="primary" size="small" @click="handleOpenFileSelector">
-              <el-icon><Upload /></el-icon>
-              点击上传
-            </el-button>
-            <div style="color: #999; font-size: 12px; margin-top: 5px">支持jpg/png/xlsx等文件</div>
-          </el-form-item>
-        </el-col>
-      </el-row>
-
-      <!-- 附件列表 -->
-      <el-row :gutter="20" v-if="fileList.length > 0">
-        <el-col :span="24">
-          <el-table :data="fileList" border style="width: 100%; margin-top: 10px">
-            <el-table-column type="index" label="序号" width="60" align="center" />
-            <el-table-column prop="name" label="附件名称" min-width="200" align="center" />
-            <el-table-column label="操作" width="150" align="center">
-              <template #default="scope">
-                <el-button link type="primary" size="small" @click="handlePreviewFile(scope.row)">预览</el-button>
-                <el-button link type="danger" size="small" @click="handleRemoveFile(scope.$index)">删除</el-button>
+          <el-form-item label="发票附件" prop="invoiceAnnex">
+            <el-upload
+              :action="uploadAction"
+              :on-success="handleUploadSuccess"
+              :before-upload="beforeUpload"
+              :on-remove="handleRemoveUploadFile"
+              :on-preview="handlePreviewUploadFile"
+              :file-list="fileList"
+              multiple
+            >
+              <el-button type="primary" icon="Upload">点击上传</el-button>
+              <template #tip>
+                <div class="el-upload__tip">支持jpg/png/xlsx等文件,单个文件不超过50MB</div>
               </template>
-            </el-table-column>
-          </el-table>
+            </el-upload>
+          </el-form-item>
         </el-col>
       </el-row>
     </el-form>
@@ -86,15 +79,9 @@
       </div>
     </template>
   </el-dialog>
-
-  <!-- 文件选择器 -->
-  <FileSelector v-model="fileSelectorVisible" :multiple="true" :allowed-types="[1, 2, 3, 4, 5]" title="选择发票附件" @confirm="handleFileSelected" />
 </template>
 
 <script setup name="AddInvoiceDialog" lang="ts">
-import { Upload } from '@element-plus/icons-vue';
-import FileSelector from '@/components/FileSelector/index.vue';
-
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { invoice_type } = toRefs<any>(proxy?.useDict('invoice_type'));
 interface InvoiceForm {
@@ -104,7 +91,7 @@ interface InvoiceForm {
   invoiceAmount?: number;
   invoiceDate?: string;
   remark?: string;
-  invoiceAttachment?: string;
+  invoiceAnnex?: string;
 }
 
 const initFormData: InvoiceForm = {
@@ -114,14 +101,14 @@ const initFormData: InvoiceForm = {
   invoiceAmount: undefined,
   remark: undefined,
   invoiceDate: undefined,
-  invoiceAttachment: undefined
+  invoiceAnnex: undefined
 };
 
 const formRef = ref<ElFormInstance>();
 const buttonLoading = ref(false);
 const form = ref<InvoiceForm>({ ...initFormData });
 const fileList = ref<any[]>([]);
-const fileSelectorVisible = ref(false);
+const uploadAction = import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload';
 
 const dialog = reactive<DialogOption>({
   visible: false,
@@ -152,14 +139,15 @@ const open = (data?: InvoiceForm) => {
     Object.assign(form.value, data);
 
     // 解析附件地址并回显附件列表
-    if (data.invoiceAttachment) {
-      const urls = data.invoiceAttachment.split(',').filter((url) => url.trim());
+    if (data.invoiceAnnex) {
+      const urls = data.invoiceAnnex.split(',').filter((url) => url.trim());
       fileList.value = urls.map((url, index) => {
         const fileName = url.split('/').pop() || `附件${index + 1}`;
         return {
           name: fileName,
           url: url.trim(),
-          id: undefined
+          uid: Date.now() + index,
+          status: 'success'
         };
       });
     }
@@ -175,39 +163,46 @@ const reset = () => {
   formRef.value?.clearValidate();
 };
 
-/** 打开文件选择器 */
-const handleOpenFileSelector = () => {
-  fileSelectorVisible.value = true;
+/** 上传前校验 */
+const beforeUpload = (file: any) => {
+  const isLt50M = file.size / 1024 / 1024 < 50;
+  if (!isLt50M) {
+    proxy?.$modal.msgWarning('上传文件大小不能超过 50MB!');
+  }
+  return isLt50M;
 };
 
-/** 文件选择完成 */
-const handleFileSelected = (files: any[]) => {
-  if (files && files.length > 0) {
-    files.forEach((file) => {
-      fileList.value.push({
-        name: file.fileName || file.name,
-        url: file.fileUrl || file.url,
-        id: file.id
-      });
+/** 上传成功回调 */
+const handleUploadSuccess = (response: any, uploadFile: any) => {
+  if (response.code === 200) {
+    uploadFile.url = response.data.url;
+    nextTick(() => {
+      form.value.invoiceAnnex = fileList.value
+        .map((f) => f.url)
+        .filter(Boolean)
+        .join(',');
     });
-    form.value.invoiceAttachment = fileList.value.map((f) => f.url || f.name).join(',');
+    proxy?.$modal.msgSuccess('上传成功');
+  } else {
+    proxy?.$modal.msgError(response.msg || '上传失败');
   }
-  fileSelectorVisible.value = false;
 };
 
 /** 删除文件 */
-const handleRemoveFile = (index: number) => {
-  fileList.value.splice(index, 1);
-  form.value.invoiceAttachment = fileList.value.map((f) => f.url || f.name).join(',');
+const handleRemoveUploadFile = (uploadFile: any) => {
+  form.value.invoiceAnnex = fileList.value
+    .map((f) => f.url)
+    .filter(Boolean)
+    .join(',');
 };
 
 /** 预览文件 */
-const handlePreviewFile = (file: any) => {
-  if (!file.url) {
+const handlePreviewUploadFile = (uploadFile: any) => {
+  if (uploadFile.url) {
+    window.open(uploadFile.url, '_blank');
+  } else {
     proxy?.$modal.msgWarning('文件地址不存在');
-    return;
   }
-  window.open(file.url, '_blank');
 };
 
 /** 提交表单 */

+ 43 - 39
src/views/bill/statementOrder/addDrawer.vue

@@ -173,9 +173,16 @@
           <span style="color: #409eff; font-weight: 600">对账附件</span>
         </el-divider>
 
-        <div style="margin-bottom: 10px">
-          <el-button type="primary" icon="Upload" @click="handleOpenFileSelector">点击上传</el-button>
-        </div>
+        <el-upload
+          :action="uploadAction"
+          :on-success="handleUploadSuccess"
+          :before-upload="beforeUpload"
+          :show-file-list="false"
+          multiple
+          style="margin-bottom: 10px"
+        >
+          <el-button type="primary" icon="Upload">点击上传</el-button>
+        </el-upload>
 
         <el-table :data="fileList" border style="width: 100%; margin-bottom: 20px">
           <el-table-column type="index" label="序号" width="80" align="center" />
@@ -185,10 +192,11 @@
               {{ scope.row.url || '暂无地址' }}
             </template>
           </el-table-column>
-          <el-table-column label="操作" width="200" align="center">
+          <el-table-column label="操作" width="250" align="center">
             <template #default="scope">
               <el-button type="primary" link @click="handleDownloadFile(scope.row)">下载</el-button>
               <el-button type="primary" link @click="handlePreviewFile(scope.row)">预览</el-button>
+              <el-button type="danger" link @click="handleRemoveFile(scope.$index)">删除</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -209,9 +217,6 @@
 
   <!-- 客户订单抽屉 -->
   <OrderMainDrawer ref="orderMainDrawerRef" @success="handleOrderSelected" />
-
-  <!-- 文件选择器 -->
-  <FileSelector v-model="fileSelectorVisible" :multiple="true" :allowed-types="[1, 2, 3, 4, 5]" title="选择对账附件" @confirm="handleFileSelected" />
 </template>
 
 <script setup name="AddDrawer" lang="ts">
@@ -226,7 +231,6 @@ 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 { getCustomerDeliverOrders } from '@/api/order/orderDeliver';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -298,8 +302,7 @@ const customerLoading = ref(false);
 const customerOptions = ref<CustomerInfoVO[]>([]);
 const staffOptions = ref<ComStaffVO[]>([]);
 const orderMainDrawerRef = ref<any>();
-const fileSelectorRef = ref<any>();
-const fileSelectorVisible = ref(false);
+const uploadAction = import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload';
 const currentSelectedOrders = ref<OrderDeliverVO[]>([]);
 const preloadedOrders = ref<OrderDeliverVO[]>([]); // 预加载的订单列表
 
@@ -542,41 +545,42 @@ const handleProductCurrentChange = (val: number) => {
   productPage.pageNum = val;
 };
 
-/** 文件上传改变 */
-const handleFileChange = (file: any, uploadFileList: any[]) => {
-  // 更新文件列表
-  fileList.value = uploadFileList;
-  // 更新表单中的附件地址
-  form.value.annexAddress = uploadFileList.map((f) => f.name).join(',');
+/** 上传前校验 */
+const beforeUpload = (file: any) => {
+  const isLt50M = file.size / 1024 / 1024 < 50;
+  if (!isLt50M) {
+    proxy?.$modal.msgWarning('上传文件大小不能超过 50MB!');
+  }
+  return isLt50M;
+};
+
+/** 上传成功回调 */
+const handleUploadSuccess = (response: any, file: any) => {
+  if (response.code === 200) {
+    fileList.value.push({
+      name: file.name,
+      url: response.data.url,
+      id: undefined
+    });
+    // 更新表单中的附件地址
+    form.value.annexAddress = fileList.value
+      .map((f) => f.url)
+      .filter(Boolean)
+      .join(',');
+    proxy?.$modal.msgSuccess('上传成功');
+  } else {
+    proxy?.$modal.msgError(response.msg || '上传失败');
+  }
 };
 
 /** 删除文件 */
 const handleRemoveFile = (index: number) => {
   fileList.value.splice(index, 1);
   // 更新表单中的附件地址
-  form.value.annexAddress = fileList.value.map((f) => f.name).join(',');
-};
-
-/** 打开文件选择器 */
-const handleOpenFileSelector = () => {
-  fileSelectorVisible.value = true;
-};
-
-/** 处理文件选择完成 */
-const handleFileSelected = (files: any[]) => {
-  if (files && files.length > 0) {
-    // 将选中的文件添加到文件列表
-    files.forEach((file) => {
-      fileList.value.push({
-        name: file.fileName || file.name,
-        url: file.fileUrl || file.url,
-        id: file.id
-      });
-    });
-    // 更新表单中的附件地址
-    form.value.annexAddress = fileList.value.map((f) => f.url || f.name).join(',');
-  }
-  fileSelectorVisible.value = false;
+  form.value.annexAddress = fileList.value
+    .map((f) => f.url)
+    .filter(Boolean)
+    .join(',');
 };
 
 /** 下载文件 */

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

@@ -623,7 +623,7 @@ const getButtonsByStatus = (orderStatus: string, checkStatus: string): ActionBut
   }
 
   // 发货完成或已完成:显示查看物流按钮
-  if (orderStatus === OrderStatus.SHIPMENT_COMPLETED || orderStatus === OrderStatus.COMPLETED) {
+  if (orderStatus === OrderStatus.PARTIAL_SHIPMENT || orderStatus === OrderStatus.SHIPMENT_COMPLETED || orderStatus === OrderStatus.COMPLETED) {
     buttons.push({ label: '查看物流', handler: handleViewLogistics });
   }
 

+ 27 - 4
src/views/order/saleOrder/sendDetail.vue

@@ -160,12 +160,12 @@
       <template #header>
         <div class="card-header">
           <span>发货信息:共{{ orderDeliverList.length }}个包裹</span>
-          <el-button type="primary" style="float: right" @click="handleAddDeliver(orderDetail)">添加发货信息</el-button>
+          <el-button type="primary" @click="handleAddDeliver(orderDetail)">添加发货信息</el-button>
         </div>
       </template>
       <div v-for="deliver in orderDeliverList" :key="deliver.id" class="mb-4">
         <div style="white-space: nowrap" class="mb-2">
-          <span style="margin-right: 16px">发货单号:{{ deliver.orderCode || '--' }}</span>
+          <span style="margin-right: 16px">发货单号:{{ (deliver as any).deliverCode || '--' }}</span>
           <span style="margin-right: 16px">发货时间:{{ (deliver as any).createTime || '--' }}</span>
           <span style="margin-right: 16px">发货方式:{{ getDictLabel(deliver_method, deliver.deliverMethod || '--') }}</span>
           <span style="margin-right: 16px">送货人:{{ deliver.deliverMan || '--' }}</span>
@@ -173,7 +173,7 @@
           <span style="margin-right: 16px">物流状态:{{ deliver.logisticsStatus || '--' }}</span>
           <span>发货备注:{{ deliver.deliverRemark || '--' }}</span>
         </div>
-        <el-table :data="deliverProductList" border style="width: 100%">
+        <el-table :data="deliver.deliverProductList" border style="width: 100%">
           <el-table-column label="产品编号" prop="productNo" align="center" />
           <el-table-column label="商品名称" prop="productName" align="center" />
           <el-table-column label="单位" prop="productUnit" align="center" />
@@ -221,6 +221,7 @@ import { OrderProductVO } from '@/api/order/orderProduct/types';
 import { DeliverProductVO } from '@/api/order/deliverProduct/types';
 import { listOrderDeliver } from '@/api/order/orderDeliver';
 import { OrderDeliverVO } from '@/api/order/orderDeliver/types';
+import { listDeliverProduct } from '@/api/order/deliverProduct';
 import { getShippingAddress } from '@/api/customer/customerFile/shippingAddress';
 import { ShippingAddressVO } from '@/api/customer/customerFile/shippingAddress/types';
 import { getWarehouse } from '@/api/company/warehouse';
@@ -380,7 +381,22 @@ const getDeliverProductList = async (orderDetail: OrderMainVO) => {
 const getOrderDeliverListData = async (orderId: string | number) => {
   try {
     const res = await listOrderDeliver({ orderId, pageNum: 1, pageSize: 100 });
-    orderDeliverList.value = (res as any).rows || res.data || [];
+    const deliverList = (res as any).rows || res.data || [];
+
+    // 为每条发货记录获取商品明细
+    for (const deliver of deliverList) {
+      if (deliver.id) {
+        try {
+          const productRes = await listDeliverProduct({ deliverId: deliver.id, pageNum: 1, pageSize: 100 });
+          deliver.deliverProductList = (productRes as any).rows || productRes.data || [];
+        } catch (error) {
+          console.error(`获取发货单${deliver.id}的商品明细失败:`, error);
+          deliver.deliverProductList = [];
+        }
+      }
+    }
+
+    orderDeliverList.value = deliverList;
   } catch (error) {
     console.error('获取发货单列表失败:', error);
   }
@@ -515,6 +531,13 @@ onMounted(() => {
   flex: 1;
 }
 
+.card-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  min-height: 40px;
+}
+
 @media print {
   .el-button {
     display: none;