| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产订åé¢æè®°å½æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ ¹æ®è®¢åIDæ¥è¯¢ç©ææ¸
åï¼é¢ææ°æ®ï¼ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/productStructureRecord/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // 颿æäº¤ |
| | | export function pick(data) { |
| | | return request({ |
| | | url: "/productStructureRecord/pick", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | v-if="o.showHide ? o.showHide(scope.row) : true" |
| | | :disabled="o.disabled ? o.disabled(scope.row) : false" |
| | | :plain="o.plain" |
| | | type="primary" |
| | | :type="o.type && ['primary', 'success', 'warning', 'danger', 'info'].includes(o.type) ? o.type : 'primary'" |
| | | :style="{ |
| | | color: |
| | | o.name === 'å é¤' || o.name === 'delete' |
| | |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥èºè·¯çº¿", |
| | | prop: "routeName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "产å屿§", |
| | | prop: "productType", |
| | | width: 100, |
| | |
| | | modelForm.value = { ...data }; |
| | | modelForm.value.tempFileIds = data.tempFileIds || []; |
| | | modelForm.value.salesLedgerFiles = data.salesLedgerFiles || []; |
| | | if (data.drawingFile) { |
| | | // å¤çå¾çº¸æä»¶åæ¾ |
| | | if (data.salesLedgerFiles && data.salesLedgerFiles.length > 0) { |
| | | drawingFileList.value = data.salesLedgerFiles.map(file => ({ |
| | | name: file.name, |
| | | url: file.url |
| | | })); |
| | | } else if (data.drawingFile) { |
| | | drawingFileList.value = [{ |
| | | name: data.drawingFile.split('/').pop(), |
| | | url: data.drawingFile |
| | |
| | | const submitModelForm = () => { |
| | | modelFormRef.value.validate((valid) => { |
| | | if (valid) { |
| | | addOrEditProductModel(modelForm.value).then((res) => { |
| | | // æå»ºæäº¤æ°æ®ï¼ç¡®ä¿ routeId 为空æ¶ä¼ nullï¼åæ¶æ¸
空 routeName |
| | | const submitData = { |
| | | ...modelForm.value, |
| | | routeId: modelForm.value.routeId || 0, |
| | | routeName: modelForm.value.routeId ? modelForm.value.routeName : null |
| | | }; |
| | | addOrEditProductModel(submitData).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeModelDia(); |
| | | getModelList(); |
| | |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- éä¸äº§ååå±ç¤ºäº§åä¿¡æ¯ --> |
| | | <div v-if="selectedBomProduct" class="selected-product-info"> |
| | | <div class="product-info-row"> |
| | | <span class="info-label">产åç¼å·</span> |
| | | <span class="info-value">{{ selectedBomProduct.model || selectedBomProduct.productCode || '-' }}</span> |
| | | </div> |
| | | <div class="product-info-row"> |
| | | <span class="info-label">产ååç§°</span> |
| | | <span class="info-value">{{ selectedBomProduct.productName || '-' }}</span> |
| | | </div> |
| | | <div class="product-info-row"> |
| | | <span class="info-label">产åè§æ ¼</span> |
| | | <span class="info-value">{{ selectedBomProduct.spec || selectedBomProduct.drawingNumber || '-' }}</span> |
| | | </div> |
| | | <div class="stock-info-box"> |
| | | <div class="stock-number">{{ selectedBomProduct.stockQuantity || 0 }}</div> |
| | | <div class="stock-label">åºåæ°é(å°)</div> |
| | | </div> |
| | | </div> |
| | | <el-form-item label="ç¨éç³»æ°" prop="coefficient" style="margin-top: 20px;"> |
| | | <el-input-number v-model="bomAddForm.coefficient" :min="0.01" :precision="2" :step="1" |
| | | controls-position="right" style="width: 100%" /> |
| | |
| | | const parentProductOptions = ref([]); |
| | | const selectedBomProduct = ref(null); |
| | | const selectedBomTreeData = ref([]); // ä¿åéä¸äº§åæ¶è·åçBOMæ æ°æ® |
| | | const showAdvancedProductDialog = ref(false); |
| | | const bomAddForm = reactive({ |
| | | parentProductId: undefined, |
| | | coefficient:1 |
| | |
| | | <el-table-column label="产ååç§°" prop="productName" min-width="120" /> |
| | | <el-table-column label="åä½äº§åºéè¦æ°é" min-width="140"> |
| | | <template #default="{ row }"> |
| | | <el-input-number v-model="row.unitQuantity" :min="0" :precision="2" size="small" style="width: 100%" /> |
| | | <el-input-number |
| | | v-model="row.unitQuantity" |
| | | :min="0" |
| | | :precision="2" |
| | | size="small" |
| | | style="width: 100%" |
| | | @change="(val) => handleUnitQuantityChange(val, row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="éæ±æ°é" min-width="120"> |
| | |
| | | const items = res.data || []; |
| | | processRouteItemsOptions.value = items; |
| | | |
| | | // èªå¨æ·»å å·¥åº |
| | | // èªå¨æ·»å å·¥åºï¼è®¡åæ°ä½¿ç¨åºæ¬ä¿¡æ¯çéæ±æ°é |
| | | const demandQty = formState.value.quantity || 1; |
| | | processRouteItems.value = items.map(item => ({ |
| | | processId: item.processId, |
| | | processName: item.processName, |
| | |
| | | userPower: item.userPower ? item.userPower.split(',') : [], |
| | | planStartTime: "", |
| | | planEndTime: "", |
| | | planNum: 1, |
| | | planNum: demandQty, |
| | | isQuality: item.isQuality || false, |
| | | })); |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // çå¬éæ±æ°éååï¼éæ°è®¡ç®ç©æéæ±æ°é |
| | | // çå¬ç©ææ¸
åååï¼å½åä½äº§åºéè¦æ°éååæ¶éæ°è®¡ç®éæ±æ°é |
| | | watch(() => productStructureRecords.value, (newRecords, oldRecords) => { |
| | | if (oldRecords && oldRecords.length > 0) { |
| | | oldRecords.forEach((oldItem, index) => { |
| | | const newItem = newRecords[index]; |
| | | if (oldItem && newItem && newItem.unitQuantity !== oldItem.unitQuantity) { |
| | | newItem.demandedQuantity = (newItem.unitQuantity || 1) * (formState.value.quantity || 1); |
| | | } |
| | | }); |
| | | } |
| | | }, { deep: true }); |
| | | |
| | | // çå¬éæ±æ°éååï¼éæ°è®¡ç®ç©æéæ±æ°éåå·¥åºè®¡åæ° |
| | | watch(() => formState.value.quantity, (newQty) => { |
| | | // æ´æ°ç©ææ¸
åçéæ±æ°é |
| | | if (productStructureRecords.value.length > 0 && newQty) { |
| | | productStructureRecords.value = productStructureRecords.value.map(item => ({ |
| | | ...item, |
| | | demandedQuantity: (item.unitQuantity || 1) * newQty |
| | | })); |
| | | productStructureRecords.value.forEach(item => { |
| | | item.demandedQuantity = (item.unitQuantity || 1) * newQty; |
| | | }); |
| | | } |
| | | // æ´æ°å·¥åºçè®¡åæ° |
| | | if (processRouteItems.value.length > 0 && newQty) { |
| | | processRouteItems.value.forEach(item => { |
| | | item.planNum = newQty; |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // åä½äº§åºéè¦æ°éååå¤ç |
| | | const handleUnitQuantityChange = (val, row) => { |
| | | row.demandedQuantity = (val || 1) * (formState.value.quantity || 1); |
| | | }; |
| | | |
| | | // å·¥åºéæ©ååå¤ç |
| | | const handleProcessChange = (processId, row) => { |
| | | const selectedProcess = processRouteItemsOptions.value.find(item => item.processId === processId); |
| | |
| | | v-model:visible="isShowNewModal" |
| | | type="qualified" |
| | | @completed="handleQuery" /> |
| | | |
| | | <!-- æ¥çæå
¥å¼¹æ¡ --> |
| | | <el-dialog v-model="inputDialogVisible" |
| | | title="æå
¥" |
| | | width="1000px"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="inputTableColumn" |
| | | :tableData="inputTableData" |
| | | :page="inputPage" |
| | | :tableLoading="inputTableLoading" |
| | | @pagination="handleInputPagination" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="inputDialogVisible = false">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- é¢æå¼¹æ¡ --> |
| | | <el-dialog v-model="pickingDialogVisible" |
| | | title="å·¥å颿" |
| | | width="1200px" |
| | | :close-on-click-modal="false"> |
| | | |
| | | <el-table |
| | | :data="pickingTableData" |
| | | border |
| | | size="small" |
| | | @selection-change="handlePickingSelectionChange" |
| | | :header-cell-style="{ background: '#f5f7fa' }" |
| | | show-summary |
| | | :summary-method="summarizePickingTable" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column label="产ååç§°" prop="productName" min-width="120" /> |
| | | <el-table-column label="å¾çº¸ç¼å·" prop="model" min-width="100" /> |
| | | <el-table-column label="åä½ç¨é" prop="unitQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="åä½" prop="unit" min-width="100" align="center" /> |
| | | <el-table-column label="éæ±æ°é" prop="demandedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="已颿æ°é" prop="completedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="æªé¢ææ°é" prop="unpickedQuantity" min-width="100" align="center" /> |
| | | <el-table-column label="颿æ°é" min-width="180" align="center" prop="quantity"> |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-model="row.quantity" |
| | | :min="0" |
| | | :max="row.unpickedQuantity" |
| | | :precision="0" |
| | | size="small" |
| | | style="width: 160px" |
| | | @change="(val) => handlePickingQuantityChange(val, row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="picking-footer-info"> |
| | | <span>å·²é {{ pickingSelectedRows.length }} æ¡</span> |
| | | <span>{{ pickingTableData.length }} æ¡è®°å½</span> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="success" @click="handlePickingNext">确认</el-button> |
| | | <el-button @click="pickingDialogVisible = false">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import { onMounted, ref, computed } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { Setting } from '@element-plus/icons-vue'; |
| | | import dayjs from "dayjs"; |
| | | import { useRouter } from "vue-router"; |
| | | import { |
| | |
| | | listProcessBom, delProductOrder, startOrPause, |
| | | } from "@/api/productionManagement/productionOrder.js"; |
| | | import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js"; |
| | | import { productionProductInputListPage } from "@/api/productionManagement/productionProductInput.js"; |
| | | import { listPage as listProductStructureRecord, pick as pickMaterial } from "@/api/productionManagement/productStructureRecord.js"; |
| | | |
| | | import {fileDel} from "@/api/financialManagement/revenueManagement.js"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue")); |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 240, |
| | | width: 360, |
| | | operation: [ |
| | | { |
| | | name: "å¼å§", |
| | | type: "text", |
| | | type: "success", |
| | | showHide: row => row.status === 'å¾
ç产', |
| | | clickFun: row => { |
| | | handleStartOrPause(row); |
| | |
| | | }, |
| | | { |
| | | name: "æå", |
| | | type: "text", |
| | | type: "danger", |
| | | showHide: row => row.status === 'ç产ä¸', |
| | | clickFun: row => { |
| | | handleStartOrPause(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "颿", |
| | | type: "success", |
| | | clickFun: row => { |
| | | showPickingDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | |
| | | showProductStructure(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥çæå
¥", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showInputDialog(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // æ¥çæå
¥ç¸å
³ |
| | | const inputDialogVisible = ref(false); |
| | | const inputTableData = ref([]); |
| | | const inputTableLoading = ref(false); |
| | | const inputCurrentRow = ref(null); |
| | | const inputPage = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const inputTableColumn = ref([ |
| | | { |
| | | label: 'æå
¥äº§ååç§°', |
| | | prop: 'productName', |
| | | }, |
| | | { |
| | | label: 'å¾çº¸ç¼å·', |
| | | prop: 'model' |
| | | }, |
| | | { |
| | | label: 'æå
¥æ°é', |
| | | prop: 'quantity', |
| | | }, |
| | | { |
| | | label: 'åä½', |
| | | prop: 'unit', |
| | | }, |
| | | ]); |
| | | |
| | | // 颿ç¸å
³ |
| | | const pickingDialogVisible = ref(false); |
| | | const pickingTableData = ref([]); |
| | | const pickingSelectedRows = ref([]); |
| | | const pickingForm = reactive({ |
| | | orderId: null, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | |
| | | const handleConfirmRoute = () => {}; |
| | | |
| | | // æ¾ç¤ºæ¥çæå
¥å¼¹æ¡ |
| | | const showInputDialog = (row) => { |
| | | inputCurrentRow.value = row; |
| | | inputDialogVisible.value = true; |
| | | inputPage.current = 1; |
| | | inputPage.total = 0; |
| | | fetchInputData(); |
| | | }; |
| | | |
| | | // æ¥çæå
¥å页 |
| | | const handleInputPagination = (obj) => { |
| | | inputPage.current = obj.page; |
| | | inputPage.size = obj.limit; |
| | | fetchInputData(); |
| | | }; |
| | | |
| | | // è·åæå
¥æ°æ® |
| | | const fetchInputData = () => { |
| | | inputTableLoading.value = true; |
| | | const params = { productOrderId: inputCurrentRow.value.id, ...inputPage }; |
| | | productionProductInputListPage(params) |
| | | .then(res => { |
| | | inputTableLoading.value = false; |
| | | inputTableData.value = res.data.records; |
| | | inputPage.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | inputTableLoading.value = false; |
| | | console.error("è·åæå
¥æ°æ®å¤±è´¥ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºé¢æå¼¹æ¡ |
| | | const showPickingDialog = async (row) => { |
| | | pickingForm.orderId = row.id; |
| | | pickingDialogVisible.value = true; |
| | | pickingTableData.value = []; |
| | | |
| | | // è·åç©ææ¸
åæ°æ® |
| | | try { |
| | | const res = await listProductStructureRecord({ productOrderId: row.id }); |
| | | const materials = res.data?.records || []; |
| | | pickingTableData.value = materials.map(item => ({ |
| | | ...item, |
| | | quantity: 0, |
| | | unpickedQuantity: (item.demandedQuantity || 0) - (item.completedQuantity || 0), |
| | | })); |
| | | } catch (e) { |
| | | console.error("è·åç©ææ¸
å失败ï¼", e); |
| | | proxy.$modal.msgError("è·åç©ææ¸
å失败"); |
| | | } |
| | | }; |
| | | |
| | | // é¢æè¡¨æ ¼éæ©åå |
| | | const handlePickingSelectionChange = (selection) => { |
| | | pickingSelectedRows.value = selection; |
| | | }; |
| | | |
| | | // 颿æ°éååå¤ç |
| | | const handlePickingQuantityChange = (val, row) => { |
| | | if (val > row.unpickedQuantity) { |
| | | proxy.$modal.msgWarning("颿æ°éä¸è½è¶
è¿æªé¢ææ°é"); |
| | | row.quantity = row.unpickedQuantity; |
| | | } |
| | | }; |
| | | |
| | | // ç¡®è®¤é¢æ |
| | | const handlePickingNext = async () => { |
| | | if (pickingSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦é¢æçç©æ"); |
| | | return; |
| | | } |
| | | // æ ¡éªé¢ææ°é |
| | | for (const row of pickingSelectedRows.value) { |
| | | if (row.quantity > row.unpickedQuantity) { |
| | | proxy.$modal.msgWarning(`${row.productName} ç颿æ°éä¸è½è¶
è¿æªé¢ææ°é`); |
| | | return; |
| | | } |
| | | if (row.quantity <= 0) { |
| | | proxy.$modal.msgWarning(`${row.productName} ç颿æ°éå¿
须大äº0`); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // æäº¤é¢ææ°æ® |
| | | try { |
| | | const pickData = pickingSelectedRows.value.map(row => ({ |
| | | productOrderId: row.productOrderId, |
| | | productStructureRecordId: row.id, |
| | | productModelId: row.productModelId, |
| | | quantity: row.quantity, |
| | | })); |
| | | await pickMaterial(pickData); |
| | | proxy.$modal.msgSuccess("颿æå"); |
| | | pickingDialogVisible.value = false; |
| | | } catch (e) { |
| | | console.error("é¢æå¤±è´¥ï¼", e); |
| | | proxy.$modal.msgError("é¢æå¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // é¢æè¡¨æ ¼åè®¡æ¹æ³ |
| | | const summarizePickingTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "quantity", |
| | | "unpickedQuantity", |
| | | "inventoryQuantity", |
| | | "demandedQuantity", |
| | | ]); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | |
| | | :deep(.purple){ |
| | | background-color: #F4DEFA; |
| | | } |
| | | |
| | | .picking-footer-info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | |
| | | </style> |
| | |
| | | </div> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery"></form-dia> |
| | | <input-modal v-if="isShowInput" |
| | | v-model:visible="isShowInput" |
| | | :production-product-main-id="isShowingId" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | } from "@/api/productionManagement/productionReporting.js"; |
| | | import { productionProductMainListPage } from "@/api/productionManagement/productionProductMain.js"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import InputModal from "@/views/productionManagement/productionReporting/Input.vue"; |
| | | |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | width: 120, |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | align: "center", |
| | | fixed: "right", |
| | | operation: [ |
| | | { |
| | | name: "æ¥çæå
¥", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showInput(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | |
| | | const rowInfo = type === "add" ? selectedRows.value[0] : row; |
| | | formDia.value?.openDialog(type, rowInfo); |
| | | }); |
| | | }; |
| | | |
| | | // æå¼æå
¥æ¨¡ææ¡ |
| | | const isShowInput = ref(false); |
| | | const isShowingId = ref(0); |
| | | const showInput = row => { |
| | | isShowInput.value = true; |
| | | isShowingId.value = row.id; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | |
| | | <span class="info-value">{{ transferCardRowData.completeQuantity }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">å¾
ç产æ°é</span> |
| | | <span class="info-value">{{ (transferCardRowData.planQuantity || 0) - (transferCardRowData.completeQuantity || 0) }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">è¯åæ°é</span> |
| | | <span class="info-value">0</span> |
| | | </div> |
| | |
| | | downProductWorkOrder, |
| | | } from "@/api/productionManagement/workOrder.js"; |
| | | import { getUserProfile, userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | |
| | | import QRCode from "qrcode"; |
| | | import { getCurrentInstance, reactive, toRefs } from "vue"; |
| | | import FilesDia from "./components/filesDia.vue"; |
| | |
| | | { |
| | | label: "宿æ°é", |
| | | prop: "completeQuantity", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "å¾
ç产æ°é", |
| | | prop: "pendingQuantity", |
| | | width: "140", |
| | | }, |
| | | { |
| | |
| | | productWorkOrderPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | pendingQuantity: (item.planQuantity || 0) - (item.completeQuantity || 0) |
| | | })); |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | |
| | | justify-content: flex-start; |
| | | } |
| | | } |
| | | |
| | | </style> |
| | | |
| | | <style lang="scss"> |
| | |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | const calcAlreadyReturned = (row) => { |
| | | // 妿 row.unQuantity å·²ç»æå¼ï¼ä»å端è·åçæªéè´§æ°éï¼ï¼ç´æ¥è¿å |
| | | if (row?.unQuantity !== undefined && row?.unQuantity !== null) { |
| | | return Number(row.unQuantity); |
| | | } |
| | | // å¦åæ ¹æ®æ»æ°éåå·²éè´§æ°éè®¡ç® |
| | | const total = Number(row?.shippingNum ?? row?.totalQuantity ?? 0); |
| | | const returned = Number(row?.returnQuantity ?? row?.num ?? 0); |
| | | const returned = Number(row?.returnNum ?? 0); |
| | | if (!Number.isFinite(total) || !Number.isFinite(returned)) return 0; |
| | | return total - returned; |
| | | }; |
| | |
| | | // ç¶ææ¯å符串 |
| | | const statusStr = String(status).trim(); |
| | | |
| | | // å¦æç¶ææ¯"å·²æ¤é"ï¼ç´æ¥è¿å |
| | | if (statusStr === 'å·²æ¤é') { |
| | | return 'å·²æ¤é'; |
| | | } |
| | | |
| | | // 妿已åè´§ï¼æåè´§æ¥ææè½¦çå·ï¼ï¼æ¾ç¤º"å·²åè´§" |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return 'å·²åè´§'; |
| | | } |
| | | |
| | | const statusTextMap = { |
| | | 'å¾
åè´§': 'å¾
åè´§', |
| | | 'å¾
å®¡æ ¸': 'å¾
å®¡æ ¸', |
| | | 'å®¡æ ¸ä¸': 'å®¡æ ¸ä¸', |
| | | 'åè´§ä¸': 'åè´§ä¸', |
| | | 'å®¡æ ¸æç»': 'å®¡æ ¸æç»', |
| | | 'å®¡æ ¸éè¿': 'å®¡æ ¸éè¿', |
| | | 'å·²åè´§': 'å·²åè´§', |
| | | 'å·²æ¤é': 'å·²æ¤é' |
| | | }; |
| | | return statusTextMap[statusStr] || 'å¾
åè´§'; |
| | | |
| | | // å¦æç¶æå¨æ å°è¡¨ä¸ï¼ç´æ¥è¿åå¯¹åºææ¬ |
| | | if (statusTextMap[statusStr]) { |
| | | return statusTextMap[statusStr]; |
| | | } |
| | | |
| | | return 'å¾
åè´§'; |
| | | }; |
| | | |
| | | /** |
| | |
| | | // ç¶ææ¯å符串 |
| | | const statusStr = String(status).trim(); |
| | | |
| | | // å¦æç¶ææ¯"å·²æ¤é"ï¼æ¾ç¤ºæ©è² |
| | | if (statusStr === 'å·²æ¤é') { |
| | | return 'warning'; |
| | | } |
| | | |
| | | // 妿已åè´§ï¼æåè´§æ¥ææè½¦çå·ï¼ï¼æ¾ç¤ºç»¿è² |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return 'success'; |
| | | } |
| | | |
| | | const typeTextMap = { |
| | | 'å¾
åè´§': 'info', |
| | | 'å¾
å®¡æ ¸': 'info', |
| | |
| | | 'å®¡æ ¸æç»': 'danger', |
| | | 'å·²æ¤é': 'warning', |
| | | 'å®¡æ ¸éè¿': 'success', |
| | | 'å·²åè´§': 'success' |
| | | 'å·²åè´§': 'success', |
| | | 'åè´§ä¸': 'warning' |
| | | }; |
| | | return typeTextMap[statusStr] || 'info'; |
| | | |
| | | // å¦æç¶æå¨æ å°è¡¨ä¸ï¼ç´æ¥è¿å对åºç±»å |
| | | if (typeTextMap[statusStr]) { |
| | | return typeTextMap[statusStr]; |
| | | } |
| | | |
| | | return 'info'; |
| | | }; |
| | | |
| | | /** |