src/api/productionManagement/processRoute.js
@@ -12,7 +12,7 @@ export function add(data) { return request({ url: "/technologyRouting", url: "/technologyRouting/addTechRoute", method: "post", data: data, }); @@ -34,7 +34,7 @@ export function update(data) { return request({ url: "/technologyRouting", url: "/technologyRouting/editTechRoute", method: "put", data: data, }); src/api/productionManagement/processRouteItem.js
@@ -82,3 +82,11 @@ data: data, }); } // 按工艺路线工序同步工序参数-生产订单 export function syncProcessParamItemOrder(data) { return request({ url: "/productionOrderRoutingOperationParam/sync", method: "post", data: data, }); } src/api/productionManagement/productProcessRoute.js
@@ -4,7 +4,7 @@ // 列表查询 export function findProductProcessRouteItemList(query) { return request({ url: "/productProcessRoute/list", url: "/productionOrderRouting/list", method: "get", params: query, }); @@ -12,7 +12,7 @@ export function addOrUpdateProductProcessRouteItem(data) { return request({ url: "/productProcessRoute/updateRouteItem", url: "/productionOrderRouting/updateRouteItem", method: "post", data: data, }); @@ -21,7 +21,7 @@ // 生产订单下:新增工艺路线项目 export function addRouteItem(data) { return request({ url: "/productProcessRoute/addRouteItem", url: "/productionOrderRouting/addRouteItem", method: "post", data, }); @@ -30,7 +30,7 @@ // 获取生产订单关联的工艺路线主信息 export function listMain(orderId) { return request({ url: "/productProcessRoute/listMain", url: "/productionOrderRouting/listMain", method: "get", params: { orderId }, }); @@ -39,7 +39,7 @@ // 删除工艺路线项目(路由后拼接 id) export function deleteRouteItem(id) { return request({ url: `/productProcessRoute/deleteRouteItem/${id}`, url: `/productionOrderRouting/deleteRouteItem/${id}`, method: "delete", }); } @@ -47,7 +47,7 @@ // 生产订单下:排序工艺路线项目 export function sortRouteItem(data) { return request({ url: "/productProcessRoute/sortRouteItem", url: "/productionOrderRouting/sortRouteItem", method: "post", data, }); @@ -55,7 +55,7 @@ // 获取工序参数列表-生产订单 export function findProcessParamListOrder(query) { return request({ url: `/productionOrderRouteItemParam/list`, url: `/productionOrderRoutingOperationParam/list`, method: "get", params: query, }); @@ -63,7 +63,7 @@ // 工艺路线参数新增-生产订单 export function addProcessRouteItemParamOrder(data) { return request({ url: "/productionOrderRouteItemParam/add", url: "/productionOrderRoutingOperationParam", method: "post", data: data, }); @@ -71,7 +71,7 @@ // 工艺路线参数修改-生产订单 export function editProcessRouteItemParamOrder(data) { return request({ url: "/productionOrderRouteItemParam/update", url: "/productionOrderRoutingOperationParam", method: "put", data: data, }); @@ -79,7 +79,7 @@ // 工艺路线参数删除-生产订单 export function delProcessRouteItemParamOrder(id) { return request({ url: `/productionOrderRouteItemParam/delete/${id}`, url: `/productionOrderRoutingOperationParam/${id}`, method: "delete", }); } src/api/productionManagement/productionOrder.js
@@ -30,7 +30,7 @@ // 生产订单-绑定工艺路线 export function bindingRoute(data) { return request({ url: "/productOrder/bindingRoute", url: "/productionOrder/bindingRoute", method: "post", data, }); @@ -39,7 +39,7 @@ // 生产订单-新增 export function addProductOrder(data) { return request({ url: "/productionOrder", url: "/productionOrder/addOrder", method: "post", data: data, }); @@ -47,7 +47,7 @@ export function delProductOrder(ids) { return request({ url: `/productOrder/${ids}`, url: `/productionOrder/delete/${ids}`, method: "delete", }); } src/components/AttachmentPreview/image/index.vue
@@ -1,6 +1,6 @@ <script setup> const props = defineProps({ list: { fileList: { type: Array, default: () => [], }, @@ -15,7 +15,7 @@ }) const normalizedList = computed(() => { return (props.list || []) return (props.fileList || []) .filter((item) => item && item.previewURL) .map((item, index) => ({ id: item.id ?? index, src/components/AttachmentUpload/image/index.vue
@@ -88,7 +88,7 @@ }) const uploadTip = computed(() => { return `支持 ${props.fileType.join('/')},单张不超过 ${props.fileSize}MB` return `支持 ${props.fileType.join('/')},单张不超过 ${props.fileSize}MB,最多上传 ${props.limit} 张图片` }) function getItemUid(item, index) { src/components/ProcessParamListDialog.vue
@@ -374,10 +374,9 @@ // 调用API新增参数 if (props.pageType === "order") { addProcessRouteItemParamOrder({ orderId: Number(props.orderId), // processId: props.process.id, routeItemId: props.process.id, // routeItemId: Number(props.routeId), productionOrderId: Number(props.orderId), productionOrderRoutingOperationId: props.process.id, technologyRoutingOperationParamId: props.process.id, paramId: selectedParam.value.id, standardValue: selectedParam.value.standardValue || "", isRequired: selectedParam.value.isRequired || 0, @@ -428,8 +427,6 @@ if (props.pageType === "order") { editProcessRouteItemParamOrder({ id: editParamForm.value.id, // routeItemId: props.process.id, // paramId: editParamForm.value.paramId, standardValue: editParamForm.value.standardValue || "", isRequired: editParamForm.value.isRequired || 0, }) src/main.js
@@ -43,11 +43,11 @@ // 富文本组件 import Editor from "@/components/Editor"; // 文件上传组件 import FileUpload from "@/components/FileUpload"; import FileUpload from "@/components/AttachmentUpload/file"; // 图片上传组件 import ImageUpload from "@/components/ImageUpload"; import ImageUpload from "@/components/AttachmentUpload/image"; // 图片预览组件 import ImagePreview from "@/components/ImagePreview"; import ImagePreview from "@/components/AttachmentPreview/image"; // 字典标签组件 import DictTag from "@/components/DictTag"; // 表格组件 src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -134,40 +134,6 @@ const currentMediaIndex = ref(0); const mediaList = ref([]); // 存储当前要查看的媒体列表(含图片和视频对象) const mediaType = ref('image'); // image | video const javaApi = proxy.javaApi; // 处理 URL:将 Windows 路径转换为可访问的 URL function processFileUrl(fileUrl) { if (!fileUrl) return ''; // 如果 URL 是 Windows 路径格式(包含反斜杠),需要转换 if (fileUrl && fileUrl.indexOf('\\') > -1) { // 查找 uploads 关键字的位置,从那里开始提取相对路径 const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads'); if (uploadsIndex > -1) { // 从 uploads 开始提取路径,并将反斜杠替换为正斜杠 const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/'); fileUrl = '/' + relativePath; } else { // 如果没有找到 uploads,提取最后一个目录和文件名 const parts = fileUrl.split('\\'); const fileName = parts[parts.length - 1]; fileUrl = '/uploads/' + fileName; } } // 确保所有非 http 开头的 URL 都拼接 baseUrl if (fileUrl && !fileUrl.startsWith('http')) { // 确保路径以 / 开头 if (!fileUrl.startsWith('/')) { fileUrl = '/' + fileUrl; } // 拼接 baseUrl fileUrl = javaApi + fileUrl; } return fileUrl; } // 处理每一类数据:分离图片和视频 function processItems(items) { @@ -180,24 +146,18 @@ } items.forEach(item => { if (!item || !item.url) return; if (!item || !item.previewURL || !item.contentType) return; // 处理文件 URL const fileUrl = processFileUrl(item.url); // 根据文件扩展名判断是图片还是视频 const urlLower = fileUrl.toLowerCase(); if (urlLower.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/)) { const fileUrl = item.previewURL; const contentType = String(item.contentType).toLowerCase(); // 根据 contentType 判断是图片还是视频 if (contentType.startsWith('image/')) { images.push(fileUrl); } else if (urlLower.match(/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/)) { } else if (contentType.startsWith('video/')) { videos.push(fileUrl); } else if (item.contentType) { // 如果有 contentType,使用 contentType 判断 if (item.contentType.startsWith('image/')) { images.push(fileUrl); } else if (item.contentType.startsWith('video/')) { videos.push(fileUrl); } } }); @@ -207,10 +167,9 @@ // 打开弹窗并加载数据 const openDialog = async (row) => { // 使用正确的字段名:commonFileListBefore, commonFileListAfter // productionIssues 可能不存在,使用空数组 const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBefore || []); const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfter || []); const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues || []); const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBeforeVO || []); const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfterVO || []); const { images: issueImgs, videos: issueVids } = processItems(row.commonFileListVO || []); beforeProductionImgs.value = beforeImgs; beforeProductionVideos.value = beforeVids; src/views/index.vue
@@ -8,7 +8,7 @@ <!-- 顶部问候条 --> <div class="welcome-banner"> <div class="welcome-title"> <span class="welcome-user">{{ userStore.roleName || '系统管理员' }}</span> <span class="welcome-user">{{ userStore.nickName || '系统管理员' }}</span> <span> 您好!祝您开心每一天</span> </div> <div class="welcome-time">登录于: {{ userStore.currentLoginTime }}</div> src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -232,7 +232,7 @@ style="width: 100%"> <el-table-column type="expand"> <template #default> <el-form ref="form" <el-form ref="bomFormRef" :model="bomDataValue"> <el-table :data="bomDataValue.dataList" row-key="tempId" @@ -356,7 +356,7 @@ prop="model" /> </el-table> <ProductSelectDialog v-if="bomDataValue.showProductDialog" v-model:model-value="bomDataValue.showProductDialog" v-model="bomDataValue.showProductDialog" :single="true" @confirm="handleBomProduct" /> <!-- 新增/编辑弹窗 --> @@ -385,8 +385,8 @@ prop="productModelId"> <el-button type="primary" @click="showProductSelectDialog = true"> {{ form.productName && form.model ? `${form.productName} - ${form.model}` {{ form.productName ? (form.model ? `${form.productName} - ${form.model}` : form.productName) : '选择产品' }} </el-button> </el-form-item> @@ -401,13 +401,13 @@ prop="isQuality"> <el-switch v-model="form.isQuality" :active-value="true" inactive-value="false" /> :inactive-value="false" /> </el-form-item> <el-form-item label="是否生产" prop="isProduction"> <el-switch v-model="form.isProduction" :active-value="true" inactive-value="false" /> :inactive-value="false" /> </el-form-item> </el-form> <template #footer> @@ -454,7 +454,10 @@ batchDeleteProcessRouteItem, getProcessParamList, } from "@/api/productionManagement/processRouteItem.js"; import { syncProcessParamItem } from "@/api/productionManagement/processRouteItem.js"; import { syncProcessParamItem, syncProcessParamItemOrder, } from "@/api/productionManagement/processRouteItem.js"; import { findProductProcessRouteItemList, deleteRouteItem, @@ -469,6 +472,7 @@ queryList, addBomDetail, } from "@/api/productionManagement/productStructure.js"; import { useRoute } from "vue-router"; import { ElMessageBox, ElMessage } from "element-plus"; import Sortable from "sortablejs"; @@ -485,6 +489,7 @@ const dialogVisible = ref(false); const operationType = ref("add"); // add | edit const formRef = ref(null); const bomFormRef = ref(null); const submitLoading = ref(false); const cardsContainer = ref(null); const tableRef = ref(null); @@ -542,17 +547,31 @@ type: "warning", }) .then(() => { syncProcessParamItem({ replaceExisting: true, technologyRoutingOperationId: currentProcess.value.id, }).then(res => { if (res.code === 200) { ElMessage.success("同步成功"); refreshParamList(); } else { ElMessage.error(res.msg || "同步失败"); } }); if (pageType.value === "order") { syncProcessParamItemOrder({ replaceExisting: true, technologyRoutingOperationId: currentProcess.value.id, }).then(res => { if (res.code === 200) { ElMessage.success("同步成功"); refreshParamList(); } else { ElMessage.error(res.msg || "同步失败"); } }); } else { syncProcessParamItem({ replaceExisting: true, technologyRoutingOperationId: currentProcess.value.id, }).then(res => { if (res.code === 200) { ElMessage.success("同步成功"); refreshParamList(); } else { ElMessage.error(res.msg || "同步失败"); } }); } }) .catch(() => {}); }; @@ -670,15 +689,20 @@ // 产品选择 const handleProductSelect = products => { console.log(products, "===products==="); if (products && products.length > 0) { const product = products[0]; form.value.productModelId = product.id; form.value.productName = product.productName; form.value.model = product.model; form.value.unit = product.unit || ""; console.log(product, "product"); form.value = { ...form.value, productModelId: product.id, productName: product.productName, model: product.model, unit: product.unit || "", }; showProductSelectDialog.value = false; // 触发表单验证 formRef.value?.validateField("productModelId"); // formRef.value?.validateField("productModelId"); } }; @@ -773,6 +797,8 @@ productName: "", model: "", unit: "", isQuality: false, isProduction: false, }; formRef.value?.resetFields(); }; @@ -788,7 +814,7 @@ currentProcess.value = row; const query = { technologyRoutingOperationId: row.id, orderId: orderId.value, productionOrderId: orderId.value, }; const apiPromise = src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -1,298 +1,327 @@ <template> <div> <el-dialog v-model="dialogVisible" title="领料台账" width="1200px" @close="handleClose"> <el-dialog v-model="dialogVisible" title="领料台账" width="1200px" @close="handleClose"> <div class="material-toolbar"> <el-button type="primary" @click="handleAddMaterialRow">新增</el-button> <el-button type="primary" @click="handleAddMaterialRow">新增</el-button> </div> <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId"> <el-table-column label="工序名称" min-width="180"> <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId"> <el-table-column label="工序名称" min-width="180"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.processName || "-" }}</span> <el-select v-else v-model="row.processName" placeholder="请选择工序" clearable filterable style="width: 100%;" @change="val => handleProcessNameChange(row, val)" > <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.name" /> <el-select v-else v-model="row.processName" placeholder="请选择工序" clearable filterable style="width: 100%;" @change="val => handleProcessNameChange(row, val)"> <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.name" /> </el-select> </template> </el-table-column> <el-table-column label="原料名称" min-width="160"> <el-table-column label="原料名称" min-width="160"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.materialName || "-" }}</span> <el-button v-else type="primary" link @click="openMaterialProductSelect(row)"> <el-button v-else type="primary" link @click="openMaterialProductSelect(row)"> {{ row.materialName || "选择原料" }} </el-button> </template> </el-table-column> <el-table-column label="原料型号" min-width="180"> <el-table-column label="原料型号" min-width="180"> <template #default="{ row }"> {{ row.materialModel || "-" }} </template> </el-table-column> <el-table-column label="需求数量" min-width="120"> <el-table-column label="需求数量" min-width="120"> <template #default="{ row }"> <span v-if="row.bom === true">{{ row.requiredQty ?? "-" }}</span> <el-input-number v-else v-model="row.requiredQty" :min="0" :precision="3" :step="1" controls-position="right" style="width: 100%;" @change="val => handleRequiredQtyChange(row, val)" /> <el-input-number v-else v-model="row.requiredQty" :min="0" :precision="3" :step="1" controls-position="right" style="width: 100%;" @change="val => handleRequiredQtyChange(row, val)" /> </template> </el-table-column> <el-table-column label="计量单位" width="120"> <el-table-column label="计量单位" width="120"> <template #default="{ row }"> {{ row.unit || "-" }} </template> </el-table-column> <el-table-column label="领用数量" min-width="120"> <el-table-column label="领用数量" min-width="120"> <template #default="{ row }"> <el-input-number v-model="row.pickQty" :min="0" :precision="3" :step="1" controls-position="right" style="width: 100%;" /> <el-input-number v-model="row.pickQty" :min="0" :precision="3" :step="1" controls-position="right" style="width: 100%;" /> </template> </el-table-column> <el-table-column label="操作" width="90" fixed="right"> <el-table-column label="操作" width="90" fixed="right"> <template #default="{ $index, row }"> <el-button v-if="row.bom !== true" type="danger" link @click="handleDeleteMaterialRow($index)">删除</el-button> <el-button v-if="row.bom !== true" type="danger" link @click="handleDeleteMaterialRow($index)">删除</el-button> </template> </el-table-column> </el-table> <template #footer> <span class="dialog-footer"> <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">保存</el-button> <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">保存</el-button> <el-button @click="dialogVisible = false">取消</el-button> </span> </template> </el-dialog> <ProductSelectDialog v-model="materialProductDialogVisible" @confirm="handleMaterialProductConfirm" single request-url="/stockInventory/rawMaterials" /> <ProductSelectDialog v-model="materialProductDialogVisible" @confirm="handleMaterialProductConfirm" single /> <!-- request-url="/stockInventory/rawMaterials" --> </div> </template> <script setup> import { computed, ref, watch } from "vue"; import { ElMessage } from "element-plus"; import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js"; import { listMaterialPickingDetail, listMaterialPickingLedger, saveMaterialPickingLedger, } from "@/api/productionManagement/productionOrder.js"; import { computed, ref, watch } from "vue"; import { ElMessage } from "element-plus"; import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js"; import { listMaterialPickingDetail, listMaterialPickingLedger, saveMaterialPickingLedger, } from "@/api/productionManagement/productionOrder.js"; const props = defineProps({ modelValue: { type: Boolean, default: false }, orderRow: { type: Object, default: null }, }); const emit = defineEmits(["update:modelValue", "saved"]); const dialogVisible = computed({ get: () => props.modelValue, set: val => emit("update:modelValue", val), }); const materialProductDialogVisible = ref(false); const materialTableLoading = ref(false); const materialSaving = ref(false); const materialTableData = ref([]); const processOptions = ref([]); const currentMaterialSelectRowIndex = ref(-1); let materialTempId = 0; const createMaterialRow = (row = {}) => ({ tempId: row.id || `temp_${++materialTempId}`, id: row.id, processId: row.processId, productProcessId: row.productProcessId || row.processId, processName: row.processName || "", bom: row.bom === true, materialModelId: row.materialModelId, materialName: row.materialName || "", materialModel: row.materialModel || "", requiredQty: Number(row.requiredQty ?? 0), unit: row.unit || "", pickQty: Number(row.pickQty ?? row.requiredQty ?? 0), }); const getProcessOptions = async () => { if (!props.orderRow?.id) return; const res = await findProductProcessRouteItemList({ orderId: props.orderRow.id }); const routeList = Array.isArray(res?.data) ? res.data : res?.data?.records || []; const processMap = new Map(); routeList.forEach(item => { const processId = item.processId; const processName = item.processName; if (!processId || !processName) return; const key = `${processId}_${processName}`; if (!processMap.has(key)) { processMap.set(key, { id: processId, name: processName, }); } const props = defineProps({ modelValue: { type: Boolean, default: false }, orderRow: { type: Object, default: null }, }); processOptions.value = Array.from(processMap.values()); }; const emit = defineEmits(["update:modelValue", "saved"]); const loadMaterialData = async () => { if (!props.orderRow?.id) return; materialTableLoading.value = true; materialTableData.value = []; await getProcessOptions(); try { const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id }); const detailList = Array.isArray(detailRes?.data) ? detailRes.data : detailRes?.data?.records || []; if (detailList.length > 0) { materialTableData.value = detailList.map(item => createMaterialRow(item)); const dialogVisible = computed({ get: () => props.modelValue, set: val => emit("update:modelValue", val), }); const materialProductDialogVisible = ref(false); const materialTableLoading = ref(false); const materialSaving = ref(false); const materialTableData = ref([]); const processOptions = ref([]); const currentMaterialSelectRowIndex = ref(-1); let materialTempId = 0; const createMaterialRow = (row = {}) => ({ tempId: row.id || `temp_${++materialTempId}`, id: row.id, processId: row.processId, productProcessId: row.productProcessId || row.processId, processName: row.processName || "", bom: row.bom === true, materialModelId: row.materialModelId, materialName: row.materialName || "", materialModel: row.materialModel || "", requiredQty: Number(row.requiredQty ?? 0), unit: row.unit || "", pickQty: Number(row.pickQty ?? row.requiredQty ?? 0), }); const getProcessOptions = async () => { if (!props.orderRow?.id) return; const res = await findProductProcessRouteItemList({ orderId: props.orderRow.id, }); const routeList = Array.isArray(res?.data) ? res.data : res?.data?.records || []; const processMap = new Map(); routeList.forEach(item => { const processId = item.processId; const processName = item.processName; if (!processId || !processName) return; const key = `${processId}_${processName}`; if (!processMap.has(key)) { processMap.set(key, { id: processId, name: processName, }); } }); processOptions.value = Array.from(processMap.values()); }; const loadMaterialData = async () => { if (!props.orderRow?.id) return; materialTableLoading.value = true; materialTableData.value = []; await getProcessOptions(); try { const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id, }); const detailList = Array.isArray(detailRes?.data) ? detailRes.data : detailRes?.data?.records || []; if (detailList.length > 0) { materialTableData.value = detailList.map(item => createMaterialRow(item)); return; } const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id, }); const ledgerList = Array.isArray(ledgerRes?.data) ? ledgerRes.data : ledgerRes?.data?.records || []; materialTableData.value = ledgerList.map(item => createMaterialRow(item)); } finally { materialTableLoading.value = false; } }; watch( () => dialogVisible.value, visible => { if (visible) { loadMaterialData(); } } ); const handleClose = () => { materialTableData.value = []; currentMaterialSelectRowIndex.value = -1; }; const handleAddMaterialRow = () => { materialTableData.value.push(createMaterialRow()); }; const handleDeleteMaterialRow = index => { materialTableData.value.splice(index, 1); }; const handleProcessNameChange = (row, processName) => { const process = processOptions.value.find(item => item.name === processName); row.productProcessId = process?.id; }; const handleRequiredQtyChange = (row, val) => { const required = Number(val ?? 0); row.requiredQty = required; if (!row.pickQty || Number(row.pickQty) === 0) { row.pickQty = required; } }; const openMaterialProductSelect = row => { currentMaterialSelectRowIndex.value = materialTableData.value.findIndex( item => item.tempId === row.tempId ); materialProductDialogVisible.value = true; }; const handleMaterialProductConfirm = products => { if (!products || products.length === 0) return; const index = currentMaterialSelectRowIndex.value; if (index < 0 || !materialTableData.value[index]) return; const product = products[0]; const row = materialTableData.value[index]; row.materialModelId = product.materialModelId || product.modelId || product.id; row.materialName = product.materialName || product.productName || product.name || ""; row.materialModel = product.materialModel || product.model || ""; row.unit = product.unit || product.measureUnit || ""; currentMaterialSelectRowIndex.value = -1; materialProductDialogVisible.value = false; }; const validateMaterialRows = () => { if (materialTableData.value.length === 0) { return { valid: false, message: "请先新增领料数据" }; } const invalidNewRow = materialTableData.value.find( item => item.bom !== true && (!item.processName || !item.materialName) ); if (invalidNewRow) { return { valid: false, message: "新增行的工序名称和原料名称为必填项" }; } const invalidRow = materialTableData.value.find( item => !item.processName || !item.materialName || item.requiredQty === null || item.requiredQty === undefined || item.pickQty === null || item.pickQty === undefined ); if (invalidRow) { return { valid: false, message: "请完善工序、原料和数量后再保存" }; } return { valid: true, message: "" }; }; const handleMaterialSave = async () => { if (!props.orderRow?.id) return; const validateResult = validateMaterialRows(); if (!validateResult.valid) { ElMessage.warning(validateResult.message); return; } const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id }); const ledgerList = Array.isArray(ledgerRes?.data) ? ledgerRes.data : ledgerRes?.data?.records || []; materialTableData.value = ledgerList.map(item => createMaterialRow(item)); } finally { materialTableLoading.value = false; } }; watch( () => dialogVisible.value, visible => { if (visible) { loadMaterialData(); materialSaving.value = true; try { await saveMaterialPickingLedger({ orderId: props.orderRow.id, items: materialTableData.value.map(item => ({ id: item.id, processId: item.processName, productProcessId: item.productProcessId, processName: item.processName, bom: item.bom === true, materialModelId: item.materialModelId, materialName: item.materialName, materialModel: item.materialModel, requiredQty: item.requiredQty, unit: item.unit, pickQty: item.pickQty, })), }); emit("saved"); dialogVisible.value = false; } finally { materialSaving.value = false; } } ); const handleClose = () => { materialTableData.value = []; currentMaterialSelectRowIndex.value = -1; }; const handleAddMaterialRow = () => { materialTableData.value.push(createMaterialRow()); }; const handleDeleteMaterialRow = index => { materialTableData.value.splice(index, 1); }; const handleProcessNameChange = (row, processName) => { const process = processOptions.value.find(item => item.name === processName); row.productProcessId = process?.id; }; const handleRequiredQtyChange = (row, val) => { const required = Number(val ?? 0); row.requiredQty = required; if (!row.pickQty || Number(row.pickQty) === 0) { row.pickQty = required; } }; const openMaterialProductSelect = row => { currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId); materialProductDialogVisible.value = true; }; const handleMaterialProductConfirm = products => { if (!products || products.length === 0) return; const index = currentMaterialSelectRowIndex.value; if (index < 0 || !materialTableData.value[index]) return; const product = products[0]; const row = materialTableData.value[index]; row.materialModelId = product.materialModelId || product.modelId || product.id; row.materialName = product.materialName || product.productName || product.name || ""; row.materialModel = product.materialModel || product.model || ""; row.unit = product.unit || product.measureUnit || ""; currentMaterialSelectRowIndex.value = -1; materialProductDialogVisible.value = false; }; const validateMaterialRows = () => { if (materialTableData.value.length === 0) { return { valid: false, message: "请先新增领料数据" }; } const invalidNewRow = materialTableData.value.find( item => item.bom !== true && (!item.processName || !item.materialName) ); if (invalidNewRow) { return { valid: false, message: "新增行的工序名称和原料名称为必填项" }; } const invalidRow = materialTableData.value.find( item => !item.processName || !item.materialName || item.requiredQty === null || item.requiredQty === undefined || item.pickQty === null || item.pickQty === undefined ); if (invalidRow) { return { valid: false, message: "请完善工序、原料和数量后再保存" }; } return { valid: true, message: "" }; }; const handleMaterialSave = async () => { if (!props.orderRow?.id) return; const validateResult = validateMaterialRows(); if (!validateResult.valid) { ElMessage.warning(validateResult.message); return; } materialSaving.value = true; try { await saveMaterialPickingLedger({ orderId: props.orderRow.id, items: materialTableData.value.map(item => ({ id: item.id, processId: item.processName, productProcessId: item.productProcessId, processName: item.processName, bom: item.bom === true, materialModelId: item.materialModelId, materialName: item.materialName, materialModel: item.materialModel, requiredQty: item.requiredQty, unit: item.unit, pickQty: item.pickQty, })), }); emit("saved"); dialogVisible.value = false; } finally { materialSaving.value = false; } }; }; </script> <style scoped lang="scss"> .material-toolbar { margin-bottom: 12px; text-align: right; } .material-toolbar { margin-bottom: 12px; text-align: right; } </style> src/views/productionManagement/productionOrder/index.vue
@@ -28,7 +28,7 @@ @change="handleQuery" /> </el-form-item> <el-form-item label="产品名称:"> <el-input v-model="searchForm.productCategory" <el-input v-model="searchForm.productName" placeholder="请输入" clearable prefix-icon="Search" @@ -36,7 +36,7 @@ @change="handleQuery" /> </el-form-item> <el-form-item label="规格:"> <el-input v-model="searchForm.specificationModel" <el-input v-model="searchForm.model" placeholder="请输入" clearable prefix-icon="Search" @@ -269,8 +269,8 @@ customerName: "", salesContractNo: "", projectName: "", productCategory: "", specificationModel: "", productName: "", model: "", }, }); const { searchForm } = toRefs(data); @@ -354,7 +354,7 @@ try { await bindingRoute({ id: bindForm.orderId, routeId: bindForm.routeId, technologyRoutingId: bindForm.routeId, }); proxy.$modal.msgSuccess("绑定成功"); bindRouteDialogVisible.value = false; @@ -429,9 +429,9 @@ id: data.id, bomId: data.bomId, processRouteCode: data.processRouteCode || "", productName: data.productName || "", model: data.model || "", bomNo: data.bomNo || "", productName: row.productName || "", model: row.model || "", bomNo: row.bomNo || "", description: data.description || "", orderId, type: "order", @@ -449,8 +449,8 @@ query: { id: row.id, bomNo: row.bomNo || "", productName: row.productCategory || "", productModelName: row.specificationModel || "", productName: row.productName || "", productModelName: row.model || "", orderId: row.id, type: "order", }, src/views/productionPlan/productionPlan/index.vue
@@ -343,7 +343,7 @@ }, { label: "已下发数量", prop: "assignedQuantity", prop: "quantityIssued", width: "120px", className: "spec-cell", // formatData: (cell, row) => (cell ? `${cell}${row.unit || "方"}` : 0), @@ -389,16 +389,18 @@ name: "下发", type: "text", showHide: row => { return row.status == 0; return row.status != 2; }, clickFun: row => { mergeForm.productName = row.productName || ""; mergeForm.model = row.model || ""; mergeForm.totalAssignedQuantity = Number(row.qtyRequired || 0); mergeForm.totalAssignedQuantity = Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); mergeForm.planCompleteTime = row.requiredDate || ""; mergeForm.productId = row.productId || ""; mergeForm.ids = [row.id]; sumAssignedQuantity.value = Number(row.qtyRequired || 0); sumAssignedQuantity.value = Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); isShowNewModal.value = true; }, }, @@ -618,9 +620,9 @@ }; } summary[category].totalAssignedQuantity += Number( ( Number(row.qtyRequired || 0) - Number(row.assignedQuantity || 0) ).toFixed(4) (Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0)).toFixed( 4 ) ); }); @@ -667,8 +669,12 @@ // 判断行是否可选择 const isSelectable = row => { // 如果是已下发状态,禁止勾选 if (row.status == 2) { return false; } // 计算剩余数量 const remainingQty = (row.qtyRequired || 0) - (row.assignedQuantity || 0); const remainingQty = (row.qtyRequired || 0) - (row.quantityIssued || 0); // 如果剩余数量小于等于0,禁止选择 if (remainingQty <= 0) { return false; @@ -696,7 +702,7 @@ // 计算总制造数量 (默认qtyRequired的和) const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => { return sum + Number(row.qtyRequired || 0); return sum + Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); }, 0); sumAssignedQuantity.value = totalAssignedQuantity; console.log(totalAssignedQuantity); src/views/salesManagement/deliveryLedger/index.vue
@@ -3,19 +3,22 @@ <div class="search_form"> <el-form :model="searchForm" :inline="true"> <el-form-item label="销售订单号:"> <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery" /> <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery"/> </el-form-item> <el-form-item label="车牌号:"> <el-input v-model="searchForm.shippingCarNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery" /> <el-input v-model="searchForm.shippingCarNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery"/> </el-form-item> <el-form-item label="快递单号:"> <el-input v-model="searchForm.expressNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery" /> <el-input v-model="searchForm.expressNumber" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px" @change="handleQuery"/> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery"> 搜索 </el-button> <el-button type="primary" @click="handleQuery"> 搜索</el-button> </el-form-item> </el-form> </div> @@ -28,18 +31,18 @@ </div> </div> <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)"> <el-table-column align="center" type="selection" width="55" /> <el-table-column align="center" label="序号" type="index" width="60" /> <el-table-column label="销售订单" prop="salesContractNo" show-overflow-tooltip /> <el-table-column label="发货订单号" prop="shippingNo" show-overflow-tooltip /> <el-table-column label="客户名称" prop="customerName" show-overflow-tooltip /> <el-table-column label="产品名称" prop="productName" show-overflow-tooltip /> <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip /> <el-table-column label="发货时间" prop="shippingDate" show-overflow-tooltip /> <el-table-column label="发货车牌号" prop="shippingCarNumber" show-overflow-tooltip /> <el-table-column label="快递公司" prop="expressCompany" show-overflow-tooltip /> <el-table-column label="快递单号" prop="expressNumber" show-overflow-tooltip /> :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)"> <el-table-column align="center" type="selection" width="55"/> <el-table-column align="center" label="序号" type="index" width="60"/> <el-table-column label="销售订单" prop="salesContractNo" show-overflow-tooltip/> <el-table-column label="发货订单号" prop="shippingNo" show-overflow-tooltip/> <el-table-column label="客户名称" prop="customerName" show-overflow-tooltip/> <el-table-column label="产品名称" prop="productName" show-overflow-tooltip/> <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip/> <el-table-column label="发货时间" prop="shippingDate" show-overflow-tooltip/> <el-table-column label="发货车牌号" prop="shippingCarNumber" show-overflow-tooltip/> <el-table-column label="快递公司" prop="expressCompany" show-overflow-tooltip/> <el-table-column label="快递单号" prop="expressNumber" show-overflow-tooltip/> <el-table-column label="审核状态" prop="status" align="center" width="120"> <template #default="scope"> <el-tag :type="getApprovalStatusType(scope.row.status)"> @@ -49,42 +52,46 @@ </el-table-column> <el-table-column fixed="right" label="操作" width="220" align="center"> <template #default="scope"> <el-button link type="primary" :disabled="!isApproved(scope.row.status)" @click="openForm('edit', scope.row)">补充发货信息</el-button> <el-button link type="primary" style="color: #67C23A" @click="openDetail(scope.row)" >详情</el-button> <el-button link type="danger" :disabled="isApproving(scope.row.status)" @click="handleDeleteSingle(scope.row)">删除</el-button> link type="primary" :disabled="!isApproved(scope.row.status)" @click="openForm('edit', scope.row)">补充发货信息 </el-button> <el-button link type="primary" style="color: #67C23A" @click="openDetail(scope.row)" >详情 </el-button> <el-button link type="danger" :disabled="isApproving(scope.row.status)" @click="handleDeleteSingle(scope.row)">删除 </el-button> </template> </el-table-column> </el-table> <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" :page="page.current" :limit="page.size" @pagination="paginationChange" /> :page="page.current" :limit="page.size" @pagination="paginationChange"/> </div> <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增发货台账' : '编辑发货台账'" width="40%" @close="closeDia"> <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增发货台账' : '编辑发货台账'" width="40%" @close="closeDia"> <el-form :model="form" label-width="120px" label-position="top" :rules="rules" ref="formRef"> <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="发货类型:" prop="type"> <el-select v-model="form.type" placeholder="请选择发货类型" style="width: 100%" @change="handleShippingTypeChange" v-model="form.type" placeholder="请选择发货类型" style="width: 100%" @change="handleShippingTypeChange" > <el-option label="货车" value="货车" /> <el-option label="快递" value="快递" /> <el-option label="货车" value="货车"/> <el-option label="快递" value="快递"/> </el-select> </el-form-item> </el-col> @@ -93,13 +100,13 @@ <el-col :span="24"> <el-form-item label="发货日期:" prop="shippingDate"> <el-date-picker style="width: 100%" v-model="form.shippingDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="请选择发货日期" clearable style="width: 100%" v-model="form.shippingDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="请选择发货日期" clearable /> </el-form-item> </el-col> @@ -108,18 +115,18 @@ <el-col :span="24" v-if="form.type === '货车'"> <el-form-item label="发货车牌号:" prop="shippingCarNumber"> <el-input v-model="form.shippingCarNumber" placeholder="请输入发货车牌号" clearable v-model="form.shippingCarNumber" placeholder="请输入发货车牌号" clearable /> </el-form-item> </el-col> <el-col :span="24" v-else> <el-form-item label="快递公司:" prop="expressCompany"> <el-input v-model="form.expressCompany" placeholder="请输入快递公司" clearable v-model="form.expressCompany" placeholder="请输入快递公司" clearable /> </el-form-item> </el-col> @@ -128,9 +135,9 @@ <el-col :span="24"> <el-form-item label="快递单号:" prop="expressNumber"> <el-input v-model="form.expressNumber" placeholder="请输入快递单号" clearable v-model="form.expressNumber" placeholder="请输入快递单号" clearable /> </el-form-item> </el-col> @@ -138,29 +145,7 @@ <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="发货图片:"> <el-upload v-model:file-list="deliveryFileList" :action="upload.url" multiple ref="deliveryFileUpload" auto-upload :headers="upload.headers" :data="{ type: 9 }" :before-upload="handleDeliveryBeforeUpload" :on-error="handleDeliveryUploadError" :on-success="handleDeliveryUploadSuccess" :on-remove="handleDeliveryRemove" list-type="picture-card" :limit="9" accept="image/png,image/jpeg,image/jpg" > <el-icon class="avatar-uploader-icon"><Plus /></el-icon> <template #tip> <div class="el-upload__tip"> 支持 jpg、jpeg、png 格式,最多上传 9 张,单张大小不超过 10MB </div> </template> </el-upload> <ImageUpload v-model:file-list="deliveryFileList" :limit="9"/> </el-form-item> </el-col> </el-row> @@ -189,19 +174,7 @@ <el-descriptions-item label="快递公司">{{ detailRow.expressCompany || '--' }}</el-descriptions-item> <el-descriptions-item label="快递单号" :span="2">{{ detailRow.expressNumber || '--' }}</el-descriptions-item> </el-descriptions> <div class="detail-images" v-if="detailImages.length"> <div class="detail-images-title">发货图片</div> <el-image v-for="img in detailImages" :key="img.url" :src="img.url" :preview-src-list="detailImages.map(i => i.url)" fit="cover" class="detail-image" /> </div> <div v-else class="detail-images-empty">暂无发货图片</div> <ImagePreview :file-list="detailRow.storageBlobVOs || []" /> </div> <template #footer> <div class="dialog-footer"> @@ -214,20 +187,19 @@ <script setup> import pagination from "@/components/PIMTable/Pagination.vue"; import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; import { ElMessageBox } from "element-plus"; import { Plus } from "@element-plus/icons-vue"; import { getToken } from "@/utils/auth"; import { getCurrentDate } from "@/utils/index.js"; import {onMounted, ref, reactive, toRefs, getCurrentInstance} from "vue"; import {ElMessageBox} from "element-plus"; import {getCurrentDate} from "@/utils/index.js"; import { deliveryLedgerListPage, addOrUpdateDeliveryLedger, delDeliveryLedger, deductStock, deliveryLedgerListPage, delDeliveryLedger, deductStock, } from "@/api/salesManagement/deliveryLedger.js"; import { delLedgerFile } from "@/api/salesManagement/salesLedger.js"; import {delLedgerFile} from "@/api/salesManagement/salesLedger.js"; import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; import ImagePreview from "@/components/AttachmentPreview/image/index.vue"; const { proxy } = getCurrentInstance(); const {proxy} = getCurrentInstance(); const tableData = ref([]); const selectedRows = ref([]); const tableLoading = ref(false); @@ -238,40 +210,9 @@ }); const total = ref(0); const deliveryFileList = ref([]); const javaApi = proxy.javaApi; // 详情弹框 const detailDialogVisible = ref(false); const detailRow = ref(null); const detailImages = ref([]); const normalizeFileUrl = (rawUrl = '') => { let fileUrl = rawUrl || ''; // Windows 路径转 URL if (fileUrl && fileUrl.indexOf('\\') > -1) { const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads'); if (uploadsIndex > -1) { const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/'); fileUrl = '/' + relativePath; } else { const parts = fileUrl.split('\\'); const fileName = parts[parts.length - 1]; fileUrl = '/uploads/' + fileName; } } if (fileUrl && !fileUrl.startsWith('http')) { if (!fileUrl.startsWith('/')) fileUrl = '/' + fileUrl; fileUrl = javaApi + fileUrl; } return fileUrl; }; // 上传配置 const upload = reactive({ // 上传的地址 url: import.meta.env.VITE_APP_BASE_API + "/file/upload", // 设置上传的请求头部 headers: { Authorization: "Bearer " + getToken() }, }); // 用户信息表单弹框数据 const operationType = ref(""); @@ -295,24 +236,23 @@ expressNumber: "", // 快递单号 }, rules: { salesContractNo: [{ required: true, message: "请选择销售订单", trigger: "change" }], customerName: [{ required: true, message: "请输入客户名称", trigger: "blur" }], salesContractNo: [{required: true, message: "请选择销售订单", trigger: "change"}], customerName: [{required: true, message: "请输入客户名称", trigger: "blur"}], type: [ { required: true, message: "请选择发货类型", trigger: "change" } {required: true, message: "请选择发货类型", trigger: "change"} ], shippingDate: [{ required: true, message: "请选择发货时间", trigger: "change" }], shippingDate: [{required: true, message: "请选择发货时间", trigger: "change"}], shippingCarNumber: [ { validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" } {validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur"} ], expressCompany: [ { validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" } {validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur"} ], }, }); const { form, rules } = toRefs(data); const { searchForm } = toRefs(data); const {form, rules} = toRefs(data); const {searchForm} = toRefs(data); // 查询列表 const handleQuery = () => { @@ -328,15 +268,15 @@ const getList = () => { tableLoading.value = true; deliveryLedgerListPage({ ...searchForm.value, ...page }) .then((res) => { tableLoading.value = false; tableData.value = res.data.records || []; total.value = res.data.total || 0; }) .catch(() => { tableLoading.value = false; }); deliveryLedgerListPage({...searchForm.value, ...page}) .then((res) => { tableLoading.value = false; tableData.value = res.data.records || []; total.value = res.data.total || 0; }) .catch(() => { tableLoading.value = false; }); }; // 销售订单变化时自动填充客户名称 @@ -359,10 +299,9 @@ proxy.$modal.msgWarning("只有审核通过的数据才可以补充发货信息"); return; } operationType.value = type; const baseUrl = import.meta.env.VITE_APP_BASE_API; if (type === 'edit' && row) { form.value = { id: row.id ?? null, @@ -374,43 +313,9 @@ expressCompany: row.expressCompany ?? "", expressNumber: row.expressNumber ?? "", }; // 如果有图片,将 commonFileList 转换为文件列表格式 if (row.commonFileList && Array.isArray(row.commonFileList) && row.commonFileList.length > 0) { deliveryFileList.value = row.commonFileList.map((file, index) => { const fileUrl = normalizeFileUrl(file.url || ''); return { uid: file.id || Date.now() + index, name: file.name || `image_${index + 1}.jpg`, url: fileUrl, status: 'success', response: { code: 200, data: { tempId: file.id, url: fileUrl } }, tempId: file.id // 保存文件ID,用于提交时使用 }; }); } else { deliveryFileList.value = []; } } else { form.value = { id: null, salesContractNo: "", customerName: "", type: "货车", shippingDate: getCurrentDate(), shippingCarNumber: "", expressCompany: "", expressNumber: "", }; deliveryFileList.value = []; deliveryFileList.value = row.storageBlobVOS || []; } dialogFormVisible.value = true; }; @@ -418,25 +323,17 @@ const openDetail = (row) => { detailRow.value = row || null; const list = Array.isArray(row?.commonFileList) ? row.commonFileList : []; detailImages.value = list .map((f) => ({ url: normalizeFileUrl(f?.url || '') })) .filter((i) => !!i.url); detailDialogVisible.value = true; }; const closeDetail = () => { detailDialogVisible.value = false; detailRow.value = null; detailImages.value = []; }; // 提交表单 const submitForm = () => { proxy.$refs["formRef"].validate((valid) => { if (valid) { let tempFileIds = []; if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) { tempFileIds = deliveryFileList.value.map((item) => item.tempId); } const payload = { id: form.value.id, type: form.value.type, @@ -444,9 +341,9 @@ shippingCarNumber: form.value.type === "货车" ? form.value.shippingCarNumber : "", expressCompany: form.value.type === "快递" ? form.value.expressCompany : "", expressNumber: form.value.type === "快递" ? form.value.expressNumber : "", tempFileIds: tempFileIds, storageBlobDTOs: deliveryFileList.value || [], }; deductStock(payload).then((res) => { deductStock(payload).then((res) => { proxy.$modal.msgSuccess("操作成功"); closeDia(); getList(); @@ -469,12 +366,12 @@ cancelButtonText: "取消", type: "warning", }) .then(() => { proxy.download("/shippingInfo/export", {}, "发货台账.xlsx"); }) .catch(() => { proxy.$modal.msg("已取消"); }); .then(() => { proxy.download("/shippingInfo/export", {}, "发货台账.xlsx"); }) .catch(() => { proxy.$modal.msg("已取消"); }); }; // 批量删除 @@ -483,29 +380,29 @@ proxy.$modal.msgWarning("请选择数据"); return; } // 检查选中的行是否有"审核中"状态 const approvingRows = selectedRows.value.filter(row => isApproving(row.status)); if (approvingRows.length > 0) { proxy.$modal.msgWarning("审核中的数据不能删除"); return; } const ids = selectedRows.value.map((item) => item.id); ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", { confirmButtonText: "确认", cancelButtonText: "取消", type: "warning", }) .then(() => { delDeliveryLedger(ids).then((res) => { proxy.$modal.msgSuccess("删除成功"); getList(); .then(() => { delDeliveryLedger(ids).then((res) => { proxy.$modal.msgSuccess("删除成功"); getList(); }); }) .catch(() => { proxy.$modal.msg("已取消"); }); }) .catch(() => { proxy.$modal.msg("已取消"); }); }; // 单个删除 @@ -515,21 +412,21 @@ proxy.$modal.msgWarning("审核中的数据不能删除"); return; } ElMessageBox.confirm("此操作将删除该记录,是否确认?", "删除", { confirmButtonText: "确认", cancelButtonText: "取消", type: "warning", }) .then(() => { delDeliveryLedger([row.id]).then((res) => { proxy.$modal.msgSuccess("删除成功"); getList(); .then(() => { delDeliveryLedger([row.id]).then((res) => { proxy.$modal.msgSuccess("删除成功"); getList(); }); }) .catch(() => { proxy.$modal.msg("已取消"); }); }) .catch(() => { proxy.$modal.msg("已取消"); }); }; // 发货类型校验:货车时要求车牌,快递时要求快递公司 @@ -563,11 +460,13 @@ proxy.$modal.loading("正在上传图片,请稍候..."); return true; } // 发货图片上传失败 function handleDeliveryUploadError(err) { proxy.$modal.msgError("上传图片失败"); proxy.$modal.closeLoading(); } // 发货图片上传成功回调 function handleDeliveryUploadSuccess(res, file, uploadFiles) { proxy.$modal.closeLoading(); @@ -579,6 +478,7 @@ proxy.$refs.deliveryFileUpload.handleRemove(file); } } // 移除发货图片 function handleDeliveryRemove(file) { console.log('file--', file) @@ -727,17 +627,21 @@ display: none; } } .detail-wrapper { padding: 8px 0; } .detail-images { margin-top: 16px; } .detail-images-title { font-weight: 600; margin-bottom: 10px; color: #303133; } .detail-image { width: 120px; height: 120px; @@ -745,6 +649,7 @@ margin-bottom: 10px; border-radius: 6px; } .detail-images-empty { margin-top: 16px; color: #909399;