From 50dcd8345bc5d7baa6c1c8d914793175a86d0b50 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 11 六月 2026 13:53:40 +0800
Subject: [PATCH] 修改销售台账工艺路线配置页面,增加导出工艺路线
---
src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue | 120 +++++++++++++++++++---------------------
src/views/salesManagement/salesLedger/index.vue | 55 +++++++++++++++++
2 files changed, 110 insertions(+), 65 deletions(-)
diff --git a/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue b/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
index f400877..606d86c 100644
--- a/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
+++ b/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
@@ -16,20 +16,6 @@
<span v-else style="color: #e6a23c;">鏈粦瀹�</span>
</div>
</div>
- <div class="export-toolbar">
- <el-date-picker
- v-model="exportDateRange"
- type="daterange"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- clearable
- style="width: 280px;"
- />
- <el-button type="success" plain @click="exportSelectedSteps">瀵煎嚭宸插嬀閫�</el-button>
- </div>
</div>
<el-select
v-model="selectedRouteId"
@@ -51,7 +37,7 @@
<div style="font-weight: 600; margin-bottom: 8px;">姝ラ棰勮</div>
<div style="font-size: 12px; color: #909399; margin-bottom: 10px;">
- 鏍规嵁鎵�閫夐厤缃睍绀烘祦绋嬪浘
+ 鏍规嵁鎵�閫夐厤缃睍绀烘祦绋嬪浘锛屽嬀閫夎〃绀鸿宸ュ簭宸插畬鎴�
</div>
</el-col>
@@ -65,12 +51,15 @@
>
<div class="process-diagram-node">
<el-checkbox
- v-model="step.checked"
+ v-model="step.isCompleted"
class="process-diagram-checkbox"
- @change="() => handleStepCheckedChange(step)"
+ @change="() => handleStepCompletedChange(step)"
/>
<div class="process-diagram-index">{{ idx + 1 }}</div>
<div class="process-diagram-name">{{ step.processName }}</div>
+ <div class="process-diagram-status" :class="{ 'is-done': Number(step.isCompleted) === 1 }">
+ {{ Number(step.isCompleted) === 1 ? "宸插畬鎴�" : "鏈畬鎴�" }}
+ </div>
</div>
<div v-if="idx < steps.length - 1" class="process-diagram-arrow">鈫�</div>
</div>
@@ -102,6 +91,8 @@
visible: { type: Boolean, default: false },
// 鎵撳紑寮圭獥鏃剁殑鍥炴樉锛氳嫢涓氬姟宸茬粦瀹氬伐鑹鸿矾绾垮垯浼犲叆璇� routeId锛涘惁鍒欓粯璁ゅ睍绀哄垪琛ㄧ涓�鏉�
defaultRouteId: { type: [Number, String, null], default: null },
+ // 鎵撳紑寮圭獥鏃剁殑宸ュ簭瀹屾垚璁板綍鍥炴樉
+ defaultRecordList: { type: Array, default: () => [] },
// 椤甸潰鎻愮ず锛氳鍗曞凡缁戝畾鐨勫伐鑹鸿矾绾垮悕绉�
boundRouteName: { type: String, default: "" },
});
@@ -120,18 +111,17 @@
const routeList = ref([]);
const selectedRouteId = ref(null);
const steps = ref([]);
-const exportDateRange = ref([]);
const saving = ref(false);
const normalizeStepsFromApi = (list) => {
if (!Array.isArray(list)) return [];
return list.map((s, idx) => ({
stepId: s.stepId ?? s.id ?? null,
+ processRouteItemId: s.processRouteItemId ?? s.process_route_item_id ?? s.id ?? null,
processId: s.processId ?? s.process_id ?? s.id ?? null,
processName: s.processName ?? s.process_name ?? s.name ?? "",
sortNo: s.sortNo ?? idx + 1,
- isCompleted: Number(s.isCompleted ?? s.completed ?? 0),
- checked: Boolean(s.checked ?? false),
+ isCompleted: Boolean(Number(s.isCompleted ?? s.completed ?? 0)),
}));
};
@@ -142,6 +132,27 @@
processRouteName: r.processRouteName ?? r.routeName ?? r.name ?? "",
isDefault: Boolean(r.isDefault),
}));
+};
+
+const applyRecordListToSteps = (stepList, recordList) => {
+ if (!Array.isArray(stepList) || stepList.length === 0) return stepList;
+ if (!Array.isArray(recordList) || recordList.length === 0) return stepList;
+
+ const recordMap = new Map(
+ recordList
+ .filter((item) => item && item.processRouteItemId !== null && item.processRouteItemId !== undefined)
+ .map((item) => [String(item.processRouteItemId), item])
+ );
+
+ return stepList.map((step) => {
+ const matched = recordMap.get(String(step.processRouteItemId));
+ if (!matched) return step;
+ return {
+ ...step,
+ isCompleted: Boolean(Number(matched.isCompleted ?? 0)),
+ completedTime: matched.completedTime ?? matched.completed_time ?? null,
+ };
+ });
};
const fetchRouteList = async () => {
@@ -158,7 +169,12 @@
}
const res = await salesProcessFlowConfigItemList(routeId);
const raw = res?.data ?? res ?? [];
- steps.value = normalizeStepsFromApi(raw);
+ const normalizedSteps = normalizeStepsFromApi(raw);
+ if (String(routeId) === String(props.defaultRouteId)) {
+ steps.value = applyRecordListToSteps(normalizedSteps, props.defaultRecordList);
+ return;
+ }
+ steps.value = normalizedSteps;
};
watch(
@@ -189,8 +205,8 @@
await fetchRouteSteps(selectedRouteId.value);
};
-const handleStepCheckedChange = step => {
- step.checked = Boolean(step.checked);
+const handleStepCompletedChange = (step) => {
+ step.isCompleted = Boolean(step.isCompleted);
};
const handleClose = () => {
@@ -206,44 +222,18 @@
}
saving.value = true;
try {
- emit("confirm", selectedRouteId.value);
+ emit("confirm", {
+ routeId: selectedRouteId.value,
+ recordList: steps.value.map((step) => ({
+ processRouteItemId: step.processRouteItemId,
+ isCompleted: Number(step.isCompleted ?? 0),
+ })),
+ });
} catch (e) {
proxy?.$modal?.msgError?.("纭澶辫触锛岃绋嶅悗閲嶈瘯");
} finally {
saving.value = false;
}
-};
-
-const exportSelectedSteps = () => {
- const selectedSteps = steps.value.filter(step => step.checked);
- if (selectedSteps.length === 0) {
- proxy?.$modal?.msgWarning?.("璇峰厛鍕鹃�夎瀵煎嚭鐨勫伐搴�");
- return;
- }
- const payload = {
- exportDateRange: Array.isArray(exportDateRange.value) ? exportDateRange.value : [],
- routeId: selectedRouteId.value,
- routeName: routeList.value.find(item => String(item.routeId) === String(selectedRouteId.value))?.processRouteName || "",
- steps: selectedSteps.map(step => ({
- processId: step.processId,
- processName: step.processName,
- sortNo: step.sortNo,
- isCompleted: Number(step.isCompleted ?? 0),
- })),
- };
- const blob = new Blob([JSON.stringify(payload, null, 2)], {
- type: "application/json;charset=utf-8",
- });
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- const dateText =
- Array.isArray(exportDateRange.value) && exportDateRange.value.length === 2
- ? `${exportDateRange.value[0]}_${exportDateRange.value[1]}`
- : "all";
- a.href = url;
- a.download = `宸ヨ壓璺嚎瀵煎嚭_${dateText}.json`;
- a.click();
- URL.revokeObjectURL(url);
};
</script>
@@ -299,6 +289,17 @@
text-overflow: ellipsis;
}
+.process-diagram-status {
+ margin-top: 4px;
+ font-size: 12px;
+ color: #909399;
+}
+
+.process-diagram-status.is-done {
+ color: #67c23a;
+ font-weight: 600;
+}
+
.process-diagram-arrow {
font-size: 18px;
color: #909399;
@@ -326,12 +327,5 @@
justify-content: space-between;
align-items: flex-start;
gap: 16px;
-}
-
-.export-toolbar {
- display: flex;
- align-items: center;
- gap: 10px;
- flex-wrap: wrap;
}
</style>
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index cd38615..2dcf0a2 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -832,6 +832,7 @@
</div>
<ProcessFlowConfigSelectDialog v-model:visible="processFlowSelectDialogVisible"
:default-route-id="processFlowSelectDefaultRouteId"
+ :default-record-list="processFlowSelectDefaultRecordList"
:bound-route-name="processFlowSelectBoundRouteName"
@confirm="handleProcessFlowSelectConfirm" />
<div class="sales-ledger-toolbar-actions">
@@ -866,6 +867,17 @@
<el-button type="primary"
@click="handleBulkDelivery"
:disabled="isBatchButtonDisabled('delivery')">鍙戣揣</el-button>
+ <el-date-picker v-model="processRouteExportDateRange"
+ type="datetimerange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm:ss"
+ clearable
+ style="width: 340px;" />
+ <el-button @click="handleExportProcessRoute"
+ :disabled="isBatchButtonDisabled('export')">瀵煎嚭宸ヨ壓璺嚎</el-button>
</el-space>
<el-space v-else-if="activeStatusTab === 'stocked'"
wrap
@@ -2609,11 +2621,13 @@
});
const total = ref(0);
const fileList = ref([]);
+ const processRouteExportDateRange = ref([]);
// 宸ヨ壓璺嚎閰嶇疆閫夋嫨寮圭獥锛堢粦瀹氬埌鍙拌处浜у搧锛�
const processFlowSelectDialogVisible = ref(false);
const processFlowSelectLedgerRow = ref(null);
const processFlowSelectDefaultRouteId = ref(null);
+ const processFlowSelectDefaultRecordList = ref([]);
const processFlowSelectBoundRouteId = ref(null);
const processFlowSelectBoundRouteName = ref("");
@@ -4282,6 +4296,7 @@
processFlowSelectLedgerRow.value = ledgerRow;
processFlowSelectDefaultRouteId.value = null;
+ processFlowSelectDefaultRecordList.value = [];
processFlowSelectBoundRouteId.value = null;
processFlowSelectBoundRouteName.value = "";
@@ -4291,25 +4306,29 @@
const boundId = info?.processRouteId ?? info?.routeId ?? info?.id ?? null;
const boundName =
info?.processRouteName ?? info?.routeName ?? info?.name ?? "";
+ const recordList = Array.isArray(info?.recordList) ? info.recordList : [];
processFlowSelectBoundRouteId.value = boundId;
processFlowSelectBoundRouteName.value = boundName;
processFlowSelectDefaultRouteId.value = boundId;
+ processFlowSelectDefaultRecordList.value = recordList;
} catch (e) {
// 鏌ヨ澶辫触鏃舵寜鏈粦瀹氬鐞嗭紝涓嶉樆濉炲脊绐�
processFlowSelectBoundRouteId.value = null;
processFlowSelectBoundRouteName.value = "";
processFlowSelectDefaultRouteId.value = null;
+ processFlowSelectDefaultRecordList.value = [];
}
processFlowSelectDialogVisible.value = true;
};
// 缁戝畾宸ヨ壓璺嚎鍒板綋鍓嶅彴璐︽暟鎹�
- const handleProcessFlowSelectConfirm = async routeId => {
+ const handleProcessFlowSelectConfirm = async payload => {
const ledgerRow = processFlowSelectLedgerRow.value;
if (!ledgerRow?.id) return;
- const finalRouteId = routeId ?? null;
+ const finalRouteId = payload?.routeId ?? payload ?? null;
+ const recordList = Array.isArray(payload?.recordList) ? payload.recordList : [];
if (!finalRouteId) return;
const oldRouteId = processFlowSelectBoundRouteId.value;
@@ -4339,6 +4358,7 @@
await saleProcessBind({
salesLedgerId: ledgerRow.id,
processRouteId: finalRouteId,
+ recordList,
});
proxy?.$modal?.msgSuccess?.("宸ヨ壓璺嚎缁戝畾鎴愬姛");
@@ -5292,6 +5312,37 @@
proxy.download("/sales/ledger/exportWithProducts", params, "閿�鍞彴璐�.xlsx");
};
+
+ const handleExportProcessRoute = () => {
+ if (selectedRows.value.length === 0) {
+ proxy?.$modal?.msgWarning?.("璇烽�夋嫨瑕佸鍑虹殑閿�鍞彴璐�");
+ return;
+ }
+ const salesLedgerIds = selectedRows.value
+ .map(item => item.id)
+ .filter(id => id !== null && id !== undefined && id !== "");
+ if (salesLedgerIds.length === 0) {
+ proxy?.$modal?.msgWarning?.("璇烽�夋嫨瑕佸鍑虹殑閿�鍞彴璐�");
+ return;
+ }
+
+ const params = {
+ salesLedgerIds: salesLedgerIds.join(","),
+ };
+ if (
+ Array.isArray(processRouteExportDateRange.value) &&
+ processRouteExportDateRange.value.length === 2
+ ) {
+ params.completedTimeStart = processRouteExportDateRange.value[0];
+ params.completedTimeEnd = processRouteExportDateRange.value[1];
+ }
+
+ proxy.download(
+ "/sales/ledger/exportProcessRoute",
+ params,
+ "閿�鍞彴璐﹀伐鑹鸿矾绾垮鍑�.xlsx"
+ );
+ };
/** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
const isProductShipped = product => {
if (!product) return false;
--
Gitblit v1.9.3