From b4506d63201a897dc50a5e2a998705a2c148deee Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 12 五月 2026 09:10:04 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' into dev_浪潮
---
src/assets/AI/待办助手.png | 0
src/assets/AI/质量助手.png | 0
src/views/salesManagement/salesLedger/index.vue | 86 ++
src/views/inventoryManagement/dispatchLog/Record.vue | 897 +++++++++++-----------
src/views/salesManagement/returnOrder/components/formDia.vue | 4
src/assets/AI/仓储助手.png | 0
public/favicon.ico | 0
src/assets/AI/采购助手.png | 0
src/views/equipmentManagement/ledger/index.vue | 29
src/assets/AI/销售助手.png | 0
src/views/inventoryManagement/receiptManagement/Record.vue | 12
src/views/equipmentManagement/upkeep/index.vue | 9
src/views/salesManagement/deliveryLedger/index.vue | 636 ++++++++++------
src/assets/AI/生产助手.png | 0
multiple/multiple-build.js | 20
src/assets/AI/财务助手.png | 0
multiple/assets/logo/BTYXLogo.png | 0
src/assets/logo/logo.png | 0
src/components/AIChatSidebar/index.vue | 2
src/router/index.js | 14
/dev/null | 565 --------------
multiple/assets/logo/ZXZNLogo.png | 0
multiple/assets/favicon/ZXZNfavicon.ico | 0
src/views/equipmentManagement/upkeep/Form/formDia.vue | 18
multiple/assets/favicon/BTYXfavicon.ico | 0
25 files changed, 1,016 insertions(+), 1,276 deletions(-)
diff --git a/multiple/assets/favicon/BTYXfavicon.ico b/multiple/assets/favicon/BTYXfavicon.ico
new file mode 100644
index 0000000..8da0f2a
--- /dev/null
+++ b/multiple/assets/favicon/BTYXfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/ZXZNfavicon.ico b/multiple/assets/favicon/ZXZNfavicon.ico
new file mode 100644
index 0000000..73bc9dd
--- /dev/null
+++ b/multiple/assets/favicon/ZXZNfavicon.ico
Binary files differ
diff --git a/multiple/assets/logo/BTYXLogo.png b/multiple/assets/logo/BTYXLogo.png
new file mode 100644
index 0000000..0890259
--- /dev/null
+++ b/multiple/assets/logo/BTYXLogo.png
Binary files differ
diff --git a/multiple/assets/logo/ZXZNLogo.png b/multiple/assets/logo/ZXZNLogo.png
new file mode 100644
index 0000000..83df55b
--- /dev/null
+++ b/multiple/assets/logo/ZXZNLogo.png
Binary files differ
diff --git a/multiple/multiple-build.js b/multiple/multiple-build.js
index 8e078e1..d87b333 100644
--- a/multiple/multiple-build.js
+++ b/multiple/multiple-build.js
@@ -24,6 +24,19 @@
const envFilePath = path.join(process.cwd(), '.env.production.local');
+async function copyFileWithOverwrite(src, dest) {
+ await fs.mkdir(path.dirname(dest), { recursive: true });
+ if (fsSync.existsSync(dest)) {
+ try {
+ await fs.chmod(dest, 0o666);
+ } catch {
+ // Ignore chmod failure and try delete directly.
+ }
+ await fs.rm(dest, { force: true });
+ }
+ await fs.copyFile(src, dest);
+}
+
try {
// 1锔忊儯 鐢熸垚 .env
console.log("=======鐢熸垚.env=======");
@@ -41,9 +54,8 @@
const backupFile = path.join(replacePath, config[key]);
const replaceFile = path.join(resourcePath, companyMap[key]);
- await fs.mkdir(path.dirname(backupFile), { recursive: true });
- await fs.copyFile(originFile, backupFile);
- await fs.copyFile(replaceFile, originFile);
+ await copyFileWithOverwrite(originFile, backupFile);
+ await copyFileWithOverwrite(replaceFile, originFile);
}
console.log("=====寮�濮嬫墦鍖�======");
@@ -66,7 +78,7 @@
const originFile = path.join(rootPath, config[key]);
const backupFile = path.join(replacePath, config[key]);
- await fs.copyFile(backupFile, originFile);
+ await copyFileWithOverwrite(backupFile, originFile);
}
await fs.rm(replacePath, { recursive: true, force: true });
console.log(`馃棏锔� 宸插垹闄� ${replacePath}`);
diff --git a/public/favicon.ico b/public/favicon.ico
index e263760..2fa05d5 100644
--- a/public/favicon.ico
+++ b/public/favicon.ico
Binary files differ
diff --git a/src/api/oaSystem/projectManagement.js b/src/api/oaSystem/projectManagement.js
deleted file mode 100644
index 56c9287..0000000
--- a/src/api/oaSystem/projectManagement.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import request from "@/utils/request";
-import { parseStrEmpty } from "@/utils/ruoyi";
-
-// 鏌ヨ椤圭洰鍒楄〃
-export function listProject(query) {
- return request({
- url: "/oA/project/listPage",
- method: "get",
- params: query
- });
-}
-
-// 鏌ヨ椤圭洰鍒楄〃璇︾粏
-export function getProject(query) {
- return request({
- url: "oA/project/getList",
- method: "get"
- });
-}
-
-// 鏂板椤圭洰
-export function addProject(data) {
- return request({
- url: "/oA/project/add",
- method: "post",
- data: data
- });
-}
-
-// 淇敼椤圭洰
-export function updateProject(data) {
- return request({
- url: "/oA/project/update",
- method: "post",
- data: data
- });
-}
-
-// 鍒犻櫎椤圭洰
-export function delProject(projectId) {
- return request({
- url: "/oA/project/delete/" + projectId,
- method: "delete"
- });
-}
-// 瀵煎嚭椤圭洰
-export function exportProject(data) {
- return request({
- url: "/oA/project/export",
- method: "post",
- data: data
- });
-}
-// // 鎵归噺鍒犻櫎椤圭洰
-// export function delProjectBatch(projectIds) {
-// return request({
-// url: "/oaSystem/project/batch",
-// method: "delete",
-// data: projectIds
-// });
-// }
-
-// 鏍规嵁椤圭洰闃舵id鏌ヨ椤圭洰闃舵浠诲姟鍒楄〃
-export function listProjectTask(phaseId) {
- return request({
- url: "/oA/projectPhaseTask/listByPhaseId/"+ phaseId,
- method: "get"
- });
-}
-
-// // 鏌ヨ椤圭洰浠诲姟璇︾粏
-// export function getProjectTask(taskId) {
-// return request({
-// url: "/oaSystem/project/task/" + taskId,
-// method: "get"
-// });
-// }
-
-// 鏂板椤圭洰闃舵浠诲姟
-export function addProjectTask(data) {
- return request({
- url: "/oA/projectPhaseTask/add",
- method: "post",
- data: data
- });
-}
-
-// 淇敼椤圭洰闃舵浠诲姟
-export function updateProjectTask(data) {
- return request({
- url: "/oA/projectPhaseTask/update",
- method: "post",
- data: data
- });
-}
-
-// 鍒犻櫎椤圭洰闃舵浠诲姟
-export function delProjectTask(taskId) {
- return request({
- url: "/oA/projectPhaseTask/delete/" + taskId,
- method: "delete"
- });
-}
-
-// 椤圭洰id鏌ヨ椤圭洰闃舵鍒楄〃
-export function listProjectPhase(projectId) {
- return request({
- url: "/oA/projectPhase/listByProjectId/" + projectId,
- method: "get"
- });
-}
-// 鏂板椤圭洰闃舵
-export function addProjectPhase(data) {
- return request({
- url: "/oA/projectPhase/add",
- method: "post",
- data: data
- });
-}
-
-// 淇敼椤圭洰闃舵
-export function updateProjectPhase(data) {
- return request({
- url: "/oA/projectPhase/update",
- method: "post",
- data: data
- });
-
-}
-// 鍒犻櫎椤圭洰闃舵
-export function delProjectPhase(phaseId) {
- return request({
- url: "/oA/projectPhase/delete/" + phaseId,
- method: "delete"
- })
-}
-//
-
-// // 鏌ヨ椤圭洰閲岀▼纰戝垪琛�
-// export function listProjectMilestone(query) {
-// return request({
-// url: "/oaSystem/project/milestone/list",
-// method: "get",
-// params: query
-// });
-// }
-
-// // 椤圭洰缁熻淇℃伅
-// export function getProjectStatistics() {
-// return request({
-// url: "/oaSystem/project/statistics",
-// method: "get"
-// });
-// }
\ No newline at end of file
diff --git "a/src/assets/AI/\344\273\223\345\202\250\345\212\251\346\211\213.png" "b/src/assets/AI/\344\273\223\345\202\250\345\212\251\346\211\213.png"
new file mode 100644
index 0000000..3aae283
--- /dev/null
+++ "b/src/assets/AI/\344\273\223\345\202\250\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\345\276\205\345\212\236\345\212\251\346\211\213.png" "b/src/assets/AI/\345\276\205\345\212\236\345\212\251\346\211\213.png"
index d8e5e80..54f4d32 100644
--- "a/src/assets/AI/\345\276\205\345\212\236\345\212\251\346\211\213.png"
+++ "b/src/assets/AI/\345\276\205\345\212\236\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\347\224\237\344\272\247\345\212\251\346\211\213.png" "b/src/assets/AI/\347\224\237\344\272\247\345\212\251\346\211\213.png"
index 2d5d3b5..998b9df 100644
--- "a/src/assets/AI/\347\224\237\344\272\247\345\212\251\346\211\213.png"
+++ "b/src/assets/AI/\347\224\237\344\272\247\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\350\200\201\346\235\277\345\212\251\346\211\213.png" "b/src/assets/AI/\350\200\201\346\235\277\345\212\251\346\211\213.png"
deleted file mode 100644
index 1b5030d..0000000
--- "a/src/assets/AI/\350\200\201\346\235\277\345\212\251\346\211\213.png"
+++ /dev/null
Binary files differ
diff --git "a/src/assets/AI/\350\264\242\345\212\241\345\212\251\346\211\213.png" "b/src/assets/AI/\350\264\242\345\212\241\345\212\251\346\211\213.png"
index fd6c90c..8932bff 100644
--- "a/src/assets/AI/\350\264\242\345\212\241\345\212\251\346\211\213.png"
+++ "b/src/assets/AI/\350\264\242\345\212\241\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\350\264\250\351\207\217\345\212\251\346\211\213.png" "b/src/assets/AI/\350\264\250\351\207\217\345\212\251\346\211\213.png"
new file mode 100644
index 0000000..e3ab7e1
--- /dev/null
+++ "b/src/assets/AI/\350\264\250\351\207\217\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\351\207\207\350\264\255\345\212\251\346\211\213.png" "b/src/assets/AI/\351\207\207\350\264\255\345\212\251\346\211\213.png"
index 3eba34a..aea0fd0 100644
--- "a/src/assets/AI/\351\207\207\350\264\255\345\212\251\346\211\213.png"
+++ "b/src/assets/AI/\351\207\207\350\264\255\345\212\251\346\211\213.png"
Binary files differ
diff --git "a/src/assets/AI/\351\224\200\345\224\256\345\212\251\346\211\213.png" "b/src/assets/AI/\351\224\200\345\224\256\345\212\251\346\211\213.png"
index 8382efa..b8087db 100644
--- "a/src/assets/AI/\351\224\200\345\224\256\345\212\251\346\211\213.png"
+++ "b/src/assets/AI/\351\224\200\345\224\256\345\212\251\346\211\213.png"
Binary files differ
diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png
index 91a5896..a5831b8 100644
--- a/src/assets/logo/logo.png
+++ b/src/assets/logo/logo.png
Binary files differ
diff --git a/src/components/AIChatSidebar/index.vue b/src/components/AIChatSidebar/index.vue
index 5d81355..d40d863 100644
--- a/src/components/AIChatSidebar/index.vue
+++ b/src/components/AIChatSidebar/index.vue
@@ -530,7 +530,7 @@
import purchaseAssistantAvatar from '@/assets/AI/閲囪喘鍔╂墜.png'
import productionAssistantAvatar from '@/assets/AI/鐢熶骇鍔╂墜.png'
import financeAssistantAvatar from '@/assets/AI/璐㈠姟鍔╂墜.png'
-import bossAssistantAvatar from '@/assets/AI/鑰佹澘鍔╂墜.png'
+import bossAssistantAvatar from '@/assets/AI/寰呭姙鍔╂墜.png'
const emit = defineEmits(['header-extra-action'])
diff --git a/src/router/index.js b/src/router/index.js
index 2c98627..aea22ca 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -118,20 +118,6 @@
name: "DeviceInfo",
meta: { title: "璁惧淇℃伅", icon: "monitor" },
},
- // 娣诲姞椤圭洰璇︽儏椤甸潰璺敱閰嶇疆
- {
- path: "/oaSystem/projectManagement/projectDetail",
- component: Layout,
- hidden: true,
- children: [
- {
- path: ":projectId",
- component: () => import("@/views/oaSystem/projectManagement/projectDetail.vue"),
- name: "ProjectDetail",
- meta: { title: "椤圭洰璇︽儏", activeMenu: "/oaSystem/projectManagement" },
- },
- ],
- },
{
path: "/projectManagement/Management/detail",
component: Layout,
diff --git a/src/views/equipmentManagement/ledger/index.vue b/src/views/equipmentManagement/ledger/index.vue
index 7ba9401..93b9e6d 100644
--- a/src/views/equipmentManagement/ledger/index.vue
+++ b/src/views/equipmentManagement/ledger/index.vue
@@ -298,7 +298,34 @@
const showQRCode = async (row) => {
// 鐩存帴浣跨敤URL锛屼笉瑕佺敤JSON.stringify鍖呰
const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id;
- qrCodeUrl.value = await QRCode.toDataURL(qrContent);
+ const qrDataUrl = await QRCode.toDataURL(qrContent, { width: 200, margin: 2 });
+
+ // 鍒涘缓canvas鍚堟垚甯﹀悕绉扮殑浜岀淮鐮佸浘鐗�
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ const qrSize = 200;
+ const textHeight = 30;
+ const padding = 10;
+ canvas.width = qrSize + padding * 2;
+ canvas.height = qrSize + textHeight + padding * 2;
+
+ // 濉厖鐧借壊鑳屾櫙
+ ctx.fillStyle = '#ffffff';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+ // 缁樺埗浜岀淮鐮�
+ const qrImg = new Image();
+ qrImg.src = qrDataUrl;
+ await new Promise((resolve) => { qrImg.onload = resolve; });
+ ctx.drawImage(qrImg, padding, padding, qrSize, qrSize);
+
+ // 缁樺埗璁惧鍚嶇О
+ ctx.fillStyle = '#333333';
+ ctx.font = 'bold 14px Arial';
+ ctx.textAlign = 'center';
+ ctx.fillText(row.deviceName || '', canvas.width / 2, qrSize + padding + 20);
+
+ qrCodeUrl.value = canvas.toDataURL('image/png');
qrRowData.value = row;
qrDialogVisible.value = true;
};
diff --git a/src/views/equipmentManagement/upkeep/Form/formDia.vue b/src/views/equipmentManagement/upkeep/Form/formDia.vue
index 66bf067..9550b08 100644
--- a/src/views/equipmentManagement/upkeep/Form/formDia.vue
+++ b/src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -67,6 +67,18 @@
</el-row>
<el-row>
<el-col :span="12">
+ <el-form-item label="璁惧椤圭洰" prop="machineryCategory">
+ <el-input
+ v-model.trim="form.machineryCategory"
+ placeholder="璇疯緭鍏ヨ澶囬」鐩�"
+ maxlength="100"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
<el-form-item label="浠诲姟棰戠巼" prop="frequencyType">
<el-select v-model="form.frequencyType" placeholder="璇烽�夋嫨" clearable>
<el-option label="姣忔棩" value="DAILY"/>
@@ -154,6 +166,7 @@
taskName: undefined,
// 褰曞叆浜猴細鍗曢�変竴涓敤鎴� id
inspector: undefined,
+ machineryCategory: "",
remarks: '',
frequencyType: '',
frequencyDetail: '',
@@ -165,7 +178,8 @@
rules: {
taskId: [{ required: true, message: "璇烽�夋嫨璁惧", trigger: "change" },],
inspector: [{ required: true, message: "璇烽�夋嫨褰曞叆浜�", trigger: "blur" },],
- registrationDate: [{ required: true, message: "璇烽�夋嫨鐧昏鏃堕棿", trigger: "change" }]
+ registrationDate: [{ required: true, message: "璇烽�夋嫨鐧昏鏃堕棿", trigger: "change" }],
+ machineryCategory: [{ required: true, message: "璇疯緭鍏ヨ澶囬」鐩�", trigger: "blur" }]
}
})
const { form, rules } = toRefs(data)
@@ -238,7 +252,7 @@
taskId: undefined,
taskName: undefined,
inspector: undefined,
- inspector: undefined,
+ machineryCategory: "",
remarks: '',
frequencyType: '',
frequencyDetail: '',
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 0ee99eb..2fc3eae 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -300,6 +300,12 @@
prop: "deviceModel",
},
{
+ label: "璁惧椤圭洰",
+ prop: "machineryCategory",
+ minWidth: 120,
+ formatData: cell => cell || "--",
+ },
+ {
prop: "frequencyType",
label: "棰戞",
minWidth: 150,
@@ -372,9 +378,10 @@
prop: "createUserName",
},
{
- label: "椤圭洰",
+ label: "璁惧椤圭洰",
align: "center",
prop: "machineryCategory",
+ formatData: cell => cell || "--",
},
// {
// label: "褰曞叆鏃ユ湡",
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index f41eaaa..dd47cb4 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -1,117 +1,110 @@
<template>
- <div>
- <div class="search_form" style="margin-bottom: 10px;">
- <div>
- <span class="search_title ml10">鍑哄簱鏃ユ湡锛�</span>
- <el-date-picker
- v-model="searchForm.timeStr"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- @change="handleQuery"
- />
- <span class="search_title ml10">鏉ユ簮锛�</span>
- <el-select v-model="searchForm.recordType"
- style="width: 240px"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option v-for="item in stockRecordTypeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"/>
- </el-select>
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
- </div>
- <div>
- <el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
- <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
- </div>
- </div>
- <div class="table_list">
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- style="width: 100%"
- height="calc(100vh - 18.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="outboundBatches"
- min-width="100"
- show-overflow-tooltip
+ <div>
+ <div class="search_form" style="margin-bottom: 10px">
+ <div>
+ <span class="search_title ml10">鍑哄簱鏃ユ湡锛�</span>
+ <el-date-picker
+ v-model="searchForm.timeStr"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ @change="handleQuery"
/>
- <el-table-column
- label="鍑哄簱鏃ユ湡"
- prop="createTime"
- show-overflow-tooltip
- />
- <el-table-column
- label="浜у搧澶х被"
- prop="productName"
- show-overflow-tooltip
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="model"
- show-overflow-tooltip
- />
- <el-table-column
- label="鎵瑰彿"
- prop="batchNo"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍗曚綅"
- prop="unit"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍑哄簱鏁伴噺"
- prop="stockOutNum"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍑哄簱浜�"
- prop="createBy"
- show-overflow-tooltip
- />
- <el-table-column label="鏉ユ簮"
- prop="recordType"
- show-overflow-tooltip>
+ <span class="search_title ml10">鏉ユ簮锛�</span>
+ <el-select
+ v-model="searchForm.recordType"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option
+ v-for="item in stockRecordTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ style="width: 100%"
+ height="calc(100vh - 18.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="outboundBatches"
+ min-width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍑哄簱鏃ユ湡"
+ prop="createTime"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="浜у搧澶х被"
+ prop="productName"
+ show-overflow-tooltip
+ />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
+ <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip />
+ <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
+ <el-table-column
+ label="鍑哄簱鏁伴噺"
+ prop="stockOutNum"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鍑哄簱浜�" prop="createBy" show-overflow-tooltip />
+ <el-table-column label="鏉ユ簮" prop="recordType" show-overflow-tooltip>
<template #default="scope">
{{ getRecordType(scope.row.recordType) }}
</template>
</el-table-column>
- <el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" show-overflow-tooltip>
- <template #default="scope">
- <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small">
- {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
- </el-tag>
- </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"
- />
- </div>
- </div>
+ <el-table-column
+ label="瀹℃壒鐘舵��"
+ prop="approvalStatus"
+ show-overflow-tooltip
+ >
+ <template #default="scope">
+ <el-tag
+ :type="getApprovalStatusTagType(scope.row.approvalStatus)"
+ size="small"
+ >
+ {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
+ </el-tag>
+ </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"
+ />
+ </div>
+ </div>
</template>
<script setup>
@@ -121,12 +114,13 @@
import useUserStore from "@/store/modules/user";
import { getCurrentDate } from "@/utils/index.js";
import {
- getStockOutPage,
- delPendingStockOut,
- batchApproveStockOutRecords,
+ getStockOutPage,
+ delPendingStockOut,
+ batchApproveStockOutRecords,
} from "@/api/inventoryManagement/stockOut.js";
import {
- findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions,
+ findAllQualifiedStockOutRecordTypeOptions,
+ findAllUnQualifiedStockOutRecordTypeOptions,
} from "@/api/basicData/enum.js";
const userStore = useUserStore();
@@ -137,8 +131,8 @@
// 鏉ユ簮绫诲瀷閫夐」
const stockRecordTypeOptions = ref([]);
const page = reactive({
- current: 1,
- size: 100,
+ current: 1,
+ size: 100,
});
const total = ref(0);
@@ -146,13 +140,13 @@
type: {
type: String,
required: true,
- default: '0'
+ default: "0",
},
topParentProductId: {
type: [String, Number],
- default: undefined
- }
-})
+ default: undefined,
+ },
+});
// 鎵撳嵃鐩稿叧
const printPreviewVisible = ref(false);
@@ -160,193 +154,215 @@
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const data = reactive({
- searchForm: {
- supplierName: "",
- timeStr: "",
+ searchForm: {
+ supplierName: "",
+ timeStr: "",
recordType: "",
- }
+ },
});
const { searchForm } = toRefs(data);
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
- page.current = 1;
- getList();
+ page.current = 1;
+ getList();
};
const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
};
const getList = () => {
- tableLoading.value = true;
- getStockOutPage({ ...searchForm.value, ...page, topParentProductId: props.topParentProductId })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.data.total;
- })
- .catch(() => {
- tableLoading.value = false;
- });
+ tableLoading.value = true;
+ getStockOutPage({
+ ...searchForm.value,
+ ...page,
+ topParentProductId: props.topParentProductId,
+ })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ tableData.value.map((item) => {
+ item.children = [];
+ });
+ total.value = res.data.total;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
};
const getRecordType = (recordType) => {
- return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
-}
+ return (
+ stockRecordTypeOptions.value.find((item) => item.value === recordType)
+ ?.label || ""
+ );
+};
const approvalStatusLabelMap = {
- 0: "寰呭鎵�",
- 1: "閫氳繃",
- 2: "椹冲洖",
- pending: "寰呭鎵�",
- approved: "閫氳繃",
- rejected: "椹冲洖",
- PENDING: "寰呭鎵�",
- APPROVED: "閫氳繃",
- REJECTED: "椹冲洖",
+ 0: "寰呭鎵�",
+ 1: "閫氳繃",
+ 2: "椹冲洖",
+ 3: "寰呯‘璁�",
+ pending: "寰呭鎵�",
+ approved: "閫氳繃",
+ rejected: "椹冲洖",
+ PENDING: "寰呭鎵�",
+ APPROVED: "閫氳繃",
+ REJECTED: "椹冲洖",
};
const getApprovalStatusLabel = (status) => {
- if (status === null || status === undefined || status === "") {
- return "寰呭鎵�";
- }
- return approvalStatusLabelMap[status] || "寰呭鎵�";
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鎵�";
+ }
+ return approvalStatusLabelMap[status] || "寰呭鎵�";
};
// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
const getApprovalStatusTagType = (status) => {
- if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
- if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
- return "warning";
+ if (
+ status === 1 ||
+ status === "1" ||
+ status === "approved" ||
+ status === "APPROVED"
+ )
+ return "success";
+ if (
+ status === 2 ||
+ status === "2" ||
+ status === "rejected" ||
+ status === "REJECTED"
+ )
+ return "danger";
+ return "warning";
};
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
- if (props.type === '0') {
- findAllQualifiedStockOutRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
- return
+ if (props.type === "0") {
+ findAllQualifiedStockOutRecordTypeOptions().then((res) => {
+ stockRecordTypeOptions.value = res.data;
+ });
+ return;
}
- findAllUnQualifiedStockOutRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
-}
+ findAllUnQualifiedStockOutRecordTypeOptions().then((res) => {
+ stockRecordTypeOptions.value = res.data;
+ });
+};
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.id);
- console.log("selection", selectedRows.value);
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter((item) => item.id);
+ console.log("selection", selectedRows.value);
};
const expandedRowKeys = ref([]);
const handleBatchApprove = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map((item) => item.id);
- ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
- type: "warning",
- distinguishCancelAndClose: true,
- })
- .then(() => {
- batchApproveStockOutRecords({ ids, approvalStatus: 1 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
- });
- })
- .catch((action) => {
- if (action === "cancel") {
- batchApproveStockOutRecords({ ids, approvalStatus: 2 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
- });
- return;
- }
- proxy.$modal.msg("宸插彇娑�");
- });
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map((item) => item.id);
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
+ confirmButtonText: "閫氳繃",
+ cancelButtonText: "椹冲洖",
+ type: "warning",
+ distinguishCancelAndClose: true,
+ })
+ .then(() => {
+ batchApproveStockOutRecords({ ids, approvalStatus: 1 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
+ });
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ batchApproveStockOutRecords({ ids, approvalStatus: 2 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ });
+ return;
+ }
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 瀵煎嚭
const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/stockOutRecord/exportStockOutRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/stockOutRecord/exportStockOutRecord",
+ { type: props.type },
+ props.type === "0" ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍒犻櫎
const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delPendingStockOut(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delPendingStockOut(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鎵撳嵃鍔熻兘
const handlePrint = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
- printData.value = [...selectedRows.value];
- console.log('鎵撳嵃鏁版嵁:', printData.value);
- printPreviewVisible.value = true;
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+ printData.value = [...selectedRows.value];
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+ printPreviewVisible.value = true;
};
// 鎵ц鎵撳嵃
const executePrint = () => {
- console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
- console.log('鎵撳嵃鏁版嵁:', printData.value);
-
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open('', '_blank', 'width=800,height=600');
-
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
+ console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+
+ // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+ const printWindow = window.open("", "_blank", "width=800,height=600");
+
+ // 鏋勫缓鎵撳嵃鍐呭
+ let printContent = `
<!DOCTYPE html>
<html>
<head>
@@ -480,10 +496,10 @@
</head>
<body>
`;
-
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
+
+ // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+ printData.value.forEach((item, index) => {
+ printContent += `
<div class="print-page">
<div class="delivery-note">
<div class="header">
@@ -503,7 +519,7 @@
</div>
<div class="info-row">
<span class="label">鍗曞彿锛�</span>
- <span class="value">${item.code || ''}</span>
+ <span class="value">${item.code || ""}</span>
</div>
</div>
@@ -521,12 +537,12 @@
</thead>
<tbody>
<tr>
- <td>${item.productName || '鐮傜伆鐮�'}</td>
- <td>${item.model || '鏍囧噯'}</td>
- <td>${item.unit || '鍧�'}</td>
- <td>${item.taxInclusiveUnitPrice || '0'}</td>
- <td>${item.inboundNum || '2000'}</td>
- <td>${item.taxInclusiveTotalPrice || '0'}</td>
+ <td>${item.productName || "鐮傜伆鐮�"}</td>
+ <td>${item.model || "鏍囧噯"}</td>
+ <td>${item.unit || "鍧�"}</td>
+ <td>${item.taxInclusiveUnitPrice || "0"}</td>
+ <td>${item.inboundNum || "2000"}</td>
+ <td>${item.taxInclusiveTotalPrice || "0"}</td>
</tr>
</tbody>
<tfoot>
@@ -535,8 +551,10 @@
<td class="total-value"></td>
<td class="total-value"></td>
<td class="total-value"></td>
- <td class="total-value">${item.inboundNum || '2000'}</td>
- <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td>
+ <td class="total-value">${item.inboundNum || "2000"}</td>
+ <td class="total-value">${
+ item.taxInclusiveTotalPrice || "0"
+ }</td>
</tr>
</tfoot>
</table>
@@ -560,7 +578,7 @@
<div class="footer-row">
<div class="footer-item">
<span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
+ <span class="value">${userStore.nickName || "鎾曞紑鍓�"}</span>
</div>
<div class="footer-item">
<span class="label">鎵撳嵃鏃ユ湡锛�</span>
@@ -571,51 +589,49 @@
</div>
</div>
`;
- });
-
- printContent += `
+ });
+
+ printContent += `
</body>
</html>
`;
-
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
-
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
- };
+
+ // 鍐欏叆鍐呭鍒版柊绐楀彛
+ printWindow.document.write(printContent);
+ printWindow.document.close();
+
+ // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+ printWindow.onload = () => {
+ setTimeout(() => {
+ printWindow.print();
+ printWindow.close();
+ printPreviewVisible.value = false;
+ }, 500);
+ };
};
-
-
// 鏍煎紡鍖栨棩鏈�
const formatDate = (dateString) => {
- if (!dateString) return getCurrentDate();
- const date = new Date(dateString);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- return `${year}/${month}/${day}`;
+ if (!dateString) return getCurrentDate();
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}/${month}/${day}`;
};
// 鏍煎紡鍖栨棩鏈熸椂闂�
const formatDateTime = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
};
onMounted(() => {
- getList();
+ getList();
fetchStockRecordTypeOptions();
});
@@ -630,169 +646,170 @@
<style scoped lang="scss">
.print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
+ }
}
.print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
- }
- }
-
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
+ text-align: center;
+
+ .el-button {
+ margin: 0 10px;
+ }
+ }
+
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
}
.print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
}
.delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
}
.header {
- text-align: center;
- margin-bottom: 8px;
-
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
-
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
}
.info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .info-row {
- line-height: 20px;
-
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 14px;
- }
-
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 14px;
- }
- }
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 14px;
+ }
+
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 14px;
+ }
+ }
}
.table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th, td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 14px;
- line-height: 1.4;
- }
-
- th {
- font-weight: bold;
- }
-
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
- font-weight: bold;
- }
- }
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
}
.footer-section {
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 20px;
- justify-content: space-between;
-
- .footer-item {
- display: flex;
- margin-right: 20px;
-
- .label {
- font-weight: bold;
- width: 80px;
- font-size: 14px;
- }
-
- .value {
- min-width: 80px;
- font-size: 14px;
- }
-
- &.address-item {
- .address-value {
- min-width: 200px;
- }
- }
- }
- }
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 14px;
+ }
+
+ .value {
+ min-width: 80px;
+ font-size: 14px;
+ }
+
+ &.address-item {
+ .address-value {
+ min-width: 200px;
+ }
+ }
+ }
+ }
}
@media print {
- .app-container {
- display: none;
- }
-
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
+ .app-container {
+ display: none;
+ }
+
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
}
</style>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index c9cb6ee..78ba5bb 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -50,6 +50,7 @@
height="calc(100vh - 18.5em)">
<el-table-column align="center"
type="selection"
+ :selectable="isRowSelectableForApprove"
width="55"/>
<el-table-column align="center"
label="搴忓彿"
@@ -181,6 +182,7 @@
APPROVED: "閫氳繃",
REJECTED: "椹冲洖",
};
+approvalStatusLabelMap[3] = "寰呯‘璁�";
const getApprovalStatusLabel = (status) => {
if (status === null || status === undefined || status === "") {
@@ -194,6 +196,14 @@
if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
return "warning";
+};
+
+const isPendingApproval = status => {
+ return status === 0 || status === "0" || status === "pending" || status === "PENDING" || status === null || status === undefined || status === "";
+};
+
+const isRowSelectableForApprove = row => {
+ return isPendingApproval(row?.approvalStatus);
};
const pageProductChange = obj => {
@@ -234,7 +244,7 @@
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = selection => {
- selectedRows.value = selection.filter(item => item.id);
+ selectedRows.value = selection.filter(item => item.id && isPendingApproval(item.approvalStatus));
};
const expandedRowKeys = ref([]);
diff --git a/src/views/oaSystem/projectManagement/components/milestoneList.vue b/src/views/oaSystem/projectManagement/components/milestoneList.vue
deleted file mode 100644
index ed31772..0000000
--- a/src/views/oaSystem/projectManagement/components/milestoneList.vue
+++ /dev/null
@@ -1,289 +0,0 @@
-// ... existing code ...
-<template>
- <div class="milestone-list-container">
- <el-timeline>
- <el-timeline-item
- v-for="milestone in milestoneList"
- :key="milestone.phaseId"
- :timestamp="milestone.endDate"
- >
- <el-card>
- <template #header>
- <div class="card-header">
- <span>{{ milestone.phaseName }}</span>
- <div class="milestone-actions">
- <el-button type="text" size="small" @click="handleEdit(milestone)">缂栬緫</el-button>
- <el-button type="text" size="small" @click="handleDelete(milestone)" danger>鍒犻櫎</el-button>
- </div>
- </div>
- </template>
- <div class="milestone-content">
- <p>{{ milestone.description }}</p>
- <div class="milestone-status">
- <el-tag :type="getStatusType(milestone.status)">{{ getStatusText(milestone.status) }}</el-tag>
- </div>
- </div>
- </el-card>
- </el-timeline-item>
- </el-timeline>
-
- <!-- 鏃犻噷绋嬬鏃剁殑鎻愮ず -->
- <div v-if="milestoneList.length === 0" class="empty-tip">
- <el-empty description="鏆傛棤閲岀▼纰戞暟鎹�" />
- </div>
-
- <!-- 缂栬緫閲岀▼纰戝璇濇 -->
- <el-dialog
- v-model="dialogVisible"
- :title="'缂栬緫閲岀▼纰�: ' + (form.phaseName || '')"
- width="600px"
- :close-on-click-modal="false"
- >
- <el-form
- ref="formRef"
- :model="form"
- :rules="rules"
- label-width="100px"
- >
- <el-form-item label="閲岀▼纰戝悕绉�" prop="phaseName">
- <el-input v-model="form.phaseName" placeholder="璇疯緭鍏ラ噷绋嬬鍚嶇О" />
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="form.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="form.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="鐘舵��" prop="status">
- <el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��">
- <el-option label="鏈紑濮�" value="notStarted" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸插欢杩�" value="delayed" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitEditForm">纭畾</el-button>
- <el-button @click="dialogVisible = false">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, onMounted, watch, reactive } from 'vue';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { getProject, listProjectPhase, updateProjectPhase,delProjectPhase } from '@/api/oaSystem/projectManagement';
-
-const props = defineProps({
- projectId: {
- type: String,
- required: true
- }
-});
-
-const emit = defineEmits(['refresh']);
-
-const milestoneList = ref([]);
-const dialogVisible = ref(false);
-const formRef = ref(null);
-const form = reactive({
- phaseId: '',
- phaseName: '',
- startDate: '',
- endDate: '',
- status: 'notStarted',
- projectId: props.projectId
-});
-
-// 琛ㄥ崟楠岃瘉瑙勫垯
-const rules = {
- phaseName: [
- { required: true, message: '璇疯緭鍏ラ噷绋嬬鍚嶇О', trigger: 'blur' },
- { min: 2, max: 50, message: '闀垮害鍦� 2 鍒� 50 涓瓧绗�', trigger: 'blur' }
- ],
- status: [
- { required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }
- ]
-};
-
-// 鑾峰彇閲岀▼纰戝垪琛�
-const getMilestoneList = async () => {
- try {
- listProjectPhase(props.projectId).then(res => {
- milestoneList.value = res.data.rows || res.data;
- // 鎸夌洰鏍囨棩鏈熸帓搴�
- // milestoneList.value.sort((a, b) => new Date(a.endDate) - new Date(b.endDate));
- })
- } catch (error) {
- ElMessage.error('鑾峰彇閲岀▼纰戝垪琛ㄥけ璐�');
- console.error('鑾峰彇閲岀▼纰戝垪琛ㄥけ璐�:', error);
- }
-};
-
-// 缂栬緫閲岀▼纰�
-const handleEdit = (milestone) => {
- // 澶嶅埗閲岀▼纰戞暟鎹埌琛ㄥ崟
- Object.assign(form, {
- phaseId: milestone.phaseId,
- phaseName: milestone.phaseName,
- description: milestone.description,
- endDate: milestone.endDate,
- status: milestone.status,
- projectId: props.projectId
- });
- dialogVisible.value = true;
-};
-
-// 鎻愪氦缂栬緫琛ㄥ崟
-const submitEditForm = async () => {
- try {
- await formRef.value.validate();
-
- // 鍙戦�佹洿鏂拌姹�
- const res = await updateProjectPhase(form);
-
- if (res.code === 200) {
- ElMessage.success('閲岀▼纰戠紪杈戞垚鍔�');
- dialogVisible.value = false;
- getMilestoneList(); // 鍒锋柊鍒楄〃
- emit('refresh'); // 閫氱煡鐖剁粍浠跺埛鏂�
- } else {
- ElMessage.error(res.msg || '閲岀▼纰戠紪杈戝け璐�');
- }
- } catch (error) {
- if (error.name === 'ValidationError') {
- // 琛ㄥ崟楠岃瘉澶辫触锛孍lement Plus浼氳嚜鍔ㄦ彁绀�
- return;
- }
- ElMessage.error('閲岀▼纰戠紪杈戝け璐�');
- console.error('缂栬緫閲岀▼纰戝け璐�:', error);
- }
-};
-
-// 鍒犻櫎閲岀▼纰�
-const handleDelete = (milestone) => {
- ElMessageBox.confirm(
- `纭畾瑕佸垹闄ら噷绋嬬 "${milestone.phaseName}" 鍚楋紵鍒犻櫎鍚庡皢鏃犳硶鎭㈠銆俙,
- '鍒犻櫎纭',
- {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- }
- )
- .then(async () => {
- try {
- // 璋冪敤鍒犻櫎API
- const res = await delProjectPhase(milestone.phaseId);
-
- if (res.code === 200) {
- ElMessage.success('閲岀▼纰戝垹闄ゆ垚鍔�');
- getMilestoneList(); // 鍒锋柊鍒楄〃
- emit('refresh'); // 閫氱煡鐖剁粍浠跺埛鏂�
- } else {
- ElMessage.error(res.msg || '閲岀▼纰戝垹闄ゅけ璐�');
- }
- } catch (error) {
- ElMessage.error('閲岀▼纰戝垹闄ゅけ璐�');
- console.error('鍒犻櫎閲岀▼纰戝け璐�:', error);
- }
- })
- .catch(() => {
- // 鐢ㄦ埛鍙栨秷鍒犻櫎
- ElMessage.info('宸插彇娑堝垹闄�');
- });
-};
-
-// 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status) => {
- const statusTypeMap = {
- notStarted: 'info',
- completed: 'success',
- delayed: 'danger'
- };
- return statusTypeMap[status] || 'default';
-};
-
-// 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status) => {
- const statusTextMap = {
- notStarted: '鏈紑濮�',
- completed: '宸插畬鎴�',
- delayed: '宸插欢杩�'
- };
- return statusTextMap[status] || status;
-};
-
-// 鐩戝惉椤圭洰ID鍙樺寲
-watch(() => props.projectId, () => {
- if (props.projectId) {
- getMilestoneList();
- }
-});
-
-// 鍒濆鍖�
-onMounted(() => {
- if (props.projectId) {
- getMilestoneList();
- }
-});
-</script>
-
-<style scoped>
-.milestone-list-container {
- padding: 10px 0;
-}
-
-.card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.milestone-actions {
- display: flex;
- gap: 10px;
-}
-
-.milestone-content {
- padding: 10px 0;
-}
-
-.milestone-status {
- margin-top: 10px;
-}
-
-.empty-tip {
- margin-top: 40px;
- text-align: center;
-}
-
-.dialog-footer {
- display: flex;
- justify-content: flex-end;
- gap: 10px;
-}
-</style>
diff --git a/src/views/oaSystem/projectManagement/components/phaseGoalList.vue b/src/views/oaSystem/projectManagement/components/phaseGoalList.vue
deleted file mode 100644
index 5054299..0000000
--- a/src/views/oaSystem/projectManagement/components/phaseGoalList.vue
+++ /dev/null
@@ -1,165 +0,0 @@
-
-<template>
- <div class="phase-goal-list-container">
- <el-table
- v-loading="loading"
- :data="phaseGoalList"
- style="width: 100%"
- >
- <el-table-column prop="phaseName" label="鎵�灞為樁娈�" width="180" />
- <el-table-column prop="taskName" label="鐩爣鍚嶇О" min-width="200" />
- <el-table-column prop="targetValue" label="鐩爣鍊�" width="120" />
- <el-table-column prop="currentValue" label="褰撳墠鍊�" width="120" />
- <el-table-column prop="unit" label="鍗曚綅" width="80" />
- <el-table-column prop="targetDate" label="鐩爣鏃ユ湡" width="120" />
- <el-table-column prop="status" label="鐘舵��" width="100">
- <template #default="scope">
- <el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="completionRate" label="瀹屾垚搴�" width="120">
- <template #default="scope">
- <el-progress :percentage="scope.row.completionRate" :stroke-width="6" />
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" width="150" fixed="right">
- <template #default="scope">
- <el-button type="text" size="small" @click="handleEdit(scope.row)">缂栬緫</el-button>
- <el-button type="text" size="small" @click="handleDelete(scope.row)" danger>鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <!-- 鏃犻樁娈电洰鏍囨椂鐨勬彁绀� -->
- <div v-if="!loading && phaseGoalList.length === 0" class="empty-tip">
- <el-empty description="鏆傛棤闃舵鐩爣鏁版嵁" />
- </div>
- </div>
-</template>
-
-<script setup>
-import { ref, onMounted, watch } from 'vue';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { listProjectPhase, updateProjectTask, delProjectTask } from '@/api/oaSystem/projectManagement';
-
-const props = defineProps({
- projectId: {
- type: String,
- required: true
- }
-});
-
-const emit = defineEmits(['refresh']);
-
-const phaseGoalList = ref([]);
-const loading = ref(true);
-
-// 鑾峰彇闃舵鐩爣鍒楄〃
-const getPhaseGoalList = async () => {
- loading.value = true;
- try {
- const { data } = await listProjectPhase(props.projectId);
- // 鍋囪phase鏁版嵁涓寘鍚簡鐩爣淇℃伅
- // 杩欓噷绠�鍖栧鐞嗭紝瀹為檯搴旇璋冪敤涓撻棬鐨勮幏鍙栭樁娈电洰鏍囩殑API
- const phases = data.rows || data;
- phaseGoalList.value = [];
-
- phases.forEach(phase => {
- if (phase.oaProjectPhaseTasks && phase.oaProjectPhaseTasks.length > 0) {
- phase.oaProjectPhaseTasks.forEach(goal => {
- phaseGoalList.value.push({
- ...goal,
- phaseName: phase.phaseName
- });
- });
- }
- });
- } catch (error) {
- ElMessage.error('鑾峰彇闃舵鐩爣鍒楄〃澶辫触');
- console.error('鑾峰彇闃舵鐩爣鍒楄〃澶辫触:', error);
- } finally {
- loading.value = false;
- }
-};
-
-// 缂栬緫闃舵鐩爣
-const handleEdit = (goal) => {
- // 瑙﹀彂鐖剁粍浠剁殑缂栬緫浜嬩欢锛屼紶閫掔洰鏍囨暟鎹�
- emit('editGoal', goal);
-};
-
-// 鍒犻櫎闃舵鐩爣
-const handleDelete = async (goal) => {
- try {
- await ElMessageBox.confirm(
- `纭畾瑕佸垹闄ょ洰鏍囥��${goal.taskName}銆嶅悧锛焋,
- '纭鍒犻櫎',
- {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- }
- );
-
- // 璋冪敤鍒犻櫎API
- await delProjectTask(goal.taskId);
- ElMessage.success('鍒犻櫎闃舵鐩爣鎴愬姛');
-
- // 鍒锋柊鍒楄〃
- getPhaseGoalList();
- emit('refresh');
- } catch (error) {
- if (error !== 'cancel') {
- ElMessage.error('鍒犻櫎闃舵鐩爣澶辫触');
- console.error('鍒犻櫎闃舵鐩爣澶辫触:', error);
- }
- }
-};
-
-// 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status) => {
- const statusTypeMap = {
- notStarted: 'info',
- inProgress: 'primary',
- completed: 'success',
- delayed: 'danger'
- };
- return statusTypeMap[status] || 'default';
-};
-
-// 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status) => {
- const statusTextMap = {
- notStarted: '鏈紑濮�',
- inProgress: '杩涜涓�',
- completed: '宸插畬鎴�',
- delayed: '宸插欢杩�'
- };
- return statusTextMap[status] || status;
-};
-
-// 鐩戝惉椤圭洰ID鍙樺寲
-watch(() => props.projectId, () => {
- if (props.projectId) {
- getPhaseGoalList();
- }
-});
-
-// 鍒濆鍖�
-onMounted(() => {
- if (props.projectId) {
- getPhaseGoalList();
- }
-});
-</script>
-
-<style scoped>
-.phase-goal-list-container {
- padding: 10px 0;
-}
-
-.empty-tip {
- margin-top: 40px;
- text-align: center;
-}
-</style>
diff --git a/src/views/oaSystem/projectManagement/components/projectForm.vue b/src/views/oaSystem/projectManagement/components/projectForm.vue
deleted file mode 100644
index 50b671c..0000000
--- a/src/views/oaSystem/projectManagement/components/projectForm.vue
+++ /dev/null
@@ -1,221 +0,0 @@
-<template>
- <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
- <el-form-item label="椤圭洰鍚嶇О" prop="projectName">
- <el-input
- v-model="form.projectName"
- placeholder="璇疯緭鍏ラ」鐩悕绉�"
- maxlength="50"
- />
- </el-form-item>
- <el-form-item label="椤圭洰鎻忚堪" prop="description">
- <el-input
- v-model="form.description"
- type="textarea"
- :rows="4"
- placeholder="璇疯緭鍏ラ」鐩弿杩�"
- />
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="form.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="form.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="椤圭洰璐熻矗浜�" prop="managerId">
- <!-- <el-input
- v-model="form.managerName"
- placeholder="璇烽�夋嫨椤圭洰璐熻矗浜�"
- readonly
- @focus="showUserSelect = true"
- /> -->
- <!-- <el-input
- v-model="userSearchKey"
- placeholder="鎼滅储鐢ㄦ埛"
- v-if="showUserSelect"
- @keyup.enter="searchUsers"
- style="margin-top: 10px"
- /> -->
- <el-select
- v-model="form.managerId"
- style="width: 100%; margin-top: 10px"
- @change="selectUser"
- filterable
- remote
- :remote-method="searchUsers"
- :loading="userLoading"
- placeholder="閫夋嫨椤圭洰璐熻矗浜�"
- >
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="椤圭洰瀹屾垚搴�" prop="completionRate">
- <el-slider v-model="form.completionRate" :max="100" />
- </el-form-item>
- <el-form-item label="椤圭洰鐘舵��" prop="status">
- <el-radio-group v-model="form.status">
- <el-radio label="planning">瑙勫垝涓�</el-radio>
- <el-radio label="inProgress">杩涜涓�</el-radio>
- <el-radio label="completed">宸插畬鎴�</el-radio>
- <el-radio label="paused">宸叉殏鍋�</el-radio>
- </el-radio-group>
- </el-form-item>
- </el-form>
-</template>
-
-<script setup>
-import { ref, watch, defineExpose } from 'vue';
-import { listUser } from '@/api/system/user';
-import { ElMessage } from 'element-plus';
-const props = defineProps({
- form: {
- type: Object,
- required: true
- },
- rules: {
- type: Object,
- required: true
- },
- visible: {
- type: Boolean,
- required: true
- }
-});
-
-const formRef = ref();
-const showUserSelect = ref(false);
-const userSearchKey = ref('');
-const userList = ref([]);
-const userLoading = ref(false);
-// 妯℃嫙鐢ㄦ埛鏁版嵁
-const mockUserData = [
- { userId: '1', nickName: '寮犱笁', userName: 'zhangsan' },
- { userId: '2', nickName: '鏉庡洓', userName: 'lisi' },
- { userId: '3', nickName: '鐜嬩簲', userName: 'wangwu' },
- { userId: '4', nickName: '璧靛叚', userName: 'zhaoliu' },
- { userId: '5', nickName: '閽变竷', userName: 'qianqi' },
- { userId: '6', nickName: '瀛欏叓', userName: 'sunba' },
- { userId: '7', nickName: '鍛ㄤ節', userName: 'zhoujiu' },
- { userId: '8', nickName: '鍚村崄', userName: 'wushi' }
-];
-// 鎼滅储鐢ㄦ埛
-const searchUsers = async (query) => {
- userLoading.value = true;
- try {
- // 妯℃嫙缃戠粶寤惰繜
- await new Promise(resolve => setTimeout(resolve, 300));
-
- // 姝g‘璁剧疆鐢ㄦ埛鍒楄〃
- if (!query) {
- userList.value = [...mockUserData];
- } else {
- userList.value = mockUserData.filter(user =>
- user.nickName.includes(query) || user.userName.includes(query)
- );
- }
- } catch (error) {
- console.error('鎼滅储鐢ㄦ埛澶辫触:', error);
- } finally {
- userLoading.value = false;
- }
-};
-
-// 閫夋嫨鐢ㄦ埛
-const selectUser = (userId) => {
- // 鍏堜粠userList鏌ユ壘锛屽鏋滄壘涓嶅埌鍐嶄粠mockUserData涓煡鎵�
- let selectedUser = userList.value.find(user => user.userId === userId);
- if (!selectedUser) {
- selectedUser = mockUserData.find(user => user.userId === userId);
- }
-
- // 浣跨敤Vue.set纭繚鍝嶅簲寮忔洿鏂�
- if (selectedUser) {
- Object.assign(props.form, { managerName: selectedUser.nickName });
- } else {
- Object.assign(props.form, { managerName: '' });
- }
- showUserSelect.value = false;
-};
-
-// 閲嶇疆琛ㄥ崟
-const resetFields = () => {
- if (formRef.value) {
- formRef.value.resetFields();
- }
- showUserSelect.value = false;
- userSearchKey.value = '';
- userList.value = [];
-};
-
-// 楠岃瘉琛ㄥ崟
-const validate = () => {
- return new Promise((resolve, reject) => {
- if (formRef.value) {
- formRef.value.validate((valid) => {
- if (valid) {
- // 棰濆楠岃瘉锛氱粨鏉熸棩鏈熶笉鑳芥棭浜庡紑濮嬫棩鏈�
- if (props.form.startDate && props.form.endDate) {
- const startDate = new Date(props.form.startDate);
- const endDate = new Date(props.form.endDate);
- if (endDate < startDate) {
- ElMessage.error('缁撴潫鏃ユ湡涓嶈兘鏃╀簬寮�濮嬫棩鏈�');
- reject(new Error('鏃ユ湡楠岃瘉澶辫触'));
- return;
- }
- }
- resolve();
- } else {
- reject(new Error('琛ㄥ崟楠岃瘉澶辫触'));
- }
- });
- } else {
- resolve();
- }
- });
-};
-
-// 鐩戝惉瀵硅瘽妗嗘樉绀虹姸鎬�
-watch(() => props.visible, (newVisible) => {
- if (!newVisible) {
- resetFields();
- // 寤惰繜閲嶇疆锛岀‘淇濇暟鎹凡缁忔彁浜ゅ埌鍚庣
- // setTimeout(() => {
- // resetFields();
- // }, 300);
- }
-});
-
-// 鏆撮湶鏂规硶
-defineExpose({
- resetFields,
- validate
-});
-</script>
-
-<style scoped>
-
-</style>
\ No newline at end of file
diff --git a/src/views/oaSystem/projectManagement/components/taskTree.vue b/src/views/oaSystem/projectManagement/components/taskTree.vue
deleted file mode 100644
index 03a1a15..0000000
--- a/src/views/oaSystem/projectManagement/components/taskTree.vue
+++ /dev/null
@@ -1,834 +0,0 @@
-<template>
- <div class="task-tree-container">
- <!-- 浠诲姟鏍戞搷浣滄寜閽� -->
- <div class="tree-actions mb10">
- <el-button type="primary" size="small" icon="Plus" @click="handleAddTask">娣诲姞浠诲姟</el-button>
- <el-button type="success" size="small" icon="RefreshRight" @click="refreshTree">鍒锋柊</el-button>
- <el-button type="info" size="small" icon="Filter" @click="toggleFilter">
- {{ showFilter ? '闅愯棌绛涢��' : '鏄剧ず绛涢��' }}
- </el-button>
- </div>
-
- <!-- 绛涢�夋潯浠� -->
- <div v-if="showFilter" class="filter-section mb10">
- <el-form :inline="true" :model="filterParams">
- <el-form-item label="浠诲姟鐘舵��">
- <el-select v-model="filterParams.status" placeholder="鍏ㄩ儴" clearable style="width: 120px">
- <el-option label="鏈紑濮�" value="notStarted" />
- <el-option label="杩涜涓�" value="inProgress" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸查�炬湡" value="overdue" />
- </el-select>
- </el-form-item>
- <el-form-item label="璐熻矗浜�">
- <el-input v-model="filterParams.assignee" placeholder="杈撳叆璐熻矗浜�" clearable style="width: 150px" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" size="small" @click="filterTree">绛涢��</el-button>
- <el-button size="small" @click="resetFilter">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
- </div>
-
- <!-- 浠诲姟鏍� -->
- <div class="tree-content">
- <el-tree
- v-loading="loading"
- :data="taskTreeData"
- :props="defaultProps"
- :expand-on-click-node="false"
- node-key="nodeId"
- ref="treeRef"
- @node-contextmenu="handleContextMenu"
- @node-click="handleNodeClick"
- >
- <template #default="{ node, data }">
- <!-- 鑺傜偣鍐呭 -->
- <div class="tree-node-content" :class="{ 'phase-node': data.type === 'phase', 'task-node': data.type === 'task' }">
- <!-- 鑺傜偣鍥炬爣 -->
- <div class="node-icon">
- <i v-if="data.type === 'phase'" class="el-icon-folder text-primary" />
- <i v-else-if="data.status === 'completed'" class="el-icon-circle-check text-success" />
- <i v-else-if="data.status === 'inProgress'" class="el-icon-circle-check text-primary" />
- <i v-else-if="data.status === 'overdue'" class="el-icon-alarm-clock text-danger" />
- <i v-else class="el-icon-circle-close text-gray-400" />
- </div>
-
- <!-- 鑺傜偣鏍囬鍜屾弿杩� -->
- <div class="node-info">
- <div class="node-title" :class="{ 'overdue-title': data.type === 'task' && data.status === 'overdue' }">
- {{ node.label }}
- <span v-if="data.type === 'task' && data.priority === 'high'" class="priority-tag">楂樹紭</span>
- <span v-else-if="data.type === 'task' && data.priority === 'medium'" class="priority-tag medium">涓紭</span>
- </div>
- <div v-if="data.description" class="node-description">{{ data.description }}</div>
-
- <!-- 浠诲姟鍏冧俊鎭� -->
- <div v-if="data.type === 'task'" class="task-meta">
- <span class="meta-item">
- <i class="el-icon-user"></i>
- {{ data.assigneeName || '鏈垎閰�' }}
- </span>
- <span class="meta-item">
- <i class="el-icon-calendar"></i>
- {{ formatDateRange(data.startDate, data.endDate) }}
- </span>
- </div>
- </div>
-
- <!-- 浠诲姟杩涘害鏉� -->
- <div v-if="data.type === 'task'" class="task-progress">
- <el-progress :percentage="data.progress || 0" :stroke-width="4" :show-text="false" />
- </div>
-
- <!-- 鎿嶄綔鎸夐挳 -->
- <div class="node-actions">
- <el-button
- v-if="data.type === 'task'"
- type="text"
- size="small"
- icon="Edit"
- @click.stop="handleEditTask(data)"
- v-hasPermi="['oaSystem:task:edit']"
- />
- <el-button
- v-if="data.type === 'phase'"
- type="text"
- size="small"
- icon="Plus"
- @click.stop="handleAddTaskUnderPhase(data)"
- v-hasPermi="['oaSystem:task:add']"
- />
- <el-button
- type="text"
- size="small"
- icon="Delete"
- @click.stop="handleDeleteNode(data)"
- v-hasPermi="['oaSystem:task:remove']"
- />
- </div>
- </div>
- </template>
- </el-tree>
- </div>
-
- <!-- 鍙抽敭鑿滃崟 -->
- <div v-if="showContextMenu" :style="contextMenuStyle" class="context-menu">
- <el-menu @select="handleContextMenuSelect">
- <el-menu-item v-if="selectedNode.type === 'task'" index="edit">缂栬緫浠诲姟</el-menu-item>
- <el-menu-item v-if="selectedNode.type === 'phase'" index="addTask">娣诲姞瀛愪换鍔�</el-menu-item>
- <el-menu-item index="delete">鍒犻櫎</el-menu-item>
- <el-menu-item index="expandAll">灞曞紑鍏ㄩ儴</el-menu-item>
- <el-menu-item index="collapseAll">鏀惰捣鍏ㄩ儴</el-menu-item>
- </el-menu>
- </div>
-
- <!-- 浠诲姟琛ㄥ崟瀵硅瘽妗� -->
- <el-dialog :title="dialogTitle" v-model="dialogOpen" width="600px" append-to-body>
- <el-form ref="taskFormRef" :model="taskForm" :rules="taskRules" label-width="80px">
- <el-form-item label="浠诲姟鍚嶇О" prop="taskName">
- <el-input v-model="taskForm.taskName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" />
- </el-form-item>
- <el-form-item label="璐熻矗浜�" prop="assigneeId">
- <el-input v-model="taskForm.assigneeId" placeholder="璇疯緭鍏ヨ礋璐d汉ID" />
- </el-form-item>
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="taskForm.startDate"
- type="date"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="taskForm.endDate"
- type="date"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="浼樺厛绾�" prop="priority">
- <el-select v-model="taskForm.priority" placeholder="閫夋嫨浼樺厛绾�">
- <el-option label="浣�" value="low" />
- <el-option label="涓�" value="medium" />
- <el-option label="楂�" value="high" />
- </el-select>
- </el-form-item>
- <el-form-item label="杩涘害" prop="progress">
- <el-input-number v-model="taskForm.progress" :min="0" :max="100" style="width: 100%" />
- </el-form-item>
- <el-form-item label="鎻忚堪" prop="description">
- <el-input v-model="taskForm.description" type="textarea" placeholder="璇疯緭鍏ヤ换鍔℃弿杩�" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitTaskForm">纭畾</el-button>
- <el-button @click="dialogOpen = false">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, reactive, computed, watch, onMounted } from 'vue';
-import { ElMessage, ElMessageBox, ElMenu, ElMenuItem } from 'element-plus';
-// import { getProject, addTask, updateTask, deleteTask, deletePhase } from '@/api/oaSystem/projectManagement';
-
-const props = defineProps({
- projectId: {
- type: String,
- required: true
- }
-});
-
-const emit = defineEmits(['refresh']);
-
-// 缁勪欢鐘舵��
-const loading = ref(false);
-const treeRef = ref();
-const showContextMenu = ref(false);
-const contextMenuStyle = ref({});
-const selectedNode = ref({});
-const showFilter = ref(false);
-const dialogOpen = ref(false);
-const dialogTitle = ref('');
-const taskFormRef = ref();
-
-// 绛涢�夊弬鏁�
-const filterParams = reactive({
- status: '',
- assignee: ''
-});
-
-// 浠诲姟琛ㄥ崟鏁版嵁
-const taskForm = reactive({
- taskId: undefined,
- taskName: '',
- description: '',
- startDate: '',
- endDate: '',
- assigneeId: '',
- assigneeName: '',
- status: 'notStarted',
- progress: 0,
- priority: 'medium',
- phaseId: '',
- projectId: props.projectId
-});
-
-// 琛ㄥ崟楠岃瘉瑙勫垯
-const taskRules = {
- taskName: [
- { required: true, message: '浠诲姟鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' },
- { min: 2, max: 50, message: '浠诲姟鍚嶇О闀垮害鍦� 2 鍒� 50 涓瓧绗�', trigger: 'blur' }
- ],
- startDate: [
- { required: true, message: '寮�濮嬫棩鏈熶笉鑳戒负绌�', trigger: 'change' }
- ],
- endDate: [
- { required: true, message: '缁撴潫鏃ユ湡涓嶈兘涓虹┖', trigger: 'change' }
- ],
- assigneeId: [
- { required: true, message: '璐熻矗浜轰笉鑳戒负绌�', trigger: 'blur' }
- ],
- progress: [
- { required: true, message: '杩涘害涓嶈兘涓虹┖', trigger: 'blur' },
- { type: 'number', min: 0, max: 100, message: '杩涘害蹇呴』鍦� 0 鍒� 100 涔嬮棿', trigger: 'blur' }
- ]
-};
-
-// 浠诲姟鏍戞暟鎹�
-const rawTaskTreeData = ref([]);
-
-// 妯℃嫙浠诲姟鏁版嵁
-const mockTaskData = {
- 'PRJ2023001': [
- {
- phaseId: 'PHASE001',
- phaseName: '闇�姹傚垎鏋�',
- startDate: '2023-11-01',
- endDate: '2023-11-15',
- status: 'completed',
- tasks: [
- {
- taskId: 'TASK001',
- taskName: '闇�姹傝皟鐮�',
- description: '璋冪爺鐢ㄦ埛闇�姹傚拰涓氬姟娴佺▼',
- startDate: '2023-11-01',
- endDate: '2023-11-05',
- assigneeId: 'USER001',
- assigneeName: '寮犱笁',
- status: 'completed',
- progress: 100,
- priority: 'medium'
- },
- {
- taskId: 'TASK002',
- taskName: '闇�姹傛枃妗g紪鍐�',
- description: '缂栧啓璇︾粏鐨勯渶姹傝鏍艰鏄庝功',
- startDate: '2023-11-06',
- endDate: '2023-11-15',
- assigneeId: 'USER002',
- assigneeName: '鏉庡洓',
- status: 'completed',
- progress: 100,
- priority: 'high'
- }
- ]
- },
- {
- phaseId: 'PHASE002',
- phaseName: '绯荤粺璁捐',
- startDate: '2023-11-16',
- endDate: '2023-12-10',
- status: 'completed',
- tasks: [
- {
- taskId: 'TASK003',
- taskName: '绯荤粺鏋舵瀯璁捐',
- description: '璁捐绯荤粺鏁翠綋鏋舵瀯',
- startDate: '2023-11-16',
- endDate: '2023-11-25',
- assigneeId: 'USER003',
- assigneeName: '鐜嬩簲',
- status: 'completed',
- progress: 100,
- priority: 'high'
- },
- {
- taskId: 'TASK004',
- taskName: '鏁版嵁搴撹璁�',
- description: '璁捐鏁版嵁搴撹〃缁撴瀯鍜屽叧绯�',
- startDate: '2023-11-26',
- endDate: '2023-12-10',
- assigneeId: 'USER004',
- assigneeName: '璧靛叚',
- status: 'completed',
- progress: 100,
- priority: 'medium'
- }
- ]
- },
- {
- phaseId: 'PHASE003',
- phaseName: '寮�鍙戝疄鐜�',
- startDate: '2023-12-11',
- endDate: '2024-01-31',
- status: 'inProgress',
- tasks: [
- {
- taskId: 'TASK005',
- taskName: '鍓嶇寮�鍙�',
- description: '寮�鍙戠敤鎴风晫闈㈠拰浜や簰閫昏緫',
- startDate: '2023-12-11',
- endDate: '2024-01-15',
- assigneeId: 'USER005',
- assigneeName: '閽变竷',
- status: 'inProgress',
- progress: 70,
- priority: 'high'
- },
- {
- taskId: 'TASK006',
- taskName: '鍚庣寮�鍙�',
- description: '寮�鍙戜笟鍔¢�昏緫鍜孉PI鎺ュ彛',
- startDate: '2023-12-11',
- endDate: '2024-01-20',
- assigneeId: 'USER006',
- assigneeName: '瀛欏叓',
- status: 'inProgress',
- progress: 60,
- priority: 'high'
- }
- ]
- }
- ],
- // 榛樿鏁版嵁
- default: [
- {
- phaseId: 'PHASE_DEFAULT1',
- phaseName: '鍑嗗闃舵',
- startDate: '2023-01-01',
- endDate: '2023-03-31',
- status: 'completed',
- tasks: [
- {
- taskId: 'TASK_DEFAULT1',
- taskName: '椤圭洰鍚姩',
- description: '鍙紑椤圭洰鍚姩浼氳',
- startDate: '2023-01-01',
- endDate: '2023-01-05',
- assigneeId: 'USER_DEFAULT1',
- assigneeName: '璐熻矗浜篈',
- status: 'completed',
- progress: 100,
- priority: 'high'
- }
- ]
- },
- {
- phaseId: 'PHASE_DEFAULT2',
- phaseName: '鎵ц闃舵',
- startDate: '2023-04-01',
- endDate: '2023-09-30',
- status: 'inProgress',
- tasks: [
- {
- taskId: 'TASK_DEFAULT2',
- taskName: '鏍稿績鍔熻兘寮�鍙�',
- description: '寮�鍙戠郴缁熸牳蹇冨姛鑳芥ā鍧�',
- startDate: '2023-04-01',
- endDate: '2023-06-30',
- assigneeId: 'USER_DEFAULT2',
- assigneeName: '璐熻矗浜築',
- status: 'inProgress',
- progress: 50,
- priority: 'high'
- }
- ]
- }
- ]
-};
-
-const taskTreeData = computed(() => {
- // 搴旂敤绛涢�夋潯浠�
- if (!showFilter.value || (!filterParams.status && !filterParams.assignee)) {
- return rawTaskTreeData.value;
- }
-
- // 娣辨嫹璐濆師濮嬫暟鎹互閬垮厤淇敼
- const filteredData = JSON.parse(JSON.stringify(rawTaskTreeData.value));
-
- // 閫掑綊绛涢�夎妭鐐�
- const filterNodes = (nodes) => {
- const result = [];
-
- nodes.forEach(node => {
- // 瀵逛簬闃舵鑺傜偣锛屾鏌ュ叾瀛愪换鍔℃槸鍚︾鍚堢瓫閫夋潯浠�
- if (node.type === 'phase' && node.children) {
- const filteredChildren = filterNodes(node.children);
- if (filteredChildren.length > 0) {
- // 淇濈暀鑷冲皯鏈変竴涓瓙浠诲姟绗﹀悎鏉′欢鐨勯樁娈�
- node.children = filteredChildren;
- result.push(node);
- }
- }
- // 瀵逛簬浠诲姟鑺傜偣锛岀洿鎺ュ簲鐢ㄧ瓫閫夋潯浠�
- else if (node.type === 'task') {
- const statusMatch = !filterParams.status || node.status === filterParams.status;
- const assigneeMatch = !filterParams.assignee ||
- (node.assigneeName && node.assigneeName.includes(filterParams.assignee));
-
- if (statusMatch && assigneeMatch) {
- result.push(node);
- }
- }
- });
-
- return result;
- };
-
- return filterNodes(filteredData);
-});
-
-// 鏍戣妭鐐归厤缃�
-const defaultProps = {
- children: 'children',
- label: (data) => {
- if (data.type === 'phase') {
- return `${data.phaseName}`;
- } else {
- return `${data.taskName}`;
- }
- }
-};
-
-// 鍔犺浇浠诲姟鏍戞暟鎹�
-const loadTaskTree = async () => {
- loading.value = true;
- // try {
- // const { data } = await getProject(props.projectId);
- // rawTaskTreeData.value = buildTaskTree(data.phases || []);
- // } catch (error) {
- // ElMessage.error('鍔犺浇浠诲姟鏍戝け璐�');
- // console.error('鍔犺浇浠诲姟鏍戝け璐�:', error);
- // } finally {
- // loading.value = false;
- // }
- try {
- // 妯℃嫙缃戠粶寤惰繜
- await new Promise(resolve => setTimeout(resolve, 500));
-
- // 浣跨敤妯℃嫙鏁版嵁鏇夸唬API璇锋眰
- const phases = mockTaskData[props.projectId] || mockTaskData.default;
- rawTaskTreeData.value = buildTaskTree(phases);
- } catch (error) {
- ElMessage.error('鍔犺浇浠诲姟鏍戝け璐�');
- console.error('鍔犺浇浠诲姟鏍戝け璐�:', error);
- } finally {
- loading.value = false;
- }
-};
-
-// 鏋勫缓浠诲姟鏍�
-const buildTaskTree = (phases) => {
- return phases.map(phase => ({
- nodeId: phase.phaseId,
- phaseId: phase.phaseId,
- phaseName: phase.phaseName,
- type: 'phase',
- children: (phase.tasks || []).map(task => ({
- nodeId: task.taskId,
- taskId: task.taskId,
- taskName: task.taskName,
- description: task.description,
- startDate: task.startDate,
- endDate: task.endDate,
- assigneeId: task.assigneeId,
- assigneeName: task.assigneeName,
- status: task.status,
- progress: task.progress,
- priority: task.priority,
- phaseId: task.phaseId,
- projectId: props.projectId,
- type: 'task'
- }))
- }));
-};
-
-// 鏍煎紡鍖栨棩鏈熻寖鍥�
-const formatDateRange = (startDate, endDate) => {
- if (!startDate || !endDate) return '';
- return `${startDate} - ${endDate}`;
-};
-
-// 鍒锋柊鏍�
-const refreshTree = () => {
- loadTaskTree();
- // 閫氱煡鐖剁粍浠跺埛鏂版暟鎹�
- emit('refresh');
-};
-
-// 鍒囨崲绛涢�夐潰鏉�
-const toggleFilter = () => {
- showFilter.value = !showFilter.value;
-};
-
-// 搴旂敤绛涢��
-const filterTree = () => {
- // 绛涢�夐�昏緫宸茬粡鍦╟omputed涓疄鐜�
-};
-
-// 閲嶇疆绛涢��
-const resetFilter = () => {
- filterParams.status = '';
- filterParams.assignee = '';
-};
-
-// 澶勭悊鑺傜偣鐐瑰嚮
-const handleNodeClick = (data, node) => {
- // 鍒囨崲灞曞紑/鏀惰捣鐘舵��
- if (data.type === 'phase') {
- node.expanded = !node.expanded;
- }
-};
-
-// 澶勭悊鍙抽敭鑿滃崟
-const handleContextMenu = (event, data) => {
- event.preventDefault();
- selectedNode.value = data;
- contextMenuStyle.value = {
- position: 'fixed',
- left: `${event.clientX}px`,
- top: `${event.clientY}px`,
- zIndex: 1000
- };
- showContextMenu.value = true;
-};
-
-// 澶勭悊鍙抽敭鑿滃崟閫夋嫨
-const handleContextMenuSelect = (index) => {
- showContextMenu.value = false;
- switch (index) {
- case 'edit':
- if (selectedNode.value.type === 'task') {
- handleEditTask(selectedNode.value);
- }
- break;
- case 'addTask':
- if (selectedNode.value.type === 'phase') {
- handleAddTaskUnderPhase(selectedNode.value);
- }
- break;
- case 'delete':
- handleDeleteNode(selectedNode.value);
- break;
- case 'expandAll':
- treeRef.value?.expandAll();
- break;
- case 'collapseAll':
- treeRef.value?.collapseAll();
- break;
- }
-};
-
-// 娣诲姞浠诲姟
-const handleAddTask = () => {
- resetTaskForm();
- dialogTitle.value = '娣诲姞浠诲姟';
- dialogOpen.value = true;
-};
-
-// 鍦ㄦ寚瀹氶樁娈典笅娣诲姞浠诲姟
-const handleAddTaskUnderPhase = (phase) => {
- resetTaskForm();
- taskForm.phaseId = phase.phaseId;
- dialogTitle.value = '娣诲姞瀛愪换鍔�';
- dialogOpen.value = true;
-};
-
-// 缂栬緫浠诲姟
-const handleEditTask = (task) => {
- resetTaskForm();
- Object.assign(taskForm, { ...task });
- dialogTitle.value = '缂栬緫浠诲姟';
- dialogOpen.value = true;
-};
-
-// 鍒犻櫎鑺傜偣
-const handleDeleteNode = async (node) => {
- const confirmMessage = node.type === 'phase'
- ? `纭畾瑕佸垹闄ら樁娈� "${node.phaseName}" 鍙婂叾鎵�鏈夊瓙浠诲姟鍚楋紵`
- : `纭畾瑕佸垹闄や换鍔� "${node.taskName}" 鍚楋紵`;
-
- await ElMessageBox.confirm(confirmMessage, '纭鎿嶄綔', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- }).catch(() => {
- throw new Error('鍙栨秷鍒犻櫎');
- });
-
- try {
- if (node.type === 'phase') {
- await deletePhase(node.phaseId);
- } else {
- await deleteTask(node.taskId);
- }
- ElMessage.success('鍒犻櫎鎴愬姛');
- refreshTree();
- } catch (error) {
- if (error.message !== '鍙栨秷鍒犻櫎') {
- ElMessage.error('鍒犻櫎澶辫触');
- console.error('鍒犻櫎澶辫触:', error);
- }
- }
-};
-
-// 閲嶇疆浠诲姟琛ㄥ崟
-const resetTaskForm = () => {
- taskForm.taskId = undefined;
- taskForm.taskName = '';
- taskForm.description = '';
- taskForm.startDate = '';
- taskForm.endDate = '';
- taskForm.assigneeId = '';
- taskForm.assigneeName = '';
- taskForm.status = 'notStarted';
- taskForm.progress = 0;
- taskForm.priority = 'medium';
- taskForm.phaseId = '';
- taskForm.projectId = props.projectId;
-
- if (taskFormRef.value) {
- taskFormRef.value.resetFields();
- }
-};
-
-// 鎻愪氦浠诲姟琛ㄥ崟
-const submitTaskForm = async () => {
- try {
- await taskFormRef.value.validate();
-
- if (taskForm.taskId) {
- await updateTask(taskForm);
- ElMessage.success('淇敼浠诲姟鎴愬姛');
- } else {
- await addTask(taskForm);
- ElMessage.success('娣诲姞浠诲姟鎴愬姛');
- }
-
- dialogOpen.value = false;
- refreshTree();
- } catch (error) {
- console.error('鎻愪氦琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 鐐瑰嚮鍏朵粬鍖哄煙鍏抽棴鍙抽敭鑿滃崟
-document.addEventListener('click', () => {
- if (showContextMenu.value) {
- showContextMenu.value = false;
- }
-});
-
-// 鐩戝惉椤圭洰ID鍙樺寲
-watch(() => props.projectId, (newProjectId) => {
- if (newProjectId) {
- loadTaskTree();
- }
-});
-
-// 鍒濆鍖�
-onMounted(() => {
- loadTaskTree();
-});
-</script>
-
-<style scoped>
-.task-tree-container {
- padding: 10px;
-}
-
-.tree-actions {
- display: flex;
- gap: 10px;
- align-items: center;
-}
-
-.filter-section {
- background: #f5f7fa;
- padding: 10px;
- border-radius: 4px;
-}
-
-.tree-content {
- background: #fff;
- border: 1px solid #ebeef5;
- border-radius: 4px;
- padding: 10px;
- max-height: 600px;
- overflow-y: auto;
-}
-
-.tree-node-content {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 5px 0;
- min-height: 40px;
-}
-
-.phase-node {
- font-weight: bold;
- color: #409eff;
-}
-
-.task-node {
- color: #606266;
-}
-
-.node-icon {
- display: flex;
- align-items: center;
- width: 20px;
-}
-
-.node-info {
- flex: 1;
- min-width: 0;
-}
-
-.node-title {
- font-weight: 500;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- margin-bottom: 2px;
-}
-
-.overdue-title {
- color: #f56c6c;
- font-weight: bold;
-}
-
-.priority-tag {
- background: #f56c6c;
- color: white;
- font-size: 10px;
- padding: 1px 4px;
- border-radius: 2px;
- margin-left: 5px;
-}
-
-.priority-tag.medium {
- background: #e6a23c;
-}
-
-.node-description {
- font-size: 12px;
- color: #909399;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.task-meta {
- display: flex;
- gap: 15px;
- font-size: 12px;
- color: #909399;
- margin-top: 2px;
-}
-
-.meta-item {
- display: flex;
- align-items: center;
- gap: 3px;
-}
-
-.task-progress {
- width: 120px;
- margin: 0 10px;
-}
-
-.node-actions {
- display: flex;
- gap: 5px;
- opacity: 0;
- transition: opacity 0.3s;
-}
-
-.tree-node-content:hover .node-actions {
- opacity: 1;
-}
-
-.context-menu {
- background: white;
- border: 1px solid #ebeef5;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- border-radius: 4px;
-}
-
-.context-menu .el-menu {
- min-width: 120px;
- border: none;
-}
-
-.context-menu .el-menu-item {
- padding: 0 15px;
- height: 36px;
- line-height: 36px;
-}
-
-.context-menu .el-menu-item:hover {
- background-color: #f5f7fa;
-}
-
-.text-gray-400 {
- color: #c0c4cc;
-}
-</style>
\ No newline at end of file
diff --git a/src/views/oaSystem/projectManagement/index.vue b/src/views/oaSystem/projectManagement/index.vue
deleted file mode 100644
index 79fbe7f..0000000
--- a/src/views/oaSystem/projectManagement/index.vue
+++ /dev/null
@@ -1,481 +0,0 @@
-<template>
- <div class="app-container">
- <!-- 椤堕儴鎼滅储鍜屾搷浣滄爮 -->
- <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px">
- <el-form-item label="椤圭洰鍚嶇О" prop="projectName">
- <el-input
- v-model="queryParams.projectName"
- placeholder="璇疯緭鍏ラ」鐩悕绉�"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="璐熻矗浜�" prop="managerName">
- <el-input
- v-model="queryParams.managerName"
- placeholder="璇疯緭鍏ヨ礋璐d汉濮撳悕"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鐘舵��" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="椤圭洰鐘舵��"
- clearable
- style="width: 150px"
- >
- <el-option label="瑙勫垝涓�" value="planning" />
- <el-option label="杩涜涓�" value="inProgress" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸叉殏鍋�" value="paused" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
- <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
- </el-form-item>
- </el-form>
-
- <!-- 宸ュ叿鏍� -->
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- v-hasPermi="['oaSystem:project:add']"
- >鏂板椤圭洰</el-button>
- </el-col>
- <!-- <el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate"
- v-hasPermi="['oaSystem:project:edit']"
- >缂栬緫椤圭洰</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete"
- v-hasPermi="['oaSystem:project:remove']"
- >鍒犻櫎椤圭洰</el-button>
- </el-col> -->
- <el-col :span="1.5">
- <el-button
- type="warning"
- plain
- icon="Download"
- @click="handleExport"
- v-hasPermi="['oaSystem:project:export']"
- >瀵煎嚭椤圭洰</el-button>
- </el-col>
- </el-row>
-
- <!-- 椤圭洰鍒楄〃琛ㄦ牸 -->
- <el-table
- v-loading="loading"
- :data="projectList"
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" width="50" align="center" />
- <el-table-column
- label="椤圭洰缂栧彿"
- align="center"
- prop="projectId"
- width="100"
- />
- <el-table-column
- label="椤圭洰鍚嶇О"
- align="center"
- prop="projectName"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="璐熻矗浜�"
- align="center"
- prop="managerName"
- />
- <el-table-column
- label="寮�濮嬫棩鏈�"
- align="center"
- prop="startDate"
- width="120"
- />
- <el-table-column
- label="缁撴潫鏃ユ湡"
- align="center"
- prop="endDate"
- width="120"
- />
- <el-table-column
- label="鐘舵��"
- align="center"
- prop="status"
- width="90"
- >
- <template #default="scope">
- <el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column
- label="瀹屾垚搴�"
- align="center"
- prop="completionRate"
- width="100"
- >
- <template #default="scope">
- <el-progress :percentage="scope.row.completionRate" :stroke-width="6" />
- </template>
- </el-table-column>
- <el-table-column
- label="鎿嶄綔"
- align="center"
- width="180"
- class-name="small-padding fixed-width"
- >
- <template #default="scope">
- <el-button
- link
- type="primary"
- icon="Search"
- @click="handleView(scope.row)"
- v-hasPermi="['oaSystem:project:query']"
- >璇︽儏</el-button>
- <el-button
- link
- type="primary"
- icon="Edit"
- @click="handleUpdate(scope.row)"
- v-hasPermi="['oaSystem:project:edit']"
- >缂栬緫</el-button>
- <el-button
- link
- type="danger"
- icon="Delete"
- @click="handleDelete(scope.row)"
- v-hasPermi="['oaSystem:project:remove']"
- >鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <!-- 鍒嗛〉缁勪欢 -->
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
-
- <!-- 椤圭洰琛ㄥ崟瀵硅瘽妗� -->
- <el-dialog :title="title" v-model="open" width="600px" append-to-body>
- <project-form
- ref="projectFormRef"
- :form="form"
- :rules="rules"
- :visible="open"
- />
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="cancel">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, reactive, computed, onMounted } from 'vue';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import Pagination from '@/components/Pagination';
-import ProjectForm from './components/projectForm.vue';
-import { useRouter } from 'vue-router';
-const { proxy } = getCurrentInstance();
-// 瀵煎叆椤圭洰绠$悊API鎺ュ彛
-import { listProject, addProject, updateProject, delProject, exportProject } from '@/api/oaSystem/projectManagement';
-// import { listUser } from '@/api/system/user'; // 瀵煎叆鐢ㄦ埛鍒楄〃API鎺ュ彛
-
-// 鍒涘缓router瀹炰緥
-const router = useRouter();
-
-// 琛ㄦ牸鏁版嵁
-const projectList = ref([]);
-const loading = ref(true);
-const total = ref(0);
-const queryParams = reactive({
- pageNum: 1,
- pageSize: 10,
- projectName: '',
- managerName: '',
- status: ''
-});
-
-// 琛ㄥ崟鏁版嵁
-const form = reactive({
- projectId: undefined,
- projectName: '',
- description: '',
- startDate: '',
- endDate: '',
- managerId: '',
- managerName: '',
- status: 'planning',
- completionRate: 0
-});
-
-// 琛ㄥ崟鏍¢獙瑙勫垯
-const rules = {
- projectName: [
- { required: true, message: '椤圭洰鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' },
- { min: 2, max: 50, message: '椤圭洰鍚嶇О闀垮害鍦� 2 鍒� 50 涓瓧绗�', trigger: 'blur' }
- ],
- startDate: [
- { required: true, message: '寮�濮嬫棩鏈熶笉鑳戒负绌�', trigger: 'change' }
- ],
- endDate: [
- { required: true, message: '缁撴潫鏃ユ湡涓嶈兘涓虹┖', trigger: 'change' }
- ],
- managerId: [
- { required: true, message: '璐熻矗浜轰笉鑳戒负绌�', trigger: 'blur' }
- ]
-};
-
-// 瀵硅瘽妗嗙姸鎬�
-const open = ref(false);
-const title = ref('');
-const projectFormRef = ref();
-const queryRef = ref();
-
-// 閫変腑鐘舵��
-const multiple = computed(() => {
- return selectedRowKeys.value.length === 0;
-});
-const single = computed(() => {
- return selectedRowKeys.value.length !== 1;
-});
-const selectedRowKeys = ref([]);
-
-// 鑾峰彇椤圭洰鍒楄〃
-const getList = async () => {
- loading.value = true;
- try {
- const { data } = await listProject(queryParams);
- projectList.value = data.records;
- total.value = data.total;
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰鍒楄〃澶辫触');
- console.error('鑾峰彇椤圭洰鍒楄〃澶辫触:', error);
- } finally {
- loading.value = false;
- }
-};
-
-// 鎼滅储
-const handleQuery = () => {
- queryParams.pageNum = 1;
- getList();
-};
-
-// 閲嶇疆
-const resetQuery = () => {
- if (queryRef.value) {
- queryRef.value.resetFields();
- }
- handleQuery();
-};
-
-// 閫変腑琛屽彉鍖�
-const handleSelectionChange = (selection) => {
- selectedRowKeys.value = selection.map(item => item.projectId);
-};
-
-// 鏂板椤圭洰
-const handleAdd = () => {
- resetForm();
- open.value = true;
- title.value = '鏂板椤圭洰';
-};
-
-// 缂栬緫椤圭洰
-const handleUpdate = async (row) => {
- resetForm();
- const projectId = row.projectId || selectedRowKeys.value[0];
- try {
- // const { data } = await getProject(projectId);
- Object.assign(form, row);
- open.value = true;
- title.value = '缂栬緫椤圭洰';
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰璇︽儏澶辫触');
- console.error('鑾峰彇椤圭洰璇︽儏澶辫触:', error);
- }
-};
-
-// 鍒犻櫎椤圭洰
-const handleDelete = async (row) => {
- // const projectIds = row.projectId ? [row.projectId] : selectedRowKeys.value;
- const projectNames = row.projectName ? [row.projectName] :
- projectList.value.filter(item => projectIds.includes(item.projectId)).map(item => item.projectName);
-
- const confirmMessage = `纭畾瑕佸垹闄ら」鐩� "${projectNames.join('銆�')}" 鍚楋紵`;
- await ElMessageBox.confirm(confirmMessage, '纭鎿嶄綔', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- }).catch(() => {
- throw new Error('鍙栨秷鍒犻櫎');
- });
-
- try {
- // if (projectIds.length === 1) {
- await delProject(row.projectId);
- // } else {
- // await delProjectBatch(projectIds);
- // }
- ElMessage.success('鍒犻櫎鎴愬姛');
- getList();
- } catch (error) {
- if (error.message !== '鍙栨秷鍒犻櫎') {
- ElMessage.error('鍒犻櫎澶辫触');
- console.error('鍒犻櫎椤圭洰澶辫触:', error);
- }
- }
- // try {
- // await ElMessageBox.confirm(confirmMessage, '纭鎿嶄綔', {
- // confirmButtonText: '纭畾',
- // cancelButtonText: '鍙栨秷',
- // type: 'warning'
- // });
-
- // // 妯℃嫙缃戠粶寤惰繜
- // await new Promise(resolve => setTimeout(resolve, 300));
-
-
- // ElMessage.success('鍒犻櫎鎴愬姛');
- // getList();
- // } catch (error) {
- // if (error !== 'cancel') {
- // console.error('鍒犻櫎椤圭洰澶辫触:', error);
- // }
- // }
-};
-
-// 鏌ョ湅椤圭洰璇︽儏
-const handleView = (row) => {
- const projectId = row.projectId;
- // 璺宠浆鍒伴」鐩鎯呴〉闈�
- router.push({
- path: `/oaSystem/projectManagement/projectDetail/${projectId}`,
- query: { projectName: row.projectName }
- });
-};
-
-// 瀵煎嚭椤圭洰
-const handleExport = async () => {
- let ids = [];
- if (selectedRowKeys.value.length > 0) {
- ids = selectedRowKeys.value; // 瀵煎嚭閫変腑鐨勯」鐩�
- } else {
- ids = projectList.value.map(item => item.projectId); // 瀵煎嚭鎵�鏈夐」鐩�
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(`/oA/project/export/${ids.join(',')}`, {}, "椤圭洰鏁版嵁.xlsx");
- ElMessage.success("瀵煎嚭鎴愬姛");
- ids = [];
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = async () => {
- try {
- await projectFormRef.value.validate();
-
- if (form.projectId) {
- await updateProject(form);
- ElMessage.success('淇敼椤圭洰鎴愬姛');
- } else {
- console.log("form",form);
- await addProject(form);
- ElMessage.success('鏂板椤圭洰鎴愬姛');
- }
- open.value = false;
- getList();
- } catch (error) {
- console.error('鎻愪氦琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 鍙栨秷
-const cancel = () => {
- open.value = false;
- resetForm();
-};
-
-// 閲嶇疆琛ㄥ崟
-const resetForm = () => {
- form.projectId = undefined;
- form.projectName = '';
- form.description = '';
- form.startDate = '';
- form.endDate = '';
- form.managerId = '';
- form.managerName = '';
- form.status = 'planning';
- form.completionRate = 0;
- if (projectFormRef.value) {
- projectFormRef.value.resetFields();
- }
-};
-
-// 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status) => {
- const statusTypeMap = {
- planning: 'info',
- inProgress: 'primary',
- completed: 'success',
- paused: 'warning'
- };
- return statusTypeMap[status] || 'default';
-};
-
-// 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status) => {
- const statusTextMap = {
- planning: '瑙勫垝涓�',
- inProgress: '杩涜涓�',
- completed: '宸插畬鎴�',
- paused: '宸叉殏鍋�'
- };
- return statusTextMap[status] || status;
-};
-
-// 鍒濆鍖�
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped>
-.app-container {
- padding: 20px;
-}
-</style>
\ No newline at end of file
diff --git a/src/views/oaSystem/projectManagement/projectDetail.vue b/src/views/oaSystem/projectManagement/projectDetail.vue
deleted file mode 100644
index 578f76e..0000000
--- a/src/views/oaSystem/projectManagement/projectDetail.vue
+++ /dev/null
@@ -1,565 +0,0 @@
-// ... existing code ...
-<template>
- <div class="app-container">
- <!-- 椤圭洰鍩烘湰淇℃伅 -->
- <el-card class="mb20">
- <template #header>
- <div class="card-header">
- <span>椤圭洰鍩烘湰淇℃伅</span>
- </div>
- </template>
- <el-descriptions :column="2" border>
- <el-descriptions-item label="椤圭洰鍚嶇О">{{ projectInfo.projectName }}</el-descriptions-item>
- <el-descriptions-item label="椤圭洰璐熻矗浜�">{{ projectInfo.managerName }}</el-descriptions-item>
- <el-descriptions-item label="寮�濮嬫棩鏈�">{{ projectInfo.startDate }}</el-descriptions-item>
- <el-descriptions-item label="缁撴潫鏃ユ湡">{{ projectInfo.endDate }}</el-descriptions-item>
- <el-descriptions-item label="椤圭洰鐘舵��">
- <el-tag :type="getStatusType(projectInfo.status)">{{ getStatusText(projectInfo.status) }}</el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="瀹屾垚搴�">
- <el-progress :percentage="projectInfo.completionRate" :stroke-width="6" />
- </el-descriptions-item>
- <el-descriptions-item label="椤圭洰鎻忚堪" :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item>
- </el-descriptions>
- </el-card>
-
- <!-- 椤圭洰杩涘害姒傝 -->
- <el-card class="mb20">
- <template #header>
- <div class="card-header">
- <span>椤圭洰杩涘害姒傝</span>
- </div>
- </template>
- <el-row :gutter="20">
- <el-col :span="6">
- <div class="progress-item">
- <div class="progress-title">鎬讳綋杩涘害</div>
- <div class="progress-number">{{ projectInfo.completionRate }}%</div>
- </div>
- </el-col>
- <el-col :span="6">
- <div class="progress-item">
- <div class="progress-title">闃舵鎬绘暟</div>
- <div class="progress-number">{{ statistics.totalPhases }}</div>
- </div>
- </el-col>
- <el-col :span="6">
- <div class="progress-item">
- <div class="progress-title">浠诲姟鎬绘暟</div>
- <div class="progress-number">{{ statistics.totalTasks }}</div>
- </div>
- </el-col>
- <el-col :span="6">
- <div class="progress-item">
- <div class="progress-title">宸插畬鎴愪换鍔�</div>
- <div class="progress-number">{{ statistics.completedTasks }}</div>
- </div>
- </el-col>
- </el-row>
- </el-card>
-
- <!-- 闃舵鍜屼换鍔$鐞� -->
- <!-- <el-card class="mb20">
- <template #header>
- <div class="card-header">
- <span>椤圭洰浠诲姟缁撴瀯</span>
- <el-button type="primary" size="small" @click="handleAddPhase">娣诲姞闃舵</el-button>
- </div>
- </template>
- <task-tree :project-id="projectId" @refresh="getProjectDetail" />
- </el-card> -->
-
- <!-- 閲岀▼纰戠鐞� -->
- <el-card class="mb20">
- <template #header>
- <div class="card-header">
- <span>椤圭洰闃舵閲岀▼纰�</span>
- <el-button type="primary" size="small" @click="handleAddMilestone">娣诲姞閲岀▼纰�</el-button>
- </div>
- </template>
- <milestone-list :project-id="projectId" @refresh="getProjectDetail" :key="`milestone-${refreshProjectId}`"/>
- </el-card>
-
- <!-- 闃舵鐩爣绠$悊 -->
- <el-card>
- <template #header>
- <div class="card-header">
- <span>闃舵浠诲姟</span>
- <el-button type="primary" size="small" @click="handleAddPhaseGoal">娣诲姞闃舵鐩爣</el-button>
- </div>
- </template>
- <phase-goal-list :project-id="projectId" @refresh="getProjectDetail" @editGoal="handleEditPhaseGoal" :key="`phaseGoal-${refreshProjectId}`"/>
- </el-card>
-
- <!-- 閲岀▼纰戠鐞嗗脊妗� -->
- <el-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form :model="form" ref="formRef" label-width="100px">
- <el-form-item label="椤圭洰闃舵鍚嶇О" prop="phaseName">
- <el-input
- v-model="form.phaseName"
- placeholder="璇疯緭鍏ラ」鐩樁娈靛悕绉�"
- maxlength="50"
- />
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="form.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="form.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="鐘舵��" prop="status">
- <el-radio-group v-model="form.status">
- <el-radio label="notStarted">鏈紑濮�</el-radio>
- <el-radio label="completed">宸插畬鎴�</el-radio>
- <el-radio label="delayed">宸插欢杩�</el-radio>
- </el-radio-group>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭畾</el-button>
- <el-button @click="cancel">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
-
- <!-- 闃舵浠诲姟绠$悊寮规 -->
- <el-dialog :title="goalTitle" v-model="goalOpen" width="600px" append-to-body>
- <el-form :model="goalForm" ref="goalFormRef" label-width="100px">
- <el-form-item label="鎵�灞為樁娈�" prop="phaseId">
- <el-select v-model="goalForm.phaseId" placeholder="璇烽�夋嫨鎵�灞為樁娈�">
- <el-option
- v-for="phase in phaseList"
- :key="phase.phaseId"
- :label="phase.phaseName"
- :value="phase.phaseId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="鐩爣鍚嶇О" prop="taskName">
- <el-input
- v-model="goalForm.taskName"
- placeholder="璇疯緭鍏ョ洰鏍囧悕绉�"
- maxlength="50"
- />
- </el-form-item>
- <el-form-item label="鐩爣鍊�" prop="targetValue">
- <el-input-number
- v-model="goalForm.targetValue"
- :min="0"
- :precision="2"
- placeholder="璇疯緭鍏ョ洰鏍囧��"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="褰撳墠鍊�" prop="currentValue">
- <el-input-number
- v-model="goalForm.currentValue"
- :min="0"
- :precision="2"
- placeholder="璇疯緭鍏ュ綋鍓嶅��"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="鍗曚綅" prop="unit">
- <el-input
- v-model="goalForm.unit"
- placeholder="璇疯緭鍏ュ崟浣�"
- maxlength="10"
- />
- </el-form-item>
- <el-form-item label="浠诲姟瀹屾垚鏃ユ湡" prop="targetDate">
- <el-date-picker
- v-model="goalForm.targetDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="goalForm.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="goalForm.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="鐘舵��" prop="status">
- <el-select v-model="goalForm.status" placeholder="璇烽�夋嫨鐘舵��">
- <el-option label="鏈紑濮�" value="notStarted" />
- <el-option label="杩涜涓�" value="inProgress" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸插欢杩�" value="delayed" />
- </el-select>
- </el-form-item>
- <!-- <el-form-item label="瀹屾垚搴�" prop="completionRate">
- <el-input-number
- v-model="goalForm.completionRate"
- :min="0"
- :max="100"
- :precision="2"
- placeholder="璇疯緭鍏ュ畬鎴愬害"
- style="width: 100%"
- />
- </el-form-item> -->
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitGoalForm">纭畾</el-button>
- <el-button @click="cancelGoal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, reactive, onMounted, watch } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
-import { ElMessage } from 'element-plus';
-import TaskTree from './components/taskTree.vue';
-import MilestoneList from './components/milestoneList.vue';
-import ProjectForm from './components/projectForm.vue';
-import PhaseGoalList from './components/phaseGoalList.vue';
-import { getProject, addProjectPhase, listProjectPhase, addProjectTask, updateProjectTask } from '@/api/oaSystem/projectManagement';
-
-const route = useRoute();
-const router = useRouter();
-const open = ref(false);
-const title = ref('');
-const projectFormRef = ref();
-const formRef = ref();
-// 椤圭洰ID
-// 鍦ㄥ叾浠杛ef瀹氫箟闄勮繎娣诲姞
-const refreshProjectId = ref(0);
-
-const projectId = ref(route.params.projectId);
-
-// 椤圭洰淇℃伅
-const projectInfo = reactive({
- projectId: '',
- projectName: '',
- description: '',
- startDate: '',
- endDate: '',
- managerId: '',
- managerName: '',
- status: 'planning',
- completionRate: 0
-});
-
-// 缁熻淇℃伅
-const statistics = reactive({
- totalPhases: 0,
- totalTasks: 0,
- completedTasks: 0
-});
-const form = reactive({
- phaseId: '',
- phaseName: '',
- startDate: '',
- endDate: '',
- status: 'planning',
- oaProjectId: projectId.value,
-})
-
-// 闃舵鐩爣鐩稿叧
-const goalOpen = ref(false);
-const goalTitle = ref('');
-const goalFormRef = ref();
-const phaseList = ref([]);
-const goalForm = reactive({
- taskId: '',
- phaseId: '',
- taskName: '',
- targetValue: 100,
- currentValue: 0,
- unit: '%',
- targetDate: '',
- startDate: '',
- endDate: '',
- status: 'notStarted',
- completionRate: 0
-});
-
-// 鑾峰彇椤圭洰璇︽儏
-const getProjectDetail = async () => {
- try {
- getProject().then((res)=>{
- console.log("椤圭洰璇︽儏",res)
- const projectData = res.data[projectId.value];
- // 鏇存柊椤圭洰淇℃伅
- Object.assign(projectInfo, projectData);
-
- // 鏇存柊缁熻淇℃伅
- updateStatistics(projectData);
-
- // 寮哄埗鏇存柊DOM浠ョ‘淇濆瓙缁勪欢鑳芥纭埛鏂�
- // 杩欓噷閫氳繃瑙﹀彂refreshProjectId浜嬩欢鏉ュ己鍒跺埛鏂板瓙缁勪欢
- refreshProjectId.value++;
- })
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰璇︽儏澶辫触');
- console.error('鑾峰彇椤圭洰璇︽儏澶辫触:', error);
- }
-};
-
-// 鏇存柊缁熻淇℃伅
-const updateStatistics = (projectData) => {
- // 杩欓噷鍋囪projectData涓寘鍚簡缁熻淇℃伅
- // 濡傛灉娌℃湁锛岄渶瑕佸崟鐙姹傜粺璁℃暟鎹�
- statistics.totalPhases = projectData.phases ? projectData.phases.length : 0;
- statistics.totalTasks = projectData.tasks ? projectData.tasks.length : 0;
- statistics.completedTasks = projectData.tasks ?
- projectData.tasks.filter(task => task.status === 'completed').length : 0;
-};
-
-// 鑾峰彇椤圭洰闃舵鍒楄〃
-const getPhaseList = async () => {
- try {
- const { data } = await listProjectPhase(projectId.value);
- phaseList.value = data.rows || data;
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰闃舵鍒楄〃澶辫触');
- console.error('鑾峰彇椤圭洰闃舵鍒楄〃澶辫触:', error);
- }
-};
-
-// 璁$畻瀹屾垚搴�
-const calculateCompletionRate = () => {
- if (goalForm.targetValue > 0) {
- goalForm.completionRate = Math.min(Math.round((goalForm.currentValue / goalForm.targetValue) * 100), 100);
- } else {
- goalForm.completionRate = 0;
- }
-};
-
-// 娣诲姞闃舵
-const handleAddPhase = () => {
- // resetForm();
- ElMessage.info('娣诲姞闃舵鍔熻兘寰呭疄鐜�');
-};
-
-// 娣诲姞閲岀▼纰�
-const handleAddMilestone = () => {
- resetForm();
- open.value = true;
- title.value = '鏂板椤圭洰闃舵';
-};
-
-// 娣诲姞闃舵浠诲姟
-const handleAddPhaseGoal = () => {
- goalForm.taskId = '';
- goalForm.phaseId = '';
- goalForm.taskName = '';
- goalForm.targetValue = 0;
- goalForm.currentValue = 0;
- goalForm.unit = '%';
- goalForm.targetDate = '';
- goalForm.startDate = '';
- goalForm.endDate = '';
- goalForm.status = 'notStarted';
- goalForm.completionRate = 0;
- if (goalFormRef.value) {
- goalFormRef.value.resetFields();
- }
- getPhaseList();
- goalTitle.value = '鏂板闃舵鐩爣';
- goalOpen.value = true;
-};
-
-// 鎻愪氦琛ㄥ崟
-const submitForm = async () => {
- try {
- await formRef.value.validate();
-
- if (form.phaseId) {
- // await updateProject(form);
- // ElMessage.success('淇敼椤圭洰闃舵鎴愬姛');
- } else {
- console.log("form",form);
- await addProjectPhase(form);
- ElMessage.success('鏂板椤圭洰闃舵鎴愬姛');
- getProjectDetail();
- }
- open.value = false;
- } catch (error) {
- console.error('鎻愪氦琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 鎻愪氦闃舵浠诲姟琛ㄥ崟
-const submitGoalForm = async () => {
- try {
- await goalFormRef.value.validate();
- calculateCompletionRate();
-
- const goalData = {
- ...goalForm,
- oaProjectId: projectId.value
- };
-
- if (goalForm.taskId) {
- await updateProjectTask(goalData);
- ElMessage.success('淇敼闃舵鐩爣鎴愬姛');
-
- } else {
- await addProjectTask(goalData);
- ElMessage.success('鏂板闃舵鐩爣鎴愬姛');
-
- }
- // 璋冪敤getProjectDetail鍒锋柊鎵�鏈夌浉鍏虫暟鎹�
- getProjectDetail();
- goalOpen.value = false;
-
- } catch (error) {
- console.error('鎻愪氦闃舵鐩爣琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 閲嶇疆閲岀▼纰戣〃鍗�
-const resetForm = () => {
- form.phaseId = '';
- form.phaseName = '';
- form.startDate = '';
- form.endDate = '';
- form.status = 'planning';
- form.oaProjectId = projectId.value;
- if (formRef.value) {
- formRef.value.resetFields();
- }
-};
-
-// 鍙栨秷闃舵浠诲姟鎿嶄綔
-const cancelGoal = () => {
- goalOpen.value = false;
-};
-
-// 鍙栨秷鎿嶄綔
-const cancel = () => {
- open.value = false;
-};
-// 缂栬緫闃舵浠诲姟
-const handleEditPhaseGoal = async (goal) => {
- // 澶嶅埗鐩爣鏁版嵁鍒拌〃鍗�
- Object.assign(goalForm, goal);
-
- // 鑾峰彇椤圭洰闃舵鍒楄〃
- await getPhaseList();
-
- // 鎵撳紑缂栬緫寮圭獥
- goalTitle.value = '缂栬緫闃舵鐩爣';
- goalOpen.value = true;
-};
-// 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status) => {
- const statusTypeMap = {
- planning: 'info',
- inProgress: 'primary',
- completed: 'success',
- paused: 'warning'
- };
- return statusTypeMap[status] || 'default';
-};
-
-// 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status) => {
- const statusTextMap = {
- planning: '瑙勫垝涓�',
- inProgress: '杩涜涓�',
- completed: '宸插畬鎴�',
- paused: '宸叉殏鍋�'
- };
- return statusTextMap[status] || status;
-};
-
-// 鐩戝惉璺敱鍙傛暟鍙樺寲
-watch(() => route.params.projectId, (newProjectId) => {
- // console.log('璺敱鍙傛暟鍙樺寲:', projectId);
- if (newProjectId) {
- projectId.value = newProjectId;
- getProjectDetail();
- }
-});
-
-// 鐩戝惉褰撳墠鍊煎拰鐩爣鍊煎彉鍖栵紝閲嶆柊璁$畻瀹屾垚搴�
-watch(() => [goalForm.currentValue, goalForm.targetValue], () => {
- calculateCompletionRate();
-});
-
-// 鍒濆鍖�
-onMounted(() => {
- if (projectId.value) {
- getProjectDetail();
- }
-});
-</script>
-
-<style scoped>
-.app-container {
- padding: 20px;
-}
-
-.card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.progress-item {
- text-align: center;
- padding: 20px;
- background-color: #f5f7fa;
- border-radius: 8px;
-}
-
-.progress-title {
- font-size: 14px;
- color: #606266;
- margin-bottom: 10px;
-}
-
-.progress-number {
- font-size: 24px;
- font-weight: bold;
- color: #409eff;
-}
-
-.mb20 {
- margin-bottom: 20px;
-}
-</style>
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index f93731b..d65727d 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -3,19 +3,34 @@
<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>
@@ -30,20 +45,68 @@
<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</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/>
- <el-table-column label="瀹℃牳鐘舵��" prop="status" align="center" width="120">
+ <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
+ />
+ <el-table-column
+ label="瀹℃牳鐘舵��"
+ prop="status"
+ align="center"
+ width="120"
+ >
<template #default="scope">
<el-tag :type="getApprovalStatusType(scope.row.status)">
{{ getApprovalStatusText(scope.row.status) }}
@@ -52,46 +115,62 @@
</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"
- :disabled="!isApproved(scope.row.status)"
- @click="openForm('edit', scope.row)">鍙戣揣
+ link
+ type="primary"
+ style="color: #67c23a"
+ @click="openDetail(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)">鍒犻櫎
+ 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"/>
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ />
</div>
- <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-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>
@@ -100,13 +179,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>
@@ -115,18 +194,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>
@@ -135,9 +214,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>
@@ -145,7 +224,7 @@
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="鍙戣揣鍥剧墖锛�">
- <ImageUpload v-model:file-list="deliveryFileList" :limit="9"/>
+ <ImageUpload v-model:file-list="deliveryFileList" :limit="9" />
</el-form-item>
</el-col>
</el-row>
@@ -159,42 +238,79 @@
</el-dialog>
<!-- 璇︽儏寮规 -->
- <el-dialog v-model="detailDialogVisible" title="鍙戣揣鍙拌处璇︽儏" width="55%" @close="closeDetail">
+ <el-dialog
+ v-model="detailDialogVisible"
+ title="鍙戣揣鍙拌处璇︽儏"
+ width="55%"
+ @close="closeDetail"
+ >
<div v-if="detailRow" class="detail-wrapper">
<el-descriptions :column="2" border>
- <el-descriptions-item label="閿�鍞鍗�">{{ detailRow.salesContractNo || '--' }}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣璁㈠崟鍙�">{{ detailRow.shippingNo || '--' }}</el-descriptions-item>
- <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ detailRow.customerName || '--' }}</el-descriptions-item>
- <el-descriptions-item label="浜у搧鍚嶇О">{{ detailRow.productName || '--' }}</el-descriptions-item>
- <el-descriptions-item label="瑙勬牸鍨嬪彿">{{ detailRow.specificationModel || '--' }}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣绫诲瀷">{{ detailRow.type || '--' }}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣鏃ユ湡">{{ detailRow.shippingDate || '--' }}</el-descriptions-item>
- <el-descriptions-item label="瀹℃牳鐘舵��">{{ getApprovalStatusText(detailRow.status) }}</el-descriptions-item>
- <el-descriptions-item label="鍙戣揣杞︾墝鍙�">{{ detailRow.shippingCarNumber || '--' }}</el-descriptions-item>
- <el-descriptions-item label="蹇�掑叕鍙�">{{ detailRow.expressCompany || '--' }}</el-descriptions-item>
- <el-descriptions-item label="蹇�掑崟鍙�" :span="2">{{ detailRow.expressNumber || '--' }}</el-descriptions-item>
+ <el-descriptions-item label="閿�鍞鍗�">{{
+ detailRow.salesContractNo || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戣揣璁㈠崟鍙�">{{
+ detailRow.shippingNo || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="瀹㈡埛鍚嶇О">{{
+ detailRow.customerName || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="浜у搧鍚嶇О">{{
+ detailRow.productName || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="瑙勬牸鍨嬪彿">{{
+ detailRow.specificationModel || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戣揣绫诲瀷">{{
+ detailRow.type || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戣揣鏃ユ湡">{{
+ detailRow.shippingDate || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="瀹℃牳鐘舵��">{{
+ getApprovalStatusText(detailRow.status)
+ }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戣揣杞︾墝鍙�">{{
+ detailRow.shippingCarNumber || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="蹇�掑叕鍙�">{{
+ detailRow.expressCompany || "--"
+ }}</el-descriptions-item>
+ <el-descriptions-item label="蹇�掑崟鍙�" :span="2">{{
+ detailRow.expressNumber || "--"
+ }}</el-descriptions-item>
</el-descriptions>
- <el-table :data="getDeliveryProductInfoList()"
- border
- size="small"
- class="delivery-product-table"
- style="width: 100%; margin-top: 16px;">
- <el-table-column label="鎵瑰彿"
- prop="batchNo"
- min-width="160"
- show-overflow-tooltip/>
- <el-table-column label="浜у搧鍚嶇О"
- prop="productName"
- min-width="160"
- show-overflow-tooltip/>
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- min-width="160"
- show-overflow-tooltip/>
- <el-table-column label="鍙戣揣鏁伴噺"
- prop="deliveryQuantity"
- min-width="120"
- align="center"/>
+ <el-table
+ :data="getDeliveryProductInfoList()"
+ border
+ size="small"
+ class="delivery-product-table"
+ style="width: 100%; margin-top: 16px"
+ >
+ <el-table-column
+ label="鎵瑰彿"
+ prop="batchNo"
+ min-width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="浜у搧鍚嶇О"
+ prop="productName"
+ min-width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="瑙勬牸鍨嬪彿"
+ prop="specificationModel"
+ min-width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍙戣揣鏁伴噺"
+ prop="deliveryQuantity"
+ min-width="120"
+ align="center"
+ />
</el-table>
<ImagePreview :file-list="detailRow.storageBlobVOs || []" />
</div>
@@ -209,21 +325,20 @@
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
-import {onMounted, ref, reactive, toRefs, getCurrentInstance} from "vue";
-import {ElMessageBox} from "element-plus";
-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,
delDeliveryLedger,
deductStock,
getDeliveryDetail,
} 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);
@@ -261,23 +376,34 @@
expressNumber: "", // 蹇�掑崟鍙�
},
rules: {
- salesContractNo: [{required: true, message: "璇烽�夋嫨閿�鍞鍗�", trigger: "change"}],
- customerName: [{required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur"}],
- type: [
- {required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change"}
+ salesContractNo: [
+ { required: true, message: "璇烽�夋嫨閿�鍞鍗�", trigger: "change" },
],
- shippingDate: [{required: true, message: "璇烽�夋嫨鍙戣揣鏃堕棿", trigger: "change"}],
+ customerName: [
+ { required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur" },
+ ],
+ type: [{ 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 = () => {
@@ -293,20 +419,22 @@
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;
+ });
};
// 閿�鍞鍗曞彉鍖栨椂鑷姩濉厖瀹㈡埛鍚嶇О
const handleSalesOrderChange = (value) => {
- const selectedOrder = salesOrderOptions.value.find(item => item.salesContractNo === value);
+ const selectedOrder = salesOrderOptions.value.find(
+ (item) => item.salesContractNo === value
+ );
if (selectedOrder) {
form.value.customerName = selectedOrder.customerName;
}
@@ -320,14 +448,14 @@
// 鎵撳紑寮规
const openForm = async (type, row) => {
// 鍙戣揣锛氫粎鈥滃鏍搁�氳繃鈥濆厑璁哥紪杈�
- if (type === 'edit' && row && !isApproved(row.status)) {
+ if (type === "edit" && row && !isApproved(row.status)) {
proxy.$modal.msgWarning("鍙湁瀹℃牳閫氳繃鐨勬暟鎹墠鍙互鍙戣揣");
return;
}
operationType.value = type;
- if (type === 'edit' && row) {
+ if (type === "edit" && row) {
form.value = {
id: row.id ?? null,
salesContractNo: row.salesContractNo ?? "",
@@ -362,62 +490,69 @@
proxy.$modal.msgError("鍔犺浇鍙戣揣鍙拌处璇︽儏澶辫触");
}
};
-const resolveDeliveryDetailList = data => {
+const resolveDeliveryDetailList = (data) => {
if (Array.isArray(data)) return data;
if (!data || typeof data !== "object") return [];
- return [
- data.batchNoDetailList,
- data.batchNoList,
- data.shippingBatchList,
- data.shippingInfoDetailList,
- data.detailList,
- data.batchDetailList,
- data.rows,
- data.records,
- data.list,
- data.data,
- ].find(value => Array.isArray(value) && value.length) || [];
+ return (
+ [
+ data.batchNoDetailList,
+ data.batchNoList,
+ data.shippingBatchList,
+ data.shippingInfoDetailList,
+ data.detailList,
+ data.batchDetailList,
+ data.rows,
+ data.records,
+ data.list,
+ data.data,
+ ].find((value) => Array.isArray(value) && value.length) || []
+ );
};
const getDeliveryProductInfoList = () => {
const row = detailRow.value;
if (!row) return [];
- const normalizeBatchNoList = value => {
+ const normalizeBatchNoList = (value) => {
if (Array.isArray(value)) return value;
if (typeof value === "string" && value.includes(",")) {
- return value.split(",").map(item => item.trim()).filter(Boolean);
+ return value
+ .split(",")
+ .map((item) => item.trim())
+ .filter(Boolean);
}
return value ? [value] : [];
};
- const detailList = detailProductList.value.length ? detailProductList.value : [
- row.batchNoDetailList,
- row.batchNoList,
- row.shippingBatchList,
- row.shippingInfoDetailList,
- row.detailList,
- row.batchDetailList,
- ].find(value => Array.isArray(value) && value.length);
+ const detailList = detailProductList.value.length
+ ? detailProductList.value
+ : [
+ row.batchNoDetailList,
+ row.batchNoList,
+ row.shippingBatchList,
+ row.shippingInfoDetailList,
+ row.detailList,
+ row.batchDetailList,
+ ].find((value) => Array.isArray(value) && value.length);
const batchNoList = normalizeBatchNoList(row.batchNo);
const toTableRow = (item = {}) => ({
batchNo:
- typeof item === "string" || typeof item === "number"
- ? item
- : item.batchNo ?? item.batchNumber ?? row.batchNo ?? "--",
+ typeof item === "string" || typeof item === "number"
+ ? item
+ : item.batchNo ?? item.batchNumber ?? row.batchNo ?? "--",
productName: item.productName ?? row.productName ?? "--",
specificationModel:
- item.specificationModel ?? item.model ?? row.specificationModel ?? "--",
+ item.specificationModel ?? item.model ?? row.specificationModel ?? "--",
deliveryQuantity:
- item.deliveryQuantity ??
- item.quantity ??
- item.shippingQuantity ??
- row.deliveryQuantity ??
- row.quantity ??
- "--",
+ item.deliveryQuantity ??
+ item.quantity ??
+ item.shippingQuantity ??
+ row.deliveryQuantity ??
+ row.quantity ??
+ "--",
});
if (detailList?.length) {
return detailList.map(toTableRow);
}
if (batchNoList.length) {
- return batchNoList.map(batchNo => toTableRow({batchNo}));
+ return batchNoList.map((batchNo) => toTableRow({ batchNo }));
}
return [toTableRow()];
};
@@ -435,9 +570,12 @@
id: form.value.id,
type: form.value.type,
shippingDate: form.value.shippingDate,
- shippingCarNumber: form.value.type === "璐ц溅" ? form.value.shippingCarNumber : "",
- expressCompany: form.value.type === "蹇��" ? form.value.expressCompany : "",
- expressNumber: form.value.type === "蹇��" ? form.value.expressNumber : "",
+ shippingCarNumber:
+ form.value.type === "璐ц溅" ? form.value.shippingCarNumber : "",
+ expressCompany:
+ form.value.type === "蹇��" ? form.value.expressCompany : "",
+ expressNumber:
+ form.value.type === "蹇��" ? form.value.expressNumber : "",
storageBlobDTOs: deliveryFileList.value || [],
};
deductStock(payload).then((res) => {
@@ -463,12 +601,12 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- proxy.download("/shippingInfo/export", {}, "鍙戣揣鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ .then(() => {
+ proxy.download("/shippingInfo/export", {}, "鍙戣揣鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鎵归噺鍒犻櫎
@@ -479,7 +617,9 @@
}
// 妫�鏌ラ�変腑鐨勮鏄惁鏈�"瀹℃牳涓�"鐘舵��
- const approvingRows = selectedRows.value.filter(row => isApproving(row.status));
+ const approvingRows = selectedRows.value.filter((row) =>
+ isApproving(row.status)
+ );
if (approvingRows.length > 0) {
proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘鍒犻櫎");
return;
@@ -491,15 +631,15 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- delDeliveryLedger(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ .then(() => {
+ delDeliveryLedger(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
});
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍗曚釜鍒犻櫎
@@ -515,15 +655,15 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- delDeliveryLedger([row.id]).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ .then(() => {
+ delDeliveryLedger([row.id]).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
});
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍙戣揣绫诲瀷鏍¢獙锛氳揣杞︽椂瑕佹眰杞︾墝锛屽揩閫掓椂瑕佹眰蹇�掑叕鍙�
@@ -543,7 +683,10 @@
// 鍙戣揣鍥剧墖涓婁紶鍓嶆牎妫�
function handleDeliveryBeforeUpload(file) {
// 鏍℃鏂囦欢绫诲瀷
- const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg';
+ const isImage =
+ file.type === "image/png" ||
+ file.type === "image/jpeg" ||
+ file.type === "image/jpg";
if (!isImage) {
proxy.$modal.msgError("鍙兘涓婁紶 jpg銆乯peg銆乸ng 鏍煎紡鐨勫浘鐗�!");
return false;
@@ -578,24 +721,30 @@
// 绉婚櫎鍙戣揣鍥剧墖
function handleDeliveryRemove(file) {
- console.log('file--', file)
+ console.log("file--", file);
// 濡傛灉鏄紪杈戞ā寮忎笖鏂囦欢鏈� id锛岄渶瑕佽皟鐢ㄦ帴鍙e垹闄�
if (operationType.value === "edit") {
let ids = [];
ids.push(file.uid);
- delLedgerFile(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- // 浠庢枃浠跺垪琛ㄤ腑绉婚櫎
- const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
- if (index > -1) {
- deliveryFileList.value.splice(index, 1);
- }
- }).catch(() => {
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- });
+ delLedgerFile(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ // 浠庢枃浠跺垪琛ㄤ腑绉婚櫎
+ const index = deliveryFileList.value.findIndex(
+ (item) => item.uid === file.uid
+ );
+ if (index > -1) {
+ deliveryFileList.value.splice(index, 1);
+ }
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍒犻櫎澶辫触");
+ });
} else {
// 鏂板妯″紡鎴栨病鏈� id 鐨勬枃浠讹紝鐩存帴浠庡垪琛ㄤ腑绉婚櫎
- const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
+ const index = deliveryFileList.value.findIndex(
+ (item) => item.uid === file.uid
+ );
if (index > -1) {
deliveryFileList.value.splice(index, 1);
}
@@ -614,92 +763,92 @@
// 鑾峰彇瀹℃牳鐘舵�佹枃鏈�
const getApprovalStatusText = (status) => {
- if (status === null || status === undefined || status === '') {
- return '寰呭鏍�';
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鏍�";
}
// 濡傛灉鏄暟瀛�
- if (typeof status === 'number') {
+ if (typeof status === "number") {
const statusMap = {
- 0: '寰呭鏍�',
- 1: '瀹℃牳涓�',
- 2: '瀹℃牳鎷掔粷',
- 3: '瀹℃牳閫氳繃'
+ 0: "寰呭鏍�",
+ 1: "瀹℃牳涓�",
+ 2: "瀹℃牳鎷掔粷",
+ 3: "瀹℃牳閫氳繃",
};
- return statusMap[status] || '寰呭鏍�';
+ return statusMap[status] || "寰呭鏍�";
}
// 濡傛灉鏄瓧绗︿覆锛岀洿鎺ヨ繑鍥炴垨鏄犲皠
const statusStr = String(status).trim();
const statusTextMap = {
- '寰呭鏍�': '寰呭鏍�',
- '瀹℃牳涓�': '瀹℃牳涓�',
- '瀹℃牳鎷掔粷': '瀹℃牳鎷掔粷',
- '瀹℃牳閫氳繃': '瀹℃牳閫氳繃',
- '宸插彂璐�': '宸插彂璐�',
- '0': '寰呭鏍�',
- '1': '瀹℃牳涓�',
- '2': '瀹℃牳鎷掔粷',
- '3': '瀹℃牳閫氳繃'
+ 寰呭鏍�: "寰呭鏍�",
+ 瀹℃牳涓�: "瀹℃牳涓�",
+ 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+ 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+ 宸插彂璐�: "宸插彂璐�",
+ 0: "寰呭鏍�",
+ 1: "瀹℃牳涓�",
+ 2: "瀹℃牳鎷掔粷",
+ 3: "瀹℃牳閫氳繃",
};
- return statusTextMap[statusStr] || statusStr || '寰呭鏍�';
+ return statusTextMap[statusStr] || statusStr || "寰呭鏍�";
};
// 鑾峰彇瀹℃牳鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
const getApprovalStatusType = (status) => {
- if (status === null || status === undefined || status === '') {
- return 'info';
+ if (status === null || status === undefined || status === "") {
+ return "info";
}
// 濡傛灉鏄暟瀛�
- if (typeof status === 'number') {
+ if (typeof status === "number") {
const typeMap = {
- 0: 'info', // 寰呭鏍� - 鐏拌壊
- 1: 'warning', // 瀹℃牳涓� - 榛勮壊
- 2: 'danger', // 瀹℃牳鎷掔粷 - 绾㈣壊
- 3: 'success' // 瀹℃牳閫氳繃 - 缁胯壊
+ 0: "info", // 寰呭鏍� - 鐏拌壊
+ 1: "warning", // 瀹℃牳涓� - 榛勮壊
+ 2: "danger", // 瀹℃牳鎷掔粷 - 绾㈣壊
+ 3: "success", // 瀹℃牳閫氳繃 - 缁胯壊
};
- return typeMap[status] || 'info';
+ return typeMap[status] || "info";
}
// 濡傛灉鏄瓧绗︿覆
const statusStr = String(status).trim();
const typeTextMap = {
- '寰呭鏍�': 'info',
- '瀹℃牳涓�': 'warning',
- '瀹℃牳鎷掔粷': 'danger',
- '瀹℃牳閫氳繃': 'success',
- '宸插彂璐�': 'success',
- '0': 'info',
- '1': 'warning',
- '2': 'danger',
- '3': 'success'
+ 寰呭鏍�: "info",
+ 瀹℃牳涓�: "warning",
+ 瀹℃牳鎷掔粷: "danger",
+ 瀹℃牳閫氳繃: "success",
+ 宸插彂璐�: "success",
+ 0: "info",
+ 1: "warning",
+ 2: "danger",
+ 3: "success",
};
- return typeTextMap[statusStr] || 'info';
+ return typeTextMap[statusStr] || "info";
};
// 妫�鏌ュ鏍哥姸鎬佹槸鍚︿负"瀹℃牳閫氳繃"
const isApproved = (status) => {
- if (status === null || status === undefined || status === '') {
+ if (status === null || status === undefined || status === "") {
return false;
}
// 濡傛灉鏄暟瀛楋紝3 琛ㄧず瀹℃牳閫氳繃
- if (typeof status === 'number') {
+ if (typeof status === "number") {
return status === 3;
}
// 濡傛灉鏄瓧绗︿覆
const statusStr = String(status).trim();
- return statusStr === '瀹℃牳閫氳繃' || statusStr === '3';
+ return statusStr === "瀹℃牳閫氳繃" || statusStr === "3";
};
// 妫�鏌ュ鏍哥姸鎬佹槸鍚︿负"瀹℃牳涓�"
const isApproving = (status) => {
- if (status === null || status === undefined || status === '') {
+ if (status === null || status === undefined || status === "") {
return false;
}
// 濡傛灉鏄暟瀛楋紝1 琛ㄧず瀹℃牳涓�
- if (typeof status === 'number') {
+ if (typeof status === "number") {
return status === 1;
}
// 濡傛灉鏄瓧绗︿覆
const statusStr = String(status).trim();
- return statusStr === '瀹℃牳涓�' || statusStr === '1';
+ return statusStr === "瀹℃牳涓�" || statusStr === "1";
};
onMounted(() => {
@@ -752,4 +901,3 @@
color: #909399;
}
</style>
-
diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 7a35ea9..f4cd44d 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -55,14 +55,14 @@
<el-date-picker v-model="form.makeTime" type="datetime" style="width:100%" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
</el-col>
- <el-col :span="4">
+ <!-- <el-col :span="4">
<el-form-item label="鐘舵�侊細" prop="status">
<el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��">
<el-option label="寰呭鐞�" :value="0" />
<el-option label="宸插鐞�" :value="1" />
</el-select>
</el-form-item>
- </el-col>
+ </el-col> -->
<el-col :span="4">
<el-form-item label="閫�璐у師鍥狅細" prop="returnReason">
<el-input v-model="form.returnReason" placeholder="璇疯緭鍏ラ��璐у師鍥�" />
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 8d25f53..4e2d84e 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -898,7 +898,8 @@
prop="type">
<el-select v-model="deliveryForm.type"
placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%">
+ style="width: 100%"
+ @change="handleDeliveryTypeChange">
<el-option label="璐ц溅"
value="璐ц溅" />
<el-option label="蹇��"
@@ -910,6 +911,41 @@
<el-form-item label="寰呭彂璐ф暟閲忥細">
<el-input :model-value="currentDeliveryRow?.noQuantity"
disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24" v-if="deliveryForm.type === '璐ц溅'">
+ <el-form-item label="鍙戣揣杞︾墝鍙凤細"
+ prop="shippingCarNumber">
+ <el-input v-model="deliveryForm.shippingCarNumber"
+ placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="24" v-else>
+ <el-form-item label="蹇�掑叕鍙革細"
+ prop="expressCompany">
+ <el-input v-model="deliveryForm.expressCompany"
+ placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30" v-if="deliveryForm.type === '蹇��'">
+ <el-col :span="24">
+ <el-form-item label="蹇�掑崟鍙凤細"
+ prop="expressNumber">
+ <el-input v-model="deliveryForm.expressNumber"
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍙戣揣鍥剧墖锛�">
+ <ImageUpload v-model:file-list="deliveryFileList" :limit="9" />
</el-form-item>
</el-col>
</el-row>
@@ -990,6 +1026,7 @@
import useFormData from "@/hooks/useFormData.js";
import dayjs from "dayjs";
import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+ import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
import { getCurrentDate } from "@/utils/index.js";
import { listCustomer } from "@/api/basicData/customer.js";
@@ -1017,6 +1054,7 @@
});
const total = ref(0);
const fileList = ref([]);
+ const deliveryFileList = ref([]);
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const operationType = ref("");
@@ -1195,11 +1233,30 @@
deliveryQuantity: 0,
}));
};
+ const validateDeliveryShippingCarNumber = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "璐ц溅" && !value) {
+ return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
+ }
+ callback();
+ };
+ const validateDeliveryExpressCompany = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "蹇��" && !value) {
+ return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
+ }
+ callback();
+ };
const deliveryFormData = reactive({
deliveryForm: {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
type: "璐ц溅", // 璐ц溅, 蹇��
},
deliveryRules: {
+ shippingCarNumber: [
+ { validator: validateDeliveryShippingCarNumber, trigger: "blur" },
+ ],
+ expressCompany: [{ validator: validateDeliveryExpressCompany, trigger: "blur" }],
type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
},
});
@@ -2621,10 +2678,14 @@
row.productModelId || row.modelId
);
deliveryForm.value = {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
type: "璐ц溅",
batchNo: [],
batchNoList,
};
+ deliveryFileList.value = [];
deliveryFormVisible.value = true;
};
@@ -2662,6 +2723,19 @@
salesLedgerId: salesLedgerId,
salesLedgerProductId: currentDeliveryRow.value.id,
type: deliveryForm.value.type,
+ shippingCarNumber:
+ deliveryForm.value.type === "璐ц溅"
+ ? deliveryForm.value.shippingCarNumber
+ : "",
+ expressCompany:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressCompany
+ : "",
+ expressNumber:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressNumber
+ : "",
+ storageBlobDTOs: deliveryFileList.value || [],
batchNo: deliveryForm.value.batchNo,
batchNoDetailList: selectedBatchRows.map(item => ({
stockInventoryId: item.id,
@@ -2701,8 +2775,18 @@
};
// 鍏抽棴鍙戣揣寮规
+ const handleDeliveryTypeChange = val => {
+ if (val === "璐ц溅") {
+ deliveryForm.value.expressCompany = "";
+ deliveryForm.value.expressNumber = "";
+ } else {
+ deliveryForm.value.shippingCarNumber = "";
+ }
+ };
+
const closeDeliveryDia = () => {
proxy.resetForm("deliveryFormRef");
+ deliveryFileList.value = [];
deliveryFormVisible.value = false;
currentDeliveryRow.value = null;
};
--
Gitblit v1.9.3