From a1eff60449d20fb54bfdf04690cfa23b3d8e7812 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期一, 26 一月 2026 17:16:49 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New
---
src/views/procurementManagement/procurementLedger/index.vue | 952 +++++++++++++++++++------------------------
src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue | 172 ++++---
src/views/procurementManagement/procurementReport/index.vue | 4
src/views/equipmentManagement/measurementEquipment/components/formDia.vue | 7
src/api/procurementManagement/procurementInvoiceLedger.js | 13
src/api/procurementManagement/procurementLedger.js | 22
src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue | 96 ++--
src/views/collaborativeApproval/approvalProcess/index.vue | 3
src/views/salesManagement/salesLedger/index.vue | 18
src/views/equipmentManagement/inspectionManagement/index.vue | 8
10 files changed, 614 insertions(+), 681 deletions(-)
diff --git a/src/api/procurementManagement/procurementInvoiceLedger.js b/src/api/procurementManagement/procurementInvoiceLedger.js
index 2408bbd..038e94f 100644
--- a/src/api/procurementManagement/procurementInvoiceLedger.js
+++ b/src/api/procurementManagement/procurementInvoiceLedger.js
@@ -83,11 +83,18 @@
});
}
-export function getProductRecordById(params) {
+// export function getProductRecordById(params) {
+// return request({
+// url: "/purchase/registration/getProductRecordById",
+// method: "get",
+// params: params,
+// });
+// }
+export function getProductRecordById(data) {
return request({
url: "/purchase/registration/getProductRecordById",
- method: "get",
- params: params,
+ method: "post",
+ data: data,
});
}
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index 69a23f7..c9a2da8 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -81,17 +81,24 @@
}
// 淇濆瓨閲囪喘妯℃澘
-// /purchase/ledger/addPurchaseTemplate
export function addPurchaseTemplate(data) {
return request({
- url: "/purchase/ledger/addPurchaseTemplate",
+ url: "/purchaseLedgerTemplate/add",
+ method: "post",
+ data: data,
+ });
+}
+
+// 淇敼閲囪喘妯℃澘
+export function updatePurchaseTemplate(data) {
+ return request({
+ url: "/purchaseLedgerTemplate/update",
method: "post",
data: data,
});
}
// 鏌ヨ閲囪喘妯℃澘
-// /purchase/ledger/getPurchaseTemplateList
export function getPurchaseTemplateList(query) {
return request({
url: "/purchase/ledger/getPurchaseTemplateList",
@@ -99,3 +106,12 @@
params: query,
});
}
+
+// 鍒犻櫎閲囪喘妯℃澘
+export function delPurchaseTemplate(id) {
+ return request({
+ url: "/purchaseLedgerTemplate/delete",
+ method: "delete",
+ data: id,
+ });
+}
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 00e59c9..95d97cb 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -38,7 +38,7 @@
<el-button
type="primary"
@click="openForm('add')"
- v-if="currentApproveType !== 6 && currentApproveType !== 7"
+ v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
>鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button
@@ -215,6 +215,7 @@
openForm("edit", row);
},
disabled: (row) =>
+ currentApproveType.value === 5 ||
currentApproveType.value === 6 ||
currentApproveType.value === 7 ||
row.approveStatus == 2 ||
diff --git a/src/views/equipmentManagement/inspectionManagement/index.vue b/src/views/equipmentManagement/inspectionManagement/index.vue
index 381fc69..245f3d2 100644
--- a/src/views/equipmentManagement/inspectionManagement/index.vue
+++ b/src/views/equipmentManagement/inspectionManagement/index.vue
@@ -1,10 +1,10 @@
<template>
<div class="app-container">
<el-form :inline="true" :model="queryParams" class="search-form">
- <el-form-item label="鎼滅储">
+ <el-form-item label="宸℃浠诲姟鍚嶇О">
<el-input
- v-model="queryParams.searchAll"
- placeholder="璇疯緭鍏ュ叧閿瓧"
+ v-model="queryParams.taskName"
+ placeholder="璇疯緭鍏ュ贰妫�浠诲姟鍚嶇О"
clearable
:style="{ width: '100%' }"
/>
@@ -100,7 +100,7 @@
// 鏌ヨ鍙傛暟
const queryParams = reactive({
- searchAll: "",
+ taskName: "",
});
// 鍗曢�夋閰嶇疆
diff --git a/src/views/equipmentManagement/measurementEquipment/components/formDia.vue b/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
index 9ac5c44..d2a1969 100644
--- a/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
+++ b/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
@@ -29,7 +29,7 @@
<el-col :span="12">
<el-form-item label="瀹夎浣嶇疆锛�" prop="instationLocation">
<el-input
- v-model="form.installationLocation"
+ v-model="form.instationLocation"
placeholder="璇疯緭鍏�"
clearable
/>
@@ -171,7 +171,7 @@
const data = reactive({
form: {
code: "",
- installationLocation: "",
+ instationLocation: "",
mostDate:"",
model: "",
cycle:"",
@@ -179,6 +179,7 @@
nextDate: "",
userId: "",
recordDate: "",
+ unit:"",
tempFileIds: []
},
rules: {
@@ -188,7 +189,7 @@
nextDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
userId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
recordDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
- installationLocation: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ instationLocation: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
mostDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
cycle: [{required: true, message: "璇烽�夋嫨", trigger: "blur"}],
valid: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue b/src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue
index f939be4..7f8b852 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue
@@ -23,17 +23,28 @@
</el-col>
<el-col :span="12">
<el-form-item label="鍙戠エ鍙凤細">
- <el-input disabled v-model="form.invoiceNumber" />
+ <el-input disabled
+ v-model="form.invoiceNumber" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="鏉ョエ鏁帮細">
- <el-input-number :step="0.1" :min="0" style="width: 100%" v-model="form.ticketsNum" @change="inputTicketsNum" :precision="2"/>
+ <el-input-number :step="0.1"
+ :min="0"
+ style="width: 100%"
+ v-model="form.ticketsNum"
+ @change="inputTicketsNum"
+ :precision="2" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="鏈鏉ョエ閲戦(鍏�)锛�">
- <el-input-number :step="0.1" :min="0" style="width: 100%" v-model="form.ticketsAmount" @change="inputTicketsAmount" :precision="2"/>
+ <el-input-number :step="0.1"
+ :min="0"
+ style="width: 100%"
+ v-model="form.ticketsAmount"
+ @change="inputTicketsAmount"
+ :precision="2" />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -46,83 +57,92 @@
</template>
<script setup>
-import useFormData from "@/hooks/useFormData";
-import { getProductRecordById } from "@/api/procurementManagement/procurementInvoiceLedger";
-const { proxy } = getCurrentInstance()
+ import useFormData from "@/hooks/useFormData";
+ import { getProductRecordById } from "@/api/procurementManagement/procurementInvoiceLedger";
+ const { proxy } = getCurrentInstance();
-defineOptions({
- name: "鏉ョエ鍙拌处琛ㄥ崟",
-});
-const temFutureTickets = ref(0)
-const { form, resetForm } = useFormData({
- id: undefined,
- purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
- salesContractNo: undefined, // 閿�鍞悎鍚屽彿
- createdAt: undefined, // 鍒涘缓鏃堕棿
- invoiceNumber: undefined, // 鍙戠エ鍙�
- ticketsNum: undefined, // 鏉ョエ鏁�
- ticketsAmount: undefined, // 鏉ョエ閲戦
- taxInclusiveUnitPrice: undefined, // 鍚◣鍗曚环
-});
+ defineOptions({
+ name: "鏉ョエ鍙拌处琛ㄥ崟",
+ });
+ const temFutureTickets = ref(0);
+ const { form, resetForm } = useFormData({
+ id: undefined,
+ purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
+ salesContractNo: undefined, // 閿�鍞悎鍚屽彿
+ createdAt: undefined, // 鍒涘缓鏃堕棿
+ invoiceNumber: undefined, // 鍙戠エ鍙�
+ ticketsNum: undefined, // 鏉ョエ鏁�
+ ticketsAmount: undefined, // 鏉ョエ閲戦
+ taxInclusiveUnitPrice: undefined, // 鍚◣鍗曚环
+ });
-const load = async (id) => {
- const { code, data } = await getProductRecordById({ id });
- if (code === 200) {
- form.id = data.id;
- form.purchaseContractNumber = data.purchaseContractNumber;
- form.salesContractNo = data.salesContractNo;
- form.createdAt = data.createdAt;
- form.invoiceNumber = data.invoiceNumber;
- form.ticketsNum = data.ticketsNum;
- form.ticketsAmount = data.ticketsAmount.toFixed(2);
- form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice;
- form.futureTickets = data.futureTickets;
- temFutureTickets.value = data.futureTickets;
- }
-};
+ const load = async (id, purchaseLedgerId, productModelId) => {
+ const { code, data } = await getProductRecordById({
+ id: id,
+ purchaseLedgerId: purchaseLedgerId,
+ productModelId: productModelId,
+ });
+ if (code === 200) {
+ form.id = data.id;
+ form.purchaseContractNumber = data.purchaseContractNumber;
+ form.salesContractNo = data.salesContractNo;
+ form.createdAt = data.createdAt;
+ form.invoiceNumber = data.invoiceNumber;
+ form.ticketsNum = data.ticketsNum;
+ form.ticketsAmount = data.ticketsAmount.toFixed(2);
+ form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice;
+ form.futureTickets = data.futureTickets;
+ temFutureTickets.value = data.futureTickets;
+ }
+ };
-const inputTicketsNum = (val) => {
- // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
- if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
- proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
- return;
- }
- if (Number(form.ticketsNum) > Number(temFutureTickets.value)) {
- proxy.$modal.msgWarning("寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
- form.ticketsNum = temFutureTickets.value
- }
-
- // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
- const ticketsAmount = Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice);
- const futureTickets = Number(temFutureTickets.value) - Number(form.ticketsNum);
- form.futureTickets = Number(futureTickets.toFixed(2));
- form.ticketsAmount = Number(ticketsAmount.toFixed(2));
-};
-const inputTicketsAmount = (val) => {
- // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
- if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
- proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
- return;
- }
-
- if (Number(val) > Number(form.futureTickets*form.taxInclusiveUnitPrice)) {
- proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鎬婚噾棰�");
- form.ticketsAmount = (form.futureTickets*form.taxInclusiveUnitPrice).toFixed(2)
- const ticketsNum = Number(form.ticketsAmount) / Number(form.taxInclusiveUnitPrice);
- form.ticketsNum = Number(ticketsNum.toFixed(2))
- return;
- }
-
- // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
- const ticketsNum = Number(val) / Number(form.taxInclusiveUnitPrice);
- form.ticketsNum = Number(ticketsNum.toFixed(2));
-};
+ const inputTicketsNum = val => {
+ // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
+ if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
+ proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
+ return;
+ }
+ if (Number(form.ticketsNum) > Number(temFutureTickets.value)) {
+ proxy.$modal.msgWarning("寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
+ form.ticketsNum = temFutureTickets.value;
+ }
-defineExpose({
- load,
- form,
- resetForm,
-});
+ // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
+ const ticketsAmount =
+ Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice);
+ const futureTickets =
+ Number(temFutureTickets.value) - Number(form.ticketsNum);
+ form.futureTickets = Number(futureTickets.toFixed(2));
+ form.ticketsAmount = Number(ticketsAmount.toFixed(2));
+ };
+ const inputTicketsAmount = val => {
+ // 纭繚鍚◣鍗曚环瀛樺湪涓斾笉涓洪浂
+ if (!form.taxInclusiveUnitPrice || Number(form.taxInclusiveUnitPrice) === 0) {
+ proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
+ return;
+ }
+
+ if (Number(val) > Number(form.futureTickets * form.taxInclusiveUnitPrice)) {
+ proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鎬婚噾棰�");
+ form.ticketsAmount = (
+ form.futureTickets * form.taxInclusiveUnitPrice
+ ).toFixed(2);
+ const ticketsNum =
+ Number(form.ticketsAmount) / Number(form.taxInclusiveUnitPrice);
+ form.ticketsNum = Number(ticketsNum.toFixed(2));
+ return;
+ }
+
+ // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
+ const ticketsNum = Number(val) / Number(form.taxInclusiveUnitPrice);
+ form.ticketsNum = Number(ticketsNum.toFixed(2));
+ };
+
+ defineExpose({
+ load,
+ form,
+ resetForm,
+ });
</script>
<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue b/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
index 82b4164..68f3650 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
@@ -1,62 +1,66 @@
<template>
- <el-dialog :title="modalOptions.title" v-model="visible" @close="close">
+ <el-dialog :title="modalOptions.title"
+ v-model="visible"
+ @close="close">
<EditForm ref="editFormRef" />
<template #footer>
- <el-button type="primary" :loading="loading" @click="sendForm">
- {{ modalOptions.confirmText }}
- </el-button>
+ <el-button type="primary"
+ :loading="loading"
+ @click="sendForm">
+ {{ modalOptions.confirmText }}
+ </el-button>
<el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
</template>
</el-dialog>
</template>
<script setup>
-import { useModal } from "@/hooks/useModal";
-import EditForm from "../Form/EditForm.vue";
-import { updateRegistration } from "@/api/procurementManagement/procurementInvoiceLedger";
-import { ElMessage } from "element-plus";
+ import { useModal } from "@/hooks/useModal";
+ import EditForm from "../Form/EditForm.vue";
+ import { updateRegistration } from "@/api/procurementManagement/procurementInvoiceLedger";
+ import { ElMessage } from "element-plus";
-defineOptions({
- name: "鏉ョエ鍙拌处缂栬緫",
-});
-const emits = defineEmits(["success"]);
+ defineOptions({
+ name: "鏉ョエ鍙拌处缂栬緫",
+ });
+ const emits = defineEmits(["success"]);
-const saleLedgerProjectId = ref('')
-const editFormRef = ref();
-const {
- id,
- visible,
- loading,
- openModal,
- modalOptions,
- handleConfirm,
- closeModal,
-} = useModal({ title: "鏉ョエ鍙拌处" });
+ const saleLedgerProjectId = ref("");
+ const editFormRef = ref();
+ const {
+ id,
+ visible,
+ loading,
+ openModal,
+ modalOptions,
+ handleConfirm,
+ closeModal,
+ } = useModal({ title: "鏉ョエ鍙拌处" });
-const open = async (row) => {
- openModal(row.id);
- saleLedgerProjectId.value = row.saleLedgerProjectId;
- await nextTick();
- editFormRef.value.load(row.id);
-};
+ const open = async row => {
+ openModal(row.id);
+ saleLedgerProjectId.value = row.saleLedgerProjectId;
+ await nextTick();
+ editFormRef.value.load(row.id, row.purchaseLedgerId, row.productModelId);
+ };
-const close = () => {
- editFormRef.value.resetForm();
- closeModal();
-};
+ const close = () => {
+ editFormRef.value.resetForm();
+ closeModal();
+ };
-const sendForm = async () => {
- const form = editFormRef.value.form;
- form.saleLedgerProjectId = saleLedgerProjectId.value;
- const { code } = await updateRegistration(form);
- if (code === 200) {
- emits("success");
- ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
- close();
- }
-};
+ const sendForm = async () => {
+ const form = editFormRef.value.form;
+ form.saleLedgerProjectId = saleLedgerProjectId.value;
+ const { code } = await updateRegistration(form);
+ if (code === 200) {
+ emits("success");
+ ElMessage({ message: "鎿嶄綔鎴愬姛", type: "success" });
+ close();
+ }
+ };
-defineExpose({
- open,
-});
+ defineExpose({
+ open,
+ });
</script>
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 9b86624..e40a68a 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -53,8 +53,6 @@
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
<el-button type="primary"
@click="openForm('add')">鏂板鍙拌处</el-button>
- <el-button type="success"
- @click="openScanAddDialog">鎵爜鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger"
plain
@@ -69,8 +67,7 @@
show-summary
:summary-method="summarizeMainTable"
@expand-change="expandChange"
- height="calc(100vh - 19em)"
- :row-class-name="tableRowClassName">
+ height="calc(100vh - 21.5em)">
<el-table-column align="center"
type="selection"
width="55" />
@@ -112,36 +109,28 @@
width="60" />
<el-table-column label="閲囪喘鍚堝悓鍙�"
prop="purchaseContractNumber"
- width="200"
+ width="160"
show-overflow-tooltip />
<el-table-column label="閿�鍞悎鍚屽彿"
prop="salesContractNo"
+ width="160"
show-overflow-tooltip />
<el-table-column label="渚涘簲鍟嗗悕绉�"
prop="supplierName"
+ width="160"
show-overflow-tooltip />
- <el-table-column label="璁㈠崟鐘舵��"
- width="100"
- align="center">
- <template #default="scope">
- <el-tag v-if="scope.row.isInvalid"
- type="danger"
- size="small">澶辨晥</el-tag>
- <el-tag v-else
- type="success"
- size="small">姝e父</el-tag>
- </template>
- </el-table-column>
<el-table-column label="椤圭洰鍚嶇О"
prop="projectName"
- width="420"
+ width="320"
show-overflow-tooltip />
<el-table-column label="瀹℃壒鐘舵��"
prop="approvalStatus"
- width="200"
+ width="100"
show-overflow-tooltip>
<template #default="scope">
- <el-tag size="small">
+ <el-tag
+ :type="getApprovalStatusType(scope.row.approvalStatus)"
+ size="small">
{{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
</el-tag>
</template>
@@ -169,17 +158,14 @@
show-overflow-tooltip />
<el-table-column fixed="right"
label="鎿嶄綔"
- width="180"
+ width="120"
align="center">
<template #default="scope">
<el-button link
type="primary"
size="small"
- @click="openForm('edit', scope.row)">缂栬緫</el-button>
- <el-button link
- type="success"
- size="small"
- @click="showQRCode(scope.row)">鐢熸垚浜岀淮鐮�</el-button>
+ @click="openForm('edit', scope.row)"
+ :disabled="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4">缂栬緫</el-button>
<el-button link
type="primary"
size="small"
@@ -194,10 +180,13 @@
:limit="page.size"
@pagination="paginationChange" />
</div>
- <el-dialog v-model="dialogFormVisible"
+ <FormDialog v-model="dialogFormVisible"
:title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
- width="70%"
- @close="closeDia">
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
<el-form :model="form"
label-width="140px"
label-position="top"
@@ -275,24 +264,12 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="瀹℃壒浜猴細"
- prop="approverId">
- <el-select v-model="form.approverId"
- placeholder="璇烽�夋嫨瀹℃壒浜�"
- clearable>
- <el-option v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId" />
- </el-select>
- </el-form-item>
<el-form-item label="褰曞叆浜猴細"
- prop="recorderId"
- v-show="false">
+ prop="recorderId">
<el-select v-model="form.recorderId"
placeholder="璇烽�夋嫨"
clearable
- disabled>
+ filterable>
<el-option v-for="item in userList"
:key="item.userId"
:label="item.nickName"
@@ -313,6 +290,50 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item>
+ <template #label>
+ <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
+ <span>瀹℃壒浜洪�夋嫨锛�</span>
+ <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">鏂板鑺傜偣</el-button>
+ </div>
+ </template>
+ <div class="approver-nodes-container">
+ <div
+ v-for="(node, index) in approverNodes"
+ :key="node.id"
+ class="approver-node-item"
+ >
+ <div class="approver-node-header">
+ <span class="approver-node-label">瀹℃壒鑺傜偣 {{ index + 1 }}</span>
+ <el-button
+ v-if="approverNodes.length > 1"
+ type="danger"
+ size="small"
+ text
+ @click="removeApproverNode(index)"
+ icon="Delete"
+ >鍒犻櫎</el-button>
+ </div>
+ <el-select
+ v-model="node.userId"
+ placeholder="璇烽�夋嫨瀹℃壒浜�"
+ filterable
+ style="width: 100%;"
+ >
+ <el-option
+ v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId"
+ />
+ </el-select>
+ </div>
+ </div>
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-row>
<el-form-item label="浜у搧淇℃伅锛�"
prop="entryDate">
@@ -323,29 +344,42 @@
@click="deleteProduct">鍒犻櫎</el-button>
</el-form-item>
<div class="select-button-group"
- style="width: 220px; margin: 20px 0;"
+ style="width: 500px; margin: 20px 0;"
v-if="operationType === 'add'">
<el-select filterable
allow-create
:reserve-keyword="true"
:default-first-option="false"
+ clearable
v-model="templateName"
:input-value="filterInputValue"
@filter-change="onTemplateFilterChange"
@change="onTemplateChange"
- style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;"
- placeholder="璇烽�夋嫨"
+ @focus="getTemplateList"
+ style="width: 500px;"
+ placeholder="璇烽�夋嫨妯$増鎴栬�呰緭鍏ユ柊鐨勬ā鐗堝悕绉板悗閫夋嫨"
class="no-arrow-select">
<el-option v-for="item in templateList"
- :key="item.value"
+ :key="item.id || item.value"
:label="item.templateName"
- :value="item.templateName"></el-option>
+ :value="item.templateName">
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <span>{{ item.templateName }}</span>
+ <el-icon
+ v-if="item.id"
+ class="delete-icon"
+ @click.stop="handleDeleteTemplate(item)"
+ style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
+ <Delete />
+ </el-icon>
+ </div>
+ </el-option>
</el-select>
<!-- 鎸夐挳锛氫笌 Select 楂樺害鍖归厤锛屽幓鎺夊乏渚ц竟妗嗭紝鏃犵紳琛旀帴 -->
<el-button size="small"
- style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;"
+ style="height: 32px;margin-left: 8px;"
@click="handleButtonClick"
- :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate">
+ :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)">
淇濆瓨
</el-button>
</div>
@@ -450,18 +484,14 @@
</el-col>
</el-row>
</el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog v-model="productFormVisible"
+ </FormDialog>
+ <FormDialog v-model="productFormVisible"
:title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- width="40%"
- @close="closeProductDia">
+ :width="'40%'"
+ :operation-type="productOperationType"
+ @close="closeProductDia"
+ @confirm="submitProduct"
+ @cancel="closeProductDia">
<el-form :model="productForm"
label-width="140px"
label-position="top"
@@ -617,228 +647,12 @@
</el-col>
</el-row>
</el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitProduct">纭</el-button>
- <el-button @click="closeProductDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 浜岀淮鐮佹樉绀哄璇濇 -->
- <el-dialog v-model="qrCodeDialogVisible"
- title="閲囪喘鍚堝悓鍙蜂簩缁寸爜"
- width="400px"
- center>
- <div style="text-align: center;">
- <img :src="qrCodeUrl"
- alt="浜岀淮鐮�"
- style="width:200px;height:200px;" />
- <div style="margin: 20px;">
- <el-button type="primary"
- @click="downloadQRCode">涓嬭浇浜岀淮鐮佸浘鐗�</el-button>
- </div>
- </div>
- </el-dialog>
- <!-- 鎵爜鏂板瀵硅瘽妗� -->
- <el-dialog v-model="scanAddDialogVisible"
- title="鎵爜鏂板閲囪喘鍙拌处"
- width="70%"
- @close="closeScanAddDialog">
- <el-form :model="scanAddForm"
- label-width="140px"
- label-position="top"
- :rules="scanAddRules"
- ref="scanAddFormRef">
- <el-row :gutter="20">
- <el-col :span="24">
- <el-form-item label="鎵爜鍐呭锛�">
- <el-input v-model="scanAddForm.scanContent"
- type="textarea"
- :rows="3"
- placeholder="璇锋壂鎻忎簩缁寸爜鎴栨墜鍔ㄨ緭鍏ラ噰璐悎鍚屼俊鎭�"
- @input="parseScanContent" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="閲囪喘鍚堝悓鍙凤細"
- prop="purchaseContractNumber">
- <el-input v-model="scanAddForm.purchaseContractNumber"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟嗗悕绉帮細"
- prop="supplierName">
- <el-input v-model="scanAddForm.supplierName"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О锛�"
- prop="projectName">
- <el-input v-model="scanAddForm.projectName"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堝悓閲戦(鍏�)锛�"
- prop="contractAmount">
- <el-input-number v-model="scanAddForm.contractAmount"
- :precision="2"
- :step="0.1"
- clearable
- style="width: 100%"
- placeholder="璇疯緭鍏�" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡锛�">
- <el-input v-model="scanAddForm.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆浜猴細">
- <el-input v-model="scanAddForm.recorderName"
- disabled />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="24">
- <el-form-item label="澶囨敞锛�">
- <el-input v-model="scanAddForm.remark"
- type="textarea"
- :rows="2"
- placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitScanAdd">纭鏂板</el-button>
- <el-button @click="closeScanAddDialog">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 鎵爜鐧昏瀵硅瘽妗� -->
- <el-dialog v-model="scanDialogVisible"
- title="鎵爜鐧昏"
- width="60%"
- @close="closeScanDialog">
- <el-form :model="scanForm"
- label-width="120px"
- label-position="left"
- :rules="scanRules"
- ref="scanFormRef">
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="閲囪喘鍚堝悓鍙凤細">
- <el-input v-model="scanForm.purchaseContractNumber"
- disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟嗗悕绉帮細">
- <el-input v-model="scanForm.supplierName"
- disabled />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О锛�">
- <el-input v-model="scanForm.projectName"
- disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鎵爜鏃堕棿锛�">
- <el-input v-model="scanForm.scanTime"
- disabled />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="鎵爜浜猴細">
- <el-input v-model="scanForm.scannerName"
- disabled />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鎵爜鐘舵�侊細">
- <el-tag :type="scanForm.scanStatus === '宸叉壂鐮�' ? 'success' : 'warning'">
- {{ scanForm.scanStatus }}
- </el-tag>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="24">
- <el-form-item label="鎵爜澶囨敞锛�">
- <el-input v-model="scanForm.scanRemark"
- type="textarea"
- :rows="3"
- placeholder="璇疯緭鍏ユ壂鐮佸娉ㄤ俊鎭�" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="24">
- <el-form-item label="鎵爜璁板綍锛�">
- <el-table :data="scanRecords"
- border
- style="width: 100%">
- <el-table-column label="搴忓彿"
- type="index"
- width="60"
- align="center" />
- <el-table-column label="鎵爜鏃堕棿"
- prop="scanTime"
- width="180" />
- <el-table-column label="鎵爜浜�"
- prop="scannerName"
- width="120" />
- <el-table-column label="鎵爜鐘舵��"
- prop="scanStatus"
- width="100">
- <template #default="scope">
- <el-tag :type="scope.row.scanStatus === '宸叉壂鐮�' ? 'success' : 'warning'">
- {{ scope.row.scanStatus }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="澶囨敞"
- prop="scanRemark" />
- </el-table>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary"
- @click="submitScan">纭鎵爜</el-button>
- <el-button @click="closeScanDialog">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- <FileList ref="fileListRef" />
+ </FormDialog>
+ <FileListDialog
+ ref="fileListRef"
+ v-model="fileListDialogVisible"
+ title="闄勪欢鍒楄〃"
+ />
</div>
</template>
@@ -853,10 +667,11 @@
getCurrentInstance,
nextTick,
} from "vue";
- import { Search } from "@element-plus/icons-vue";
+ import { Search, Delete } from "@element-plus/icons-vue";
import { ElMessageBox, ElMessage } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
- import FileList from "./fileList.vue";
+ import FormDialog from '@/components/Dialog/FormDialog.vue';
+ import FileListDialog from '@/components/Dialog/FileListDialog.vue';
import {
getSalesLedgerWithProducts,
addOrUpdateSalesLedgerProduct,
@@ -867,6 +682,7 @@
import {
addOrEditPurchase,
addPurchaseTemplate,
+ updatePurchaseTemplate,
createPurchaseNo,
delPurchase,
getSalesNo,
@@ -875,9 +691,9 @@
getPurchaseById,
getOptions,
getPurchaseTemplateList,
+ delPurchaseTemplate,
} from "@/api/procurementManagement/procurementLedger.js";
import useFormData from "@/hooks/useFormData.js";
- import QRCode from "qrcode";
const { proxy } = getCurrentInstance();
const tableData = ref([]);
@@ -902,21 +718,41 @@
const userStore = useUserStore();
- // 浜岀淮鐮佺浉鍏冲彉閲�
- const qrCodeDialogVisible = ref(false);
- const qrCodeUrl = ref("");
+ // 瀹℃壒浜鸿妭鐐癸紙浠块攢鍞彴璐﹀彂璐у鎵逛汉锛�
+ const approverNodes = ref([{ id: 1, userId: null }]);
+ let nextApproverId = 2;
+ const addApproverNode = () => {
+ approverNodes.value.push({ id: nextApproverId++, userId: null });
+ };
+ const removeApproverNode = (index) => {
+ approverNodes.value.splice(index, 1);
+ };
// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
const approvalStatusText = {
- 0: "瀹℃壒涓�",
- 1: "瀹℃壒閫氳繃",
- 2: "瀹℃壒澶辫触",
+ 1: "寰呭鏍�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒閫氳繃",
+ 4: "瀹℃壒澶辫触",
+ };
+
+ // 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+ const getApprovalStatusType = (status) => {
+ const typeMap = {
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ };
+ return typeMap[status] || "";
};
const templateName = ref("");
const filterInputValue = ref("");
const templateList = ref([]);
const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
+ // 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
+ const currentTemplateId = ref(null);
// 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
const checkTemplateNameDuplicate = name => {
@@ -970,22 +806,28 @@
);
if (matchedTemplate?.id) {
- // 濡傛灉鎵惧埌妯℃澘锛屽姞杞芥ā鏉挎暟鎹�
- form.value = {
- ...form.value,
- ...matchedTemplate,
- };
- productData.value = matchedTemplate.productData || [];
- // 鐢熸垚鏂扮殑閲囪喘鍚堝悓鍙�
- try {
- const res = await createPurchaseNo();
- if (res?.data) {
- form.value.purchaseContractNumber = res.data;
- }
- } catch (error) {
- console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+ // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄D锛屽悗缁繚瀛樻椂杩涜鏇存柊鎿嶄綔
+ currentTemplateId.value = matchedTemplate.id;
+ // 閫変腑宸叉湁妯℃澘鏃讹紝涓嶅簲瑙嗕负鈥滄ā鏉垮悕绉伴噸澶嶅鑷翠笉鍙繚瀛樷��
+ isTemplateNameDuplicate.value = false;
+ // 濡傛灉鎵惧埌妯℃澘锛屽彧璧嬪�间緵搴斿晢銆侀」鐩悕绉般�佷粯娆炬柟寮忓拰浜у搧淇℃伅
+ if (matchedTemplate.supplierId) {
+ form.value.supplierId = matchedTemplate.supplierId;
}
+ if (matchedTemplate.supplierName) {
+ form.value.supplierName = matchedTemplate.supplierName;
+ }
+ if (matchedTemplate.projectName) {
+ form.value.projectName = matchedTemplate.projectName;
+ }
+ if (matchedTemplate.paymentMethod) {
+ form.value.paymentMethod = matchedTemplate.paymentMethod;
+ }
+ // 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
+ productData.value = matchedTemplate.productList || matchedTemplate.productData || [];
} else {
+ // 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
+ currentTemplateId.value = null;
// 濡傛灉娌℃湁鎵惧埌妯℃澘锛岄噸缃〃鍗曪紙淇濇寔褰撳墠琛ㄥ崟鐘舵�侊級
const currentFormData = { ...form.value };
const currentProductData = [...productData.value];
@@ -1140,14 +982,17 @@
return;
}
- // 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
- const isDuplicate = checkTemplateNameDuplicate(templateName.value);
- if (isDuplicate) {
- ElMessage({
- message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
- type: "warning",
- });
- return;
+ // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
+ // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
+ if (!currentTemplateId.value) {
+ const isDuplicate = checkTemplateNameDuplicate(templateName.value);
+ if (isDuplicate) {
+ ElMessage({
+ message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
+ type: "warning",
+ });
+ return;
+ }
}
// 妫�鏌ヤ緵搴斿晢鏄惁閫夋嫨
@@ -1160,29 +1005,47 @@
}
// 妫�鏌ユ槸鍚︽湁浜у搧鏁版嵁
- // if (!productData.value || productData.value.length === 0) {
- // ElMessage({
- // message: '璇峰厛娣诲姞浜у搧淇℃伅',
- // type: 'warning',
- // });
- // return;
- // }
+ if (!productData.value || productData.value.length === 0) {
+ ElMessage({
+ message: '璇峰厛娣诲姞浜у搧淇℃伅',
+ type: 'warning',
+ });
+ return;
+ }
try {
+ // 鑾峰彇瀹℃壒浜篒D瀛楃涓�
+ const approveUserIds = approverNodes.value
+ .filter(node => node.userId)
+ .map(node => node.userId)
+ .join(",");
+
let params = {
productData: proxy.HaveJson(productData.value),
supplierId: form.value.supplierId,
paymentMethod: form.value.paymentMethod,
recorderId: form.value.recorderId,
- approverId: form.value.approverId,
+ projectName: form.value.projectName,
+ approveUserIds: approveUserIds,
templateName: templateName.value.trim(),
};
- console.log(params);
- let res = await addPurchaseTemplate(params);
+ console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
+
+ // 濡傛灉 currentTemplateId 鏈夊�硷紝璇存槑褰撳墠鏄�滅紪杈戝凡鏈夋ā鏉库�� 鈫� 璋冪敤鏇存柊鎺ュ彛
+ // 鍚﹀垯涓衡�滄柊寤烘ā鏉库�� 鈫� 璋冪敤鏂板鎺ュ彛
+ let res;
+ if (currentTemplateId.value) {
+ res = await updatePurchaseTemplate({
+ id: currentTemplateId.value,
+ ...params,
+ });
+ } else {
+ res = await addPurchaseTemplate(params);
+ }
if (res && res.code === 200) {
ElMessage({
- message: "妯℃澘淇濆瓨鎴愬姛",
+ message: currentTemplateId.value ? "妯℃澘鏇存柊鎴愬姛" : "妯℃澘淇濆瓨鎴愬姛",
type: "success",
});
// 淇濆瓨鎴愬姛鍚庨噸鏂拌幏鍙栨ā鏉垮垪琛�
@@ -1191,6 +1054,8 @@
templateName.value = "";
filterInputValue.value = "";
isTemplateNameDuplicate.value = false;
+ // 淇濆瓨/鏇存柊瀹屾垚鍚庯紝閲嶇疆褰撳墠妯℃澘ID
+ currentTemplateId.value = null;
} else {
ElMessage({
message: res?.msg || "妯℃澘淇濆瓨澶辫触",
@@ -1238,7 +1103,6 @@
// tableData.value = res.data.records;
tableData.value = res.data.records.map(record => ({
...record,
- isInvalid: record.isWhite === 1,
}));
// 鍒濆鍖栧瓙鏁版嵁鏁扮粍
tableData.value.forEach(item => {
@@ -1297,6 +1161,14 @@
};
// 鎵撳紑寮规
const openForm = async (type, row) => {
+ // 缂栬緫鏃舵鏌ュ鏍哥姸鎬侊紝鍙湁寰呭鏍�(1)鍜屽鎵瑰け璐�(4)鎵嶈兘缂栬緫
+ if (type === "edit" && row) {
+ if (row.approvalStatus !== 1 && row.approvalStatus !== 4) {
+ proxy.$modal.msgWarning("鍙湁寰呭鏍稿拰瀹℃壒澶辫触鐘舵�佺殑璁板綍鎵嶈兘缂栬緫");
+ return;
+ }
+ }
+
await getTemplateList();
operationType.value = type;
form.value = {};
@@ -1305,6 +1177,9 @@
templateName.value = "";
filterInputValue.value = "";
isTemplateNameDuplicate.value = false;
+ // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
try {
// 骞惰鍔犺浇鍩虹鏁版嵁
const [userRes, salesRes, supplierRes] = await Promise.all([
@@ -1343,6 +1218,15 @@
form.value = { ...purchaseRes };
productData.value = purchaseRes.productData || [];
fileList.value = purchaseRes.salesLedgerFiles || [];
+ // 濡傛灉缂栬緫鏃舵湁瀹℃壒浜猴紝瑙f瀽瀹℃壒浜篒D瀛楃涓插苟璁剧疆鍒拌妭鐐逛腑
+ if (purchaseRes.approveUserIds) {
+ const approverIds = purchaseRes.approveUserIds.split(",");
+ approverNodes.value = approverIds.map((id, index) => ({
+ id: index + 1,
+ userId: Number(id)
+ }));
+ nextApproverId = approverIds.length + 1;
+ }
} catch (error) {
console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
@@ -1411,8 +1295,24 @@
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
if (valid) {
+ // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
+ const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
+ if (hasEmptyApprover) {
+ proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
+ return;
+ }
+ const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
+
if (productData.value.length > 0) {
- form.value.productData = proxy.HaveJson(productData.value);
+ // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
+ let processedProductData = productData.value;
+ if (operationType.value === "add") {
+ processedProductData = productData.value.map(product => {
+ const { id, ...rest } = product;
+ return rest;
+ });
+ }
+ form.value.productData = proxy.HaveJson(processedProductData);
} else {
proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
return;
@@ -1423,13 +1323,20 @@
}
form.value.tempFileIds = tempFileIds;
form.value.type = 2;
+ form.value.approveUserIds = approveUserIds;
// 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
if (!form.value.salesLedgerId) {
form.value.salesContractNo = "";
}
- addOrEditPurchase(form.value).then(res => {
+ // 鏂板鏃朵笉浼犻�抜d
+ const submitData = { ...form.value };
+ if (operationType.value === "add") {
+ delete submitData.id;
+ }
+
+ addOrEditPurchase(submitData).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
getList();
@@ -1440,35 +1347,102 @@
// 鍏抽棴寮规
const closeDia = () => {
proxy.resetForm("formRef");
+ // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
dialogFormVisible.value = false;
};
// 鎵撳紑浜у搧寮规
- const openProductForm = (type, row, index) => {
+ const openProductForm = async (type, row, index) => {
productOperationType.value = type;
productOperationIndex.value = index;
productForm.value = {};
proxy.resetForm("productFormRef");
- if (type === "edit") {
- productForm.value = { ...row };
- }
productFormVisible.value = true;
- getProductOptions();
+
+ // 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
+ await getProductOptions();
+
+ // 绛夊緟 DOM 鏇存柊
+ await nextTick();
+
+ if (type === "edit") {
+ // 澶嶅埗琛屾暟鎹�
+ productForm.value = { ...row };
+
+ // 濡傛灉鏄粠妯℃澘鍔犺浇鐨勬暟鎹紝鍙兘娌℃湁 productId 鍜� productModelId
+ // 闇�瑕佹牴鎹� productCategory 鍜� specificationModel 鏉ユ煡鎵惧搴旂殑 ID
+ if (!productForm.value.productId && productForm.value.productCategory) {
+ // 鏍规嵁 productCategory 鏌ユ壘 productId
+ const findProductIdByCategory = (nodes, categoryName) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].label === categoryName) {
+ return nodes[i].value;
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const found = findProductIdByCategory(nodes[i].children, categoryName);
+ if (found) return found;
+ }
+ }
+ return null;
+ };
+
+ const productId = findProductIdByCategory(productOptions.value, productForm.value.productCategory);
+ if (productId) {
+ productForm.value.productId = productId;
+ // 鑾峰彇鍨嬪彿鍒楄〃骞剁瓑寰呭畬鎴�
+ const modelRes = await modelList({ id: productId });
+ modelOptions.value = modelRes;
+
+ // 绛夊緟 DOM 鏇存柊
+ await nextTick();
+
+ // 鏍规嵁 specificationModel 鏌ユ壘 productModelId
+ if (productForm.value.specificationModel && modelOptions.value.length > 0) {
+ const modelItem = modelOptions.value.find(
+ item => item.model === productForm.value.specificationModel
+ );
+ if (modelItem) {
+ productForm.value.productModelId = modelItem.id;
+ // 璁剧疆瑙勬牸鍨嬪彿鍜屽崟浣�
+ getProductModel(modelItem.id);
+ }
+ }
+ }
+ } else if (productForm.value.productId) {
+ // 濡傛灉鏈� productId锛屾甯稿姞杞藉瀷鍙峰垪琛�
+ await getModels(productForm.value.productId);
+
+ // 绛夊緟 DOM 鏇存柊
+ await nextTick();
+
+ if (productForm.value.productModelId) {
+ getProductModel(productForm.value.productModelId);
+ }
+ }
+
+ // 鏈�鍚庡啀绛夊緟涓�娆� DOM 鏇存柊锛岀‘淇濇墍鏈夋暟鎹兘宸茶缃�
+ await nextTick();
+ }
};
const getProductOptions = () => {
- productTreeList().then(res => {
+ return productTreeList().then(res => {
productOptions.value = convertIdToValue(res);
+ return res;
});
};
const getModels = value => {
if (value) {
productForm.value.productCategory =
findNodeById(productOptions.value, value) || "";
- modelList({ id: value }).then(res => {
+ return modelList({ id: value }).then(res => {
modelOptions.value = res;
+ return res;
});
} else {
productForm.value.productCategory = "";
modelOptions.value = [];
+ return Promise.resolve([]);
}
};
const getProductModel = value => {
@@ -1773,205 +1747,11 @@
};
const fileListRef = ref(null);
+ const fileListDialogVisible = ref(false);
const downLoadFile = row => {
- fileListRef.value.open(row.salesLedgerFiles);
- };
-
- // 鏄剧ず浜岀淮鐮�
- const showQRCode = async row => {
- try {
- // 鏋勫缓浜岀淮鐮佸唴瀹癸紝鍙寘鍚噰璐悎鍚屽彿锛堢函鏂囨湰锛�
- const qrContent = row.purchaseContractNumber || "";
- // 妫�鏌ュ唴瀹规槸鍚︿负绌�
- if (!qrContent || qrContent.trim() === "") {
- proxy.$modal.msgWarning("璇ヨ娌℃湁閲囪喘鍚堝悓鍙凤紝鏃犳硶鐢熸垚浜岀淮鐮�");
- return;
- }
- qrCodeUrl.value = await QRCode.toDataURL(qrContent, {
- width: 200,
- margin: 2,
- color: {
- dark: "#000000",
- light: "#FFFFFF",
- },
- });
- qrCodeDialogVisible.value = true;
- } catch (error) {
- console.error("鐢熸垚浜岀淮鐮佸け璐�:", error);
- proxy.$modal.msgError("鐢熸垚浜岀淮鐮佸け璐ワ細" + error.message);
+ if (fileListRef.value) {
+ fileListRef.value.open(row.salesLedgerFiles);
}
- };
-
- // 涓嬭浇浜岀淮鐮�
- const downloadQRCode = () => {
- if (!qrCodeUrl.value) {
- proxy.$modal.msgWarning("浜岀淮鐮佹湭鐢熸垚");
- return;
- }
-
- const a = document.createElement("a");
- a.href = qrCodeUrl.value;
- a.download = `閲囪喘鍚堝悓鍙蜂簩缁寸爜_${new Date().getTime()}.png`;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- proxy.$modal.msgSuccess("涓嬭浇鎴愬姛");
- };
-
- // 鎵爜鏂板瀵硅瘽妗嗙浉鍏冲彉閲�
- const scanAddDialogVisible = ref(false);
- const scanAddForm = reactive({
- scanContent: "",
- purchaseContractNumber: "",
- supplierName: "",
- projectName: "",
- contractAmount: "",
- paymentMethod: "",
- recorderName: "",
- scanRemark: "",
- });
- const scanAddRules = {
- purchaseContractNumber: [
- { required: true, message: "璇疯緭鍏ラ噰璐悎鍚屽彿", trigger: "blur" },
- ],
- supplierName: [
- { required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" },
- ],
- projectName: [{ required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" }],
- };
-
- // 鎵爜鐧昏瀵硅瘽妗嗙浉鍏冲彉閲�
- const scanDialogVisible = ref(false);
- const scanForm = reactive({
- purchaseContractNumber: "",
- supplierName: "",
- projectName: "",
- scanTime: "",
- scannerName: "",
- scanStatus: "鏈壂鐮�",
- scanRemark: "",
- });
- const scanRules = {
- scanRemark: [{ required: true, message: "璇疯緭鍏ユ壂鐮佸娉�", trigger: "blur" }],
- };
- const scanRecords = ref([]);
-
- // 鎵撳紑鎵爜鏂板瀵硅瘽妗�
- const openScanAddDialog = () => {
- scanAddForm.scanContent = "";
- scanAddForm.purchaseContractNumber = "";
- scanAddForm.supplierName = "";
- scanAddForm.projectName = "";
- scanAddForm.contractAmount = "";
- scanAddForm.paymentMethod = "";
- scanAddForm.recorderName = userStore.nickName;
- scanAddForm.scanRemark = "";
- scanAddDialogVisible.value = true;
- };
-
- // 瑙f瀽鎵爜鍐呭锛堟ā鎷熻В鏋愪簩缁寸爜鏁版嵁锛�
- const parseScanContent = content => {
- if (!content) return;
-
- // 妯℃嫙瑙f瀽浜岀淮鐮佸唴瀹癸紝杩欓噷鍙互鏍规嵁瀹為檯闇�姹傝皟鏁磋В鏋愰�昏緫
- // 鍋囪鎵爜鍐呭鏍煎紡涓猴細鍚堝悓鍙穦渚涘簲鍟唡閲戦|浠樻鏂瑰紡
- const parts = content.split("|");
- if (parts.length >= 2) {
- scanAddForm.purchaseContractNumber = parts[0] || "";
- scanAddForm.supplierName = parts[1] || "";
- scanAddForm.contractAmount = parts[2] || "";
- scanAddForm.paymentMethod = parts[3] || "";
- scanAddForm.projectName = parts[4] || "";
- // scanAddForm.contractAmount = parts[3] || "";
- // scanAddForm.paymentMethod = parts[4] || "";
- }
- };
-
- // 鍏抽棴鎵爜鏂板瀵硅瘽妗�
- const closeScanAddDialog = () => {
- scanAddDialogVisible.value = false;
- proxy.resetForm("scanAddFormRef");
- };
-
- // 鎻愪氦鎵爜鏂板
- const submitScanAdd = () => {
- proxy.$refs["scanAddFormRef"].validate(valid => {
- if (valid) {
- // 鏋勫缓鏂板鏁版嵁
- const newData = {
- purchaseContractNumber: scanAddForm.purchaseContractNumber,
- supplierName: scanAddForm.supplierName,
- projectName: scanAddForm.projectName,
- contractAmount: scanAddForm.contractAmount,
- paymentMethod: scanAddForm.paymentMethod,
- recorderName: scanAddForm.recorderName,
- entryDate: getCurrentDate(),
- remark: scanAddForm.scanRemark,
- type: 2,
- };
-
- // 妯℃嫙鏂板鎴愬姛
- proxy.$modal.msgSuccess("鎵爜鏂板鎴愬姛锛�");
- closeScanAddDialog();
-
- // 鍙互閫夋嫨鏄惁鍒锋柊鍒楄〃
- // getList();
- }
- });
- };
-
- // 鎵撳紑鎵爜鐧昏瀵硅瘽妗�
- const openScanDialog = row => {
- scanForm.purchaseContractNumber = row.purchaseContractNumber;
- scanForm.supplierName = row.supplierName;
- scanForm.projectName = row.projectName;
- scanForm.scanTime = getCurrentDateTime();
- scanForm.scannerName = userStore.nickName;
- scanForm.scanStatus = "鏈壂鐮�";
- scanForm.scanRemark = "";
- scanRecords.value = [];
- scanDialogVisible.value = true;
- };
-
- // 鍏抽棴鎵爜鐧昏瀵硅瘽妗�
- const closeScanDialog = () => {
- scanDialogVisible.value = false;
- proxy.resetForm("scanFormRef");
- };
-
- // 鎻愪氦鎵爜鐧昏
- const submitScan = () => {
- proxy.$refs["scanFormRef"].validate(valid => {
- if (valid) {
- // 娣诲姞鎵爜璁板綍
- scanRecords.value.push({
- ...scanForm,
- id: Date.now(), // 妯℃嫙ID
- scanTime: getCurrentDateTime(),
- });
- scanForm.scanStatus = "宸叉壂鐮�";
- scanForm.scanRemark = scanForm.scanRemark || "鏃�";
- proxy.$modal.msgSuccess("鎵爜鐧昏鎴愬姛锛�");
- closeScanDialog();
- }
- });
- };
-
- // 鑾峰彇褰撳墠鏃ユ湡鏃堕棿
- function getCurrentDateTime() {
- const now = new Date();
- const year = now.getFullYear();
- const month = String(now.getMonth() + 1).padStart(2, "0");
- const day = String(now.getDate()).padStart(2, "0");
- const hours = String(now.getHours()).padStart(2, "0");
- const minutes = String(now.getMinutes()).padStart(2, "0");
- const seconds = String(now.getSeconds()).padStart(2, "0");
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
- }
-
- // 娣诲姞琛岀被鍚嶆柟娉�
- const tableRowClassName = ({ row }) => {
- return row.isInvalid ? "invalid-row" : "";
};
// 鑾峰彇妯℃澘淇℃伅
@@ -1979,6 +1759,54 @@
let res = await getPurchaseTemplateList();
if (res && res.code === 200 && Array.isArray(res.data)) {
templateList.value = res.data;
+ }
+ };
+
+ // 鍒犻櫎妯℃澘
+ const handleDeleteTemplate = async (item) => {
+ if (!item.id) {
+ proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
+ return;
+ }
+
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
+ "鍒犻櫎纭",
+ {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ );
+
+ const res = await delPurchaseTemplate([item.id]);
+ if (res && res.code === 200) {
+ ElMessage({
+ message: "鍒犻櫎鎴愬姛",
+ type: "success",
+ });
+ // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勬ā鏉匡紝娓呯┖閫夋嫨
+ if (templateName.value === item.templateName) {
+ templateName.value = "";
+ filterInputValue.value = "";
+ }
+ // 閲嶆柊鑾峰彇妯℃澘鍒楄〃
+ await getTemplateList();
+ } else {
+ ElMessage({
+ message: res?.msg || "鍒犻櫎澶辫触",
+ type: "error",
+ });
+ }
+ } catch (error) {
+ if (error !== "cancel") {
+ console.error("鍒犻櫎妯℃澘澶辫触:", error);
+ ElMessage({
+ message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
+ type: "error",
+ });
+ }
}
};
@@ -2004,4 +1832,64 @@
display: flex;
align-items: center;
}
+
+ // 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
+ .approver-nodes-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ padding: 16px;
+ background-color: #f8f9fa;
+ border-radius: 4px;
+ border: 1px solid #e4e7ed;
+ }
+
+ .approver-node-item {
+ flex: 0 0 calc(33.333% - 12px);
+ min-width: 200px;
+ padding: 12px;
+ background-color: #fff;
+ border-radius: 4px;
+ border: 1px solid #dcdfe6;
+ transition: all 0.3s;
+
+ &:hover {
+ border-color: #409eff;
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
+ }
+ }
+
+ .approver-node-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+ }
+
+ .approver-node-label {
+ font-size: 13px;
+ font-weight: 500;
+ color: #606266;
+ }
+
+ @media (max-width: 1200px) {
+ .approver-node-item {
+ flex: 0 0 calc(50% - 8px);
+ }
+ }
+
+ @media (max-width: 768px) {
+ .approver-node-item {
+ flex: 0 0 100%;
+ }
+ }
+
+ // 鍒犻櫎鍥炬爣鏍峰紡
+ .delete-icon {
+ transition: all 0.3s;
+ &:hover {
+ color: #f56c6c !important;
+ transform: scale(1.2);
+ }
+ }
</style>
diff --git a/src/views/procurementManagement/procurementReport/index.vue b/src/views/procurementManagement/procurementReport/index.vue
index 8c8f3f6..4c17e0c 100644
--- a/src/views/procurementManagement/procurementReport/index.vue
+++ b/src/views/procurementManagement/procurementReport/index.vue
@@ -103,12 +103,10 @@
{
label: '浜у搧澶х被',
prop: 'productCategory',
- width: 150,
},
{
label: '瑙勬牸鍨嬪彿',
prop: 'specificationModel',
- width: 180
},
{
label: '閲囪喘鏁伴噺',
@@ -121,7 +119,6 @@
{
label: '閲囪喘閲戦',
prop: 'purchaseAmount',
- width: 140,
formatData: (val) => {
return val ? `楼${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '楼0.00'
}
@@ -142,7 +139,6 @@
{
label: '渚涘簲鍟嗗悕绉�',
prop: 'supplierName',
- width: 200
},
{
label: '褰曞叆鏃ユ湡',
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index a07aa44..bef389b 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -53,13 +53,13 @@
<el-table-column label="浜у搧鐘舵��"
width="100px"
align="center">
- <template #default="scope">
+ <template #default="scope">
<el-tag v-if="scope.row.approveStatus === 1"
type="success">鍏呰冻</el-tag>
<el-tag v-else
type="danger">涓嶈冻</el-tag>
- </template>
- </el-table-column>
+ </template>
+ </el-table-column>
<el-table-column label="鍙戣揣鐘舵��" prop="shippingStatus" width="140" align="center" show-overflow-tooltip />
<el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
<el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
@@ -74,14 +74,14 @@
<el-table-column label="鍙戣揣鏃ユ湡"
minWidth="100px"
align="center">
- <template #default="scope">
- <div>
- <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
+ <template #default="scope">
+ <div>
+ <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
<el-tag v-else
type="info">-</el-tag>
- </div>
- </template>
- </el-table-column>
+ </div>
+ </template>
+ </el-table-column>
<el-table-column label="鏁伴噺" prop="quantity" />
<el-table-column label="绋庣巼(%)" prop="taxRate" />
<el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
--
Gitblit v1.9.3