From 90b6240233ef9a896a4075758eabb7342e2c49a0 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 21 四月 2026 09:00:56 +0800
Subject: [PATCH] 湟水峡 1.销售、采购模块不要客户合同号、项目名称 2.销售报价和销售台账价格导入按照客户类型赋值 3.人力资源字段增减 4.仓储物流四根模块tab标签页和查询条件修改 5.销售、采购模块字段增减
---
src/views/index.vue | 25
src/views/procurementManagement/procurementInvoiceLedger/index.vue | 18
src/views/basicData/supplierManage/index.vue | 684 ++++
src/views/equipmentManagement/upkeep/Form/PlanModal.vue | 14
src/api/procurementManagement/procurementLedger.js | 8
src/views/collaborativeApproval/approvalProcess/index.vue | 120
src/views/procurementManagement/paymentEntry/index.vue | 24
src/views/salesManagement/salesLedger/index.vue | 2400 +++++++--------
src/views/inventoryManagement/issueManagement/Record.vue | 570 +++
src/views/personnelManagement/contractManagement/index.vue | 24
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue | 97
src/views/inventoryManagement/dispatchLog/Record.vue | 36
src/views/salesManagement/invoiceLedger/index.vue | 18
src/views/basicData/customerFile/index.vue | 257 -
src/views/inventoryManagement/receiptManagement/index.vue | 55
src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue | 132
src/views/inventoryManagement/dispatchLog/index.vue | 64
src/views/inventoryManagement/receiptManagement/Record.vue | 37
src/views/basicData/supplierManage/components/HomeTab.vue | 135
src/views/equipmentManagement/upkeep/index.vue | 10
src/views/personnelManagement/employeeRecord/index.vue | 16
src/views/inventoryManagement/issueManagement/index.vue | 299 -
src/views/basicData/customerFileOpenSea/index.vue | 269 -
src/views/salesManagement/salesQuotation/index.vue | 468 --
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue | 82
src/views/basicData/supplierManage/filesDia.vue | 16
src/views/personnelManagement/dimission/components/formDia.vue | 19
src/views/procurementManagement/procurementLedger/index.vue | 3033 ++++++++-----------
src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue | 2
src/api/viewIndex.js | 17
src/views/equipmentManagement/upkeep/Form/formDia.vue | 20
src/views/basicData/supplierManage/components/BlacklistTab.vue | 135
src/views/personnelManagement/dimission/index.vue | 10
33 files changed, 4,428 insertions(+), 4,686 deletions(-)
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index 5f9df05..b3e6d02 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -122,4 +122,12 @@
method: "get",
params: id,
});
+}
+// 鏌ヨ閿�鍞鎯咃紙鐢ㄤ簬閿�鍞鎵癸級
+export function getSalesByCode(query) {
+ return request({
+ url: "/purchase/ledger/getSalesByCode",
+ method: "get",
+ params: query,
+ });
}
\ No newline at end of file
diff --git a/src/api/viewIndex.js b/src/api/viewIndex.js
index 8b5d144..fa91232 100644
--- a/src/api/viewIndex.js
+++ b/src/api/viewIndex.js
@@ -144,12 +144,19 @@
// 绾垮舰鍥�
export const getAmountHalfYear = () => {
- return request({
- url: "/sales/ledger/getAmountHalfYear",
- method: "get",
- });
-};
+ return request({
+ url: '/sales/ledger/getAmountHalfYear',
+ method: 'get'
+ })
+}
+// 棣栭〉-寰呭洖娆炬彁閱�
+export const overdueReceivable = () => {
+ return request({
+ url: '/home/overdueReceivable',
+ method: 'get'
+ })
+}
// 鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻
// /home/progressStatistics
export const getProgressStatistics = () => {
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index d0f829c..812dc5f 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -15,10 +15,10 @@
style="width: 240px"
clearable
@change="handleQuery">
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="涓�鎵瑰晢"
+ value="涓�鎵瑰晢" />
+ <el-option label="缁堢鍟�"
+ value="缁堢鍟�" />
</el-select>
<el-button type="primary"
@click="handleQuery"
@@ -66,16 +66,6 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNumber">
- <el-input v-model="form.taxpayerIdentificationNumber"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
<el-form-item label="鍏徃鍦板潃锛�"
prop="companyAddress">
<el-input v-model="form.companyAddress"
@@ -83,88 +73,22 @@
clearable />
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�"
- prop="companyPhone">
- <el-input v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="閾惰鍩烘湰鎴凤細"
- prop="basicBankAccount">
- <el-input v-model="form.basicBankAccount"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="閾惰璐﹀彿锛�"
- prop="bankAccount">
- <el-input v-model="form.bankAccount"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯鍙凤細"
- prop="bankCode">
- <el-input v-model="form.bankCode"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
<el-col :span="12">
<el-form-item label="瀹㈡埛鍒嗙被锛�"
prop="customerType">
<el-select v-model="form.customerType"
placeholder="璇烽�夋嫨"
clearable>
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="涓�鎵瑰晢"
+ value="涓�鎵瑰晢" />
+ <el-option label="缁堢鍟�"
+ value="缁堢鍟�" />
</el-select>
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30"
- v-for="(contact, index) in formYYs.contactList"
- :key="index">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細"
- prop="contactPerson">
- <el-input v-model="contact.contactPerson"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�"
- prop="contactPhone">
- <div style="display: flex; align-items: center;width: 100%;">
- <el-input v-model="contact.contactPhone"
- placeholder="璇疯緭鍏�"
- clearable />
- <el-button @click="removeContact(index)"
- type="danger"
- circle
- style="margin-left: 5px;">
- <el-icon>
- <Close />
- </el-icon>
- </el-button>
- </div>
- </el-form-item>
- </el-col>
- </el-row>
- <el-button @click="addNewContact"
- style="margin-bottom: 10px;">+ 鏂板鑱旂郴浜�</el-button>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="缁存姢浜猴細"
@@ -390,56 +314,8 @@
<el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
- <span class="info-label">绾崇◣浜鸿瘑鍒彿锛�</span>
- <span class="info-value">{{ detailForm.taxpayerIdentificationNumber }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鍏徃鐢佃瘽锛�</span>
- <span class="info-value">{{ detailForm.companyPhone }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
<span class="info-label">鍏徃鍦板潃锛�</span>
<span class="info-value">{{ detailForm.companyAddress }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">閾惰鍩烘湰鎴凤細</span>
- <span class="info-value">{{ detailForm.basicBankAccount }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">閾惰璐﹀彿锛�</span>
- <span class="info-value">{{ detailForm.bankAccount }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">寮�鎴疯鍙凤細</span>
- <span class="info-value">{{ detailForm.bankCode }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鑱旂郴浜猴細</span>
- <span class="info-value">{{ detailForm.contactPerson }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鑱旂郴鐢佃瘽锛�</span>
- <span class="info-value">{{ detailForm.contactPhone }}</span>
</div>
</el-col>
</el-row>
@@ -681,14 +557,7 @@
const detailForm = reactive({
customerName: "",
customerType: "",
- taxpayerIdentificationNumber: "",
- companyPhone: "",
companyAddress: "",
- basicBankAccount: "",
- bankAccount: "",
- bankCode: "",
- contactPerson: "",
- contactPhone: "",
maintainer: "",
maintenanceTime: "",
});
@@ -712,33 +581,26 @@
const tableColumn = ref([
{
- label: "瀹㈡埛鍒嗙被",
- prop: "customerType",
- width: 120,
- },
- {
label: "瀹㈡埛鍚嶇О",
prop: "customerName",
width: 220,
},
{
- label: "绾崇◣浜鸿瘑鍒爜",
- prop: "taxpayerIdentificationNumber",
- width: 220,
+ label: "瀹㈡埛鍒嗙被",
+ prop: "customerType",
+ dataType: "tag",
+ width: 120,
+ formatType: value => {
+ if (value === "涓�鎵瑰晢") {
+ return "primary";
+ }
+ return "success";
+ },
},
{
- label: "鍦板潃鍙婅仈绯绘柟寮�",
+ label: "鍏徃鍦板潃",
prop: "companyAddress",
width: 250,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactPerson",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactPhone",
- width: 150,
},
{
label: "璺熻繘杩涘害",
@@ -749,21 +611,6 @@
label: "璺熻繘鏃堕棿",
prop: "followUpTime",
width: 120,
- },
- {
- label: "閾惰鍩烘湰鎴�",
- prop: "basicBankAccount",
- width: 220,
- },
- {
- label: "閾惰璐﹀彿",
- prop: "bankAccount",
- width: 220,
- },
- {
- label: "寮�鎴疯鍙�",
- prop: "bankCode",
- width: 220,
},
{
label: "缁存姢浜�",
@@ -844,15 +691,6 @@
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const operationType = ref("");
const dialogFormVisible = ref(false);
- const formYYs = ref({
- // 鍏朵粬瀛楁...
- contactList: [
- {
- contactPerson: "",
- contactPhone: "",
- },
- ],
- });
const data = reactive({
searchForm: {
customerName: "",
@@ -860,34 +698,18 @@
},
form: {
customerName: "",
- taxpayerIdentificationNumber: "",
companyAddress: "",
- companyPhone: "",
- contactPerson: "",
- contactPhone: "",
maintainer: "",
maintenanceTime: "",
- basicBankAccount: "",
- bankAccount: "",
- bankCode: "",
customerType: "",
},
rules: {
customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- // contactPerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- // contactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
maintenanceTime: [
{ required: false, message: "璇烽�夋嫨", trigger: "change" },
],
- basicBankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
customerType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
@@ -947,18 +769,6 @@
},
});
const { searchForm, form, rules } = toRefs(data);
- const addNewContact = () => {
- formYYs.value.contactList.push({
- contactPerson: "",
- contactPhone: "",
- });
- };
-
- const removeContact = index => {
- if (formYYs.value.contactList.length > 1) {
- formYYs.value.contactList.splice(index, 1);
- }
- };
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
@@ -1001,12 +811,6 @@
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
- formYYs.value.contactList = [
- {
- contactPerson: "",
- contactPhone: "",
- },
- ];
form.value.maintenanceTime = getCurrentDate();
userListNoPage().then(res => {
userList.value = res.data;
@@ -1014,14 +818,6 @@
if (type === "edit") {
getCustomerPrivatePoolById(row.id).then(res => {
form.value = { ...res.data };
- formYYs.value.contactList = res.data.contactPerson
- .split(",")
- .map((item, index) => {
- return {
- contactPerson: item,
- contactPhone: res.data.contactPhone.split(",")[index],
- };
- });
});
}
dialogFormVisible.value = true;
@@ -1040,15 +836,6 @@
};
// 鎻愪氦鏂板
const submitAdd = () => {
- if (formYYs.value.contactList.length < 1) {
- return proxy.$modal.msgWarning("璇疯嚦灏戞坊鍔犱竴涓仈绯讳汉");
- }
- form.value.contactPerson = formYYs.value.contactList
- .map(item => item.contactPerson)
- .join(",");
- form.value.contactPhone = formYYs.value.contactList
- .map(item => item.contactPhone)
- .join(",");
addCustomerPrivate(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
@@ -1057,12 +844,6 @@
};
// 鎻愪氦淇敼
const submitEdit = () => {
- form.value.contactPerson = formYYs.value.contactList
- .map(item => item.contactPerson)
- .join(",");
- form.value.contactPhone = formYYs.value.contactList
- .map(item => item.contactPhone)
- .join(",");
updateCustomerPrivatePool(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
diff --git a/src/views/basicData/customerFileOpenSea/index.vue b/src/views/basicData/customerFileOpenSea/index.vue
index 71cc051..33b4cf1 100644
--- a/src/views/basicData/customerFileOpenSea/index.vue
+++ b/src/views/basicData/customerFileOpenSea/index.vue
@@ -15,10 +15,10 @@
style="width: 240px"
clearable
@change="handleQuery">
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="涓�鎵瑰晢"
+ value="涓�鎵瑰晢" />
+ <el-option label="缁堢鍟�"
+ value="缁堢鍟�" />
</el-select>
<el-button type="primary"
@click="handleQuery"
@@ -66,16 +66,6 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNumber">
- <el-input v-model="form.taxpayerIdentificationNumber"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
<el-form-item label="鍏徃鍦板潃锛�"
prop="companyAddress">
<el-input v-model="form.companyAddress"
@@ -83,88 +73,22 @@
clearable />
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�"
- prop="companyPhone">
- <el-input v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="閾惰鍩烘湰鎴凤細"
- prop="basicBankAccount">
- <el-input v-model="form.basicBankAccount"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="閾惰璐﹀彿锛�"
- prop="bankAccount">
- <el-input v-model="form.bankAccount"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯鍙凤細"
- prop="bankCode">
- <el-input v-model="form.bankCode"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
<el-col :span="12">
<el-form-item label="瀹㈡埛鍒嗙被锛�"
prop="customerType">
<el-select v-model="form.customerType"
placeholder="璇烽�夋嫨"
clearable>
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="涓�鎵瑰晢"
+ value="涓�鎵瑰晢" />
+ <el-option label="缁堢鍟�"
+ value="缁堢鍟�" />
</el-select>
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30"
- v-for="(contact, index) in formYYs.contactList"
- :key="index">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細"
- prop="contactPerson">
- <el-input v-model="contact.contactPerson"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�"
- prop="contactPhone">
- <div style="display: flex; align-items: center;width: 100%;">
- <el-input v-model="contact.contactPhone"
- placeholder="璇疯緭鍏�"
- clearable />
- <el-button @click="removeContact(index)"
- type="danger"
- circle
- style="margin-left: 5px;">
- <el-icon>
- <Close />
- </el-icon>
- </el-button>
- </div>
- </el-form-item>
- </el-col>
- </el-row>
- <el-button @click="addNewContact"
- style="margin-bottom: 10px;">+ 鏂板鑱旂郴浜�</el-button>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="缁存姢浜猴細"
@@ -459,56 +383,8 @@
<el-row :gutter="20">
<el-col :span="12">
<div class="info-item">
- <span class="info-label">绾崇◣浜鸿瘑鍒彿锛�</span>
- <span class="info-value">{{ detailForm.taxpayerIdentificationNumber }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鍏徃鐢佃瘽锛�</span>
- <span class="info-value">{{ detailForm.companyPhone }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
<span class="info-label">鍏徃鍦板潃锛�</span>
<span class="info-value">{{ detailForm.companyAddress }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">閾惰鍩烘湰鎴凤細</span>
- <span class="info-value">{{ detailForm.basicBankAccount }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">閾惰璐﹀彿锛�</span>
- <span class="info-value">{{ detailForm.bankAccount }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">寮�鎴疯鍙凤細</span>
- <span class="info-value">{{ detailForm.bankCode }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鑱旂郴浜猴細</span>
- <span class="info-value">{{ detailForm.contactPerson }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鑱旂郴鐢佃瘽锛�</span>
- <span class="info-value">{{ detailForm.contactPhone }}</span>
</div>
</el-col>
</el-row>
@@ -771,14 +647,7 @@
const detailForm = reactive({
customerName: "",
customerType: "",
- taxpayerIdentificationNumber: "",
- companyPhone: "",
companyAddress: "",
- basicBankAccount: "",
- bankAccount: "",
- bankCode: "",
- contactPerson: "",
- contactPhone: "",
maintainer: "",
maintenanceTime: "",
});
@@ -802,58 +671,26 @@
const tableColumn = ref([
{
- label: "瀹㈡埛鍒嗙被",
- prop: "customerType",
- width: 120,
- },
- {
label: "瀹㈡埛鍚嶇О",
prop: "customerName",
width: 220,
},
{
- label: "绾崇◣浜鸿瘑鍒爜",
- prop: "taxpayerIdentificationNumber",
- width: 220,
+ label: "瀹㈡埛鍒嗙被",
+ prop: "customerType",
+ dataType: "tag",
+ width: 120,
+ formatType: value => {
+ if (value === "涓�鎵瑰晢") {
+ return "primary";
+ }
+ return "success";
+ },
},
{
- label: "鍦板潃鍙婅仈绯绘柟寮�",
- prop: "addressPhone",
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
width: 250,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactPerson",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactPhone",
- width: 150,
- },
- // {
- // label: "璺熻繘杩涘害",
- // prop: "followUpLevel",
- // width: 120,
- // },
- // {
- // label: "璺熻繘鏃堕棿",
- // prop: "followUpTime",
- // width: 120,
- // },
- {
- label: "閾惰鍩烘湰鎴�",
- prop: "basicBankAccount",
- width: 220,
- },
- {
- label: "閾惰璐﹀彿",
- prop: "bankAccount",
- width: 220,
- },
- {
- label: "寮�鎴疯鍙�",
- prop: "bankCode",
- width: 220,
},
{
label: "缁存姢浜�",
@@ -957,15 +794,6 @@
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const operationType = ref("");
const dialogFormVisible = ref(false);
- const formYYs = ref({
- // 鍏朵粬瀛楁...
- contactList: [
- {
- contactPerson: "",
- contactPhone: "",
- },
- ],
- });
const data = reactive({
searchForm: {
customerName: "",
@@ -973,34 +801,18 @@
},
form: {
customerName: "",
- taxpayerIdentificationNumber: "",
companyAddress: "",
- companyPhone: "",
- contactPerson: "",
- contactPhone: "",
maintainer: "",
maintenanceTime: "",
- basicBankAccount: "",
- bankAccount: "",
- bankCode: "",
customerType: "",
},
rules: {
customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- // contactPerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- // contactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
maintenanceTime: [
{ required: false, message: "璇烽�夋嫨", trigger: "change" },
],
- basicBankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
customerType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
@@ -1060,18 +872,6 @@
},
});
const { searchForm, form, rules } = toRefs(data);
- const addNewContact = () => {
- formYYs.value.contactList.push({
- contactPerson: "",
- contactPhone: "",
- });
- };
-
- const removeContact = index => {
- if (formYYs.value.contactList.length > 1) {
- formYYs.value.contactList.splice(index, 1);
- }
- };
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
@@ -1115,12 +915,6 @@
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
- formYYs.value.contactList = [
- {
- contactPerson: "",
- contactPhone: "",
- },
- ];
form.value.maintenanceTime = getCurrentDate();
userListNoPage().then(res => {
userList.value = res.data;
@@ -1128,14 +922,6 @@
if (type === "edit") {
getCustomer(row.id).then(res => {
form.value = { ...res.data };
- formYYs.value.contactList = res.data.contactPerson
- .split(",")
- .map((item, index) => {
- return {
- contactPerson: item,
- contactPhone: res.data.contactPhone.split(",")[index],
- };
- });
});
}
dialogFormVisible.value = true;
@@ -1154,15 +940,6 @@
};
// 鎻愪氦鏂板
const submitAdd = () => {
- if (formYYs.value.contactList.length < 1) {
- return proxy.$modal.msgWarning("璇疯嚦灏戞坊鍔犱竴涓仈绯讳汉");
- }
- form.value.contactPerson = formYYs.value.contactList
- .map(item => item.contactPerson)
- .join(",");
- form.value.contactPhone = formYYs.value.contactList
- .map(item => item.contactPhone)
- .join(",");
addCustomer(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
@@ -1171,12 +948,6 @@
};
// 鎻愪氦淇敼
const submitEdit = () => {
- form.value.contactPerson = formYYs.value.contactList
- .map(item => item.contactPerson)
- .join(",");
- form.value.contactPhone = formYYs.value.contactList
- .map(item => item.contactPhone)
- .join(",");
updateCustomer(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
diff --git a/src/views/basicData/supplierManage/components/BlacklistTab.vue b/src/views/basicData/supplierManage/components/BlacklistTab.vue
index 8f6204b..39c5c43 100644
--- a/src/views/basicData/supplierManage/components/BlacklistTab.vue
+++ b/src/views/basicData/supplierManage/components/BlacklistTab.vue
@@ -56,72 +56,9 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item
- label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNum"
- >
- <el-input
- v-model="form.taxpayerIdentificationNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
<el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
<el-input
v-model="form.companyAddress"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
- <el-input
- v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯锛�" prop="bankAccountName">
- <el-input
- v-model="form.bankAccountName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璐﹀彿锛�" prop="bankAccountNum">
- <el-input
- v-model="form.bankAccountNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細" prop="contactUserName">
- <el-input
- v-model="form.contactUserName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactUserPhone">
- <el-input
- v-model="form.contactUserPhone"
placeholder="璇疯緭鍏�"
clearable
/>
@@ -157,26 +94,6 @@
placeholder="璇烽�夋嫨"
clearable
/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟嗙被鍨嬶細" prop="supplierType">
- <el-select v-model="form.supplierType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鐢�" value="鐢�" />
- <el-option label="涔�" value="涔�" />
- <el-option label="涓�" value="涓�" />
- <el-option label="涓�" value="涓�" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏄惁鐧藉悕鍗曪細" prop="isWhite">
- <el-select v-model="form.isWhite" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鏄�" :value="0" />
- <el-option label="鍚�" :value="1" />
- </el-select>
</el-form-item>
</el-col>
</el-row>
@@ -260,49 +177,14 @@
width: 250,
},
{
- label: "渚涘簲鍟嗙被鍨�",
- prop: "supplierType",
- width: 120,
- },
- {
- label: "绾崇◣浜鸿瘑鍒彿",
- prop: "taxpayerIdentificationNum",
- width: 230,
- },
- {
label: "鍏徃鍦板潃",
prop: "companyAddress",
width: 220,
},
{
- label: "鑱旂郴鏂瑰紡",
- prop: "companyPhone",
- width:150
- },
- {
- label: "寮�鎴疯",
- prop: "bankAccountName",
- width: 220,
- },
- {
- label: "璐﹀彿",
- prop: "bankAccountNum",
- width: 220,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactUserName",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactUserPhone",
- width: 150,
- },
- {
label: "缁存姢浜�",
prop: "maintainUserName",
},
-
{
label: "缁存姢鏃堕棿",
prop: "maintainTime",
@@ -352,32 +234,15 @@
},
form: {
supplierName: "",
- taxpayerIdentificationNum: "",
companyAddress: "",
- companyPhone: "",
- bankAccountName: "",
- bankAccountNum: "",
- contactUserName: "",
- contactUserPhone: "",
maintainUserId: "",
maintainTime: "",
- supplierType: "",
- isWhite: "",
},
rules: {
supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNum: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- supplierType: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" }],
},
});
const { searchForm, form, rules } = toRefs(data);
diff --git a/src/views/basicData/supplierManage/components/HomeTab.vue b/src/views/basicData/supplierManage/components/HomeTab.vue
index 85c3265..4947a4f 100644
--- a/src/views/basicData/supplierManage/components/HomeTab.vue
+++ b/src/views/basicData/supplierManage/components/HomeTab.vue
@@ -62,72 +62,9 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item
- label="绾崇◣浜鸿瘑鍒彿锛�"
- prop="taxpayerIdentificationNum"
- >
- <el-input
- v-model="form.taxpayerIdentificationNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
<el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
<el-input
v-model="form.companyAddress"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
- <el-input
- v-model="form.companyPhone"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="寮�鎴疯锛�" prop="bankAccountName">
- <el-input
- v-model="form.bankAccountName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璐﹀彿锛�" prop="bankAccountNum">
- <el-input
- v-model="form.bankAccountNum"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細" prop="contactUserName">
- <el-input
- v-model="form.contactUserName"
- placeholder="璇疯緭鍏�"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactUserPhone">
- <el-input
- v-model="form.contactUserPhone"
placeholder="璇疯緭鍏�"
clearable
/>
@@ -163,26 +100,6 @@
placeholder="璇烽�夋嫨"
clearable
/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="渚涘簲鍟嗙被鍨嬶細" prop="supplierType">
- <el-select v-model="form.supplierType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鐢�" value="鐢�" />
- <el-option label="涔�" value="涔�" />
- <el-option label="涓�" value="涓�" />
- <el-option label="涓�" value="涓�" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏄惁鐧藉悕鍗曪細" prop="isWhite">
- <el-select v-model="form.isWhite" placeholder="璇烽�夋嫨" clearable>
- <el-option label="鏄�" :value="0" />
- <el-option label="鍚�" :value="1" />
- </el-select>
</el-form-item>
</el-col>
</el-row>
@@ -266,49 +183,14 @@
width: 250,
},
{
- label: "渚涘簲鍟嗙被鍨�",
- prop: "supplierType",
- width: 120,
- },
- {
- label: "绾崇◣浜鸿瘑鍒彿",
- prop: "taxpayerIdentificationNum",
- width: 230,
- },
- {
label: "鍏徃鍦板潃",
prop: "companyAddress",
width: 220,
},
{
- label: "鑱旂郴鏂瑰紡",
- prop: "companyPhone",
- width:150
- },
- {
- label: "寮�鎴疯",
- prop: "bankAccountName",
- width: 220,
- },
- {
- label: "璐﹀彿",
- prop: "bankAccountNum",
- width: 220,
- },
- {
- label: "鑱旂郴浜�",
- prop: "contactUserName",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "contactUserPhone",
- width: 150,
- },
- {
label: "缁存姢浜�",
prop: "maintainUserName",
},
-
{
label: "缁存姢鏃堕棿",
prop: "maintainTime",
@@ -358,32 +240,15 @@
},
form: {
supplierName: "",
- taxpayerIdentificationNum: "",
companyAddress: "",
- companyPhone: "",
- bankAccountName: "",
- bankAccountNum: "",
- contactUserName: "",
- contactUserPhone: "",
maintainUserId: "",
maintainTime: "",
- supplierType: "",
- isWhite: "",
},
rules: {
supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNum: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
- supplierType: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟嗙被鍨�", trigger: "change" }],
},
});
const { searchForm, form, rules } = toRefs(data);
diff --git a/src/views/basicData/supplierManage/filesDia.vue b/src/views/basicData/supplierManage/filesDia.vue
index 7943185..4fc3ce3 100644
--- a/src/views/basicData/supplierManage/filesDia.vue
+++ b/src/views/basicData/supplierManage/filesDia.vue
@@ -30,20 +30,10 @@
:isSelection="true"
@selection-change="handleSelectionChange"
height="500"
- @pagination-change="paginationSearch"
- :total="total"
- :page="page.current"
- :limit="page.size"
+ @pagination="paginationSearch"
+ :page="{ ...page, total }"
>
</PIMTable>
- <pagination
- style="margin: 10px 0"
- v-show="total > 0"
- @pagination="paginationSearch"
- :total="total"
- :page="page.current"
- :limit="page.size"
- />
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDia">鍙栨秷</el-button>
@@ -200,4 +190,4 @@
<style scoped>
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/basicData/supplierManage/index.vue b/src/views/basicData/supplierManage/index.vue
index d87a45b..6f02c5b 100644
--- a/src/views/basicData/supplierManage/index.vue
+++ b/src/views/basicData/supplierManage/index.vue
@@ -1,43 +1,663 @@
-<!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
<template>
<div class="app-container">
- <el-tabs v-model="activeTab" @tab-change="handleTabChange">
- <el-tab-pane label="姝e父渚涘簲鍟�" name="home">
- <HomeTab ref="homeTab" />
- </el-tab-pane>
- <el-tab-pane label="榛戝悕鍗�" name="blacklist">
- <BlacklistTab ref="blacklistTab" />
- </el-tab-pane>
- </el-tabs>
+ <div class="search_form">
+ <div>
+ <span class="search_title">渚涘簲鍟嗘。妗堬細</span>
+ <el-input
+ v-model="searchForm.supplierName"
+ style="width: 240px"
+ placeholder="杈撳叆渚涘簲鍟嗗悕绉版悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')"
+ >鏂板渚涘簲鍟�</el-button
+ >
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="info" plain icon="Upload" @click="handleImport"
+ >瀵煎叆</el-button
+ >
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板渚涘簲鍟嗕俊鎭�' : '缂栬緫渚涘簲鍟嗕俊鎭�'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierName">
+ <el-input
+ v-model="form.supplierName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
+ <el-input
+ v-model="form.companyAddress"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainUserId">
+ <el-select
+ filterable
+ v-model="form.maintainUserId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintainTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintainTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="浜у搧澶х被锛�" prop="productId">
+ <el-tree-select
+ v-model="form.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ @change="getModels"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select
+ v-model="form.productModelId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ @change="getProductModel"
+ >
+ <el-option
+ v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </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
+ :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body
+ >
+ <el-upload
+ ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :on-error="handleFileError"
+ :auto-upload="false"
+ drag
+ >
+ <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+ <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+ <template #tip>
+ <div class="el-upload__tip text-center">
+ <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+ <el-link
+ type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline"
+ @click="importTemplate"
+ >涓嬭浇妯℃澘</el-link
+ >
+ </div>
+ </template>
+ </el-upload>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button @click="upload.open = false">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <el-dialog
+ v-model="historyDialogVisible"
+ :title="`${currentHistorySupplierName || ''}鍚堜綔鍘嗗彶`"
+ width="80%"
+ >
+ <el-table
+ :data="historyTableData"
+ border
+ v-loading="historyTableLoading"
+ style="width: 100%"
+ max-height="500"
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber" min-width="180" show-overflow-tooltip />
+ <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" min-width="180" show-overflow-tooltip />
+ <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" min-width="160" show-overflow-tooltip />
+ <el-table-column label="浠樻鏂瑰紡" prop="paymentMethod" min-width="120" show-overflow-tooltip />
+ <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" min-width="140" show-overflow-tooltip />
+ <el-table-column label="褰曞叆浜�" prop="recorderName" min-width="100" show-overflow-tooltip />
+ <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" min-width="120" show-overflow-tooltip />
+ </el-table>
+ <pagination
+ v-show="historyPage.total > 0"
+ :total="historyPage.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="historyPage.current"
+ :limit="historyPage.size"
+ @pagination="historyPagination"
+ />
+ </el-dialog>
+ <files-dia ref="filesDia"></files-dia>
</div>
</template>
-<script>
-import HomeTab from './components/HomeTab.vue'
-import BlacklistTab from './components/BlacklistTab.vue'
+<script setup>
+import { onMounted, ref } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import Pagination from "@/components/PIMTable/Pagination.vue";
+import { delSupplier } from "@/api/basicData/supplierManageFile.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
+import { productTreeList, modelList } from "@/api/basicData/product.js";
+import {
+ addSupplier,
+ getSupplier,
+ listSupplier,
+ updateSupplier,
+} from "@/api/basicData/supplierManageFile.js";
+import useUserStore from "@/store/modules/user";
+import { getToken } from "@/utils/auth.js";
+import FilesDia from "./filesDia.vue";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
-export default {
- name: 'MainPage',
- components: {
- HomeTab,
- BlacklistTab
+const tableColumn = ref([
+ {
+ label: "渚涘簲鍟嗗悕绉�",
+ prop: "supplierName",
},
- data() {
- return {
- activeTab: 'home'
- }
+ {
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
},
- methods: {
- handleTabChange(tabName) {
- this.activeTab = tabName
- this.$nextTick(() => {
- if (tabName === 'home') {
- this.$refs.homeTab && this.$refs.homeTab.getList && this.$refs.homeTab.getList()
- } else if (tabName === 'blacklist') {
- this.$refs.blacklistTab && this.$refs.blacklistTab.getList && this.$refs.blacklistTab.getList()
+ {
+ label: "缁存姢浜�",
+ prop: "maintainUserName",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintainTime",
+ width:160
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width:230,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
}
- })
- },
- }
+ },
+ {
+ name: "鍚堜綔鍘嗗彶",
+ type: "text",
+ clickFun: (row) => {
+ openHistoryDialog(row);
+ }
+ },
+ {
+ //璧勮川闄勪欢
+ name: "璧勮川鏂囦欢",
+ type: "text",
+ clickFun: (row) => {
+ openFilesFormDia(row)
+ }
+ }
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const productOptions = ref([]);
+const modelOptions = ref([]);
+const historyDialogVisible = ref(false);
+const historyTableData = ref([]);
+const historyTableLoading = ref(false);
+const currentHistorySupplierName = ref("");
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const historyPage = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ supplierName: "",
+ },
+ form: {
+ supplierName: "",
+ companyAddress: "",
+ maintainUserId: "",
+ maintainTime: "",
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+const filesDia = ref()
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+/** 鎻愪氦涓婁紶鏂囦欢 */
+function submitFileForm() {
+ upload.isUploading = true;
+ proxy.$refs["uploadRef"].submit();
}
+const getList = () => {
+ tableLoading.value = true;
+ listSupplier({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog(row)
+ })
+};
+const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙渚涘簲鍟嗗鍏ワ級
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙渚涘簲鍟嗗鍏ワ級
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
+});
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+function handleImport() {
+ upload.title = "渚涘簲鍟嗗鍏�";
+ upload.open = true;
+}
+/** 涓嬭浇妯℃澘 */
+function importTemplate() {
+ proxy.download("/system/supplier/downloadTemplate", {}, "渚涘簲鍟嗗鍏ユā鏉�.xlsx");
+}
+
+/**鏂囦欢涓婁紶涓鐞� */
+const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+};
+
+/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+const handleFileSuccess = (response, file, fileList) => {
+ upload.isUploading = false;
+ if(response.code === 200){
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ upload.open = false;
+ proxy.$refs["uploadRef"].clearFiles();
+ getList();
+ }else if(response.code === 500){
+ proxy.$modal.msgError(response.msg);
+ }else{
+ proxy.$modal.msgWarning(response.msg);
+ }
+};
+
+/** 鏂囦欢涓婁紶澶辫触澶勭悊 */
+const handleFileError = (error, file, fileList) => {
+ upload.isUploading = false;
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const getProductTreeData = () => {
+ return productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value;
+ });
+};
+const getModels = (value) => {
+ form.value.productId = value;
+ form.value.productModelId = "";
+ form.value.specificationModel = "";
+ form.value.productCategory = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ });
+};
+const getProductModel = (value) => {
+ const index = modelOptions.value.findIndex((item) => item.id === value);
+ if (index !== -1) {
+ form.value.specificationModel = modelOptions.value[index].model;
+ } else {
+ form.value.specificationModel = "";
+ }
+};
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label;
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode;
+ }
+ }
+ }
+ return "";
+};
+const findNodeIdByLabel = (nodes, label) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].label === label) {
+ return nodes[i].id;
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const found = findNodeIdByLabel(nodes[i].children, label);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return "";
+};
+const convertIdToValue = (data) => {
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id,
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+ return newItem;
+ });
+};
+const getHistoryList = () => {
+ if (!currentHistorySupplierName.value) {
+ historyTableData.value = [];
+ historyPage.total = 0;
+ return;
+ }
+ historyTableLoading.value = true;
+ purchaseListPage({
+ supplierName: currentHistorySupplierName.value,
+ current: historyPage.current,
+ size: historyPage.size,
+ })
+ .then((res) => {
+ historyTableData.value = res.data.records || [];
+ historyPage.total = res.data.total || 0;
+ })
+ .finally(() => {
+ historyTableLoading.value = false;
+ });
+};
+const openHistoryDialog = (row) => {
+ currentHistorySupplierName.value = row.supplierName || "";
+ historyPage.current = 1;
+ historyDialogVisible.value = true;
+ getHistoryList();
+};
+const historyPagination = (obj) => {
+ historyPage.current = obj.page;
+ historyPage.size = obj.limit;
+ getHistoryList();
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ modelOptions.value = [];
+ form.value.maintainUserId = userStore.id;
+ form.value.maintainTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getProductTreeData().then(() => {
+ getSupplier(row.id).then(async (res) => {
+ form.value = { ...res.data };
+ try {
+ const productId = form.value.producutId || form.value.productId;
+ if (productId) {
+ form.value.productId = productId;
+ form.value.productCategory = findNodeById(productOptions.value, productId);
+ const models = await modelList({ id: productId });
+ modelOptions.value = models || [];
+ const currentModel = (modelOptions.value || []).find((m) => `${m.id}` === `${form.value.supplyProduct}`);
+ if (currentModel) {
+ form.value.productModelId = currentModel.id;
+ form.value.specificationModel = currentModel.model;
+ }
+ }
+ } catch (e) {
+ console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+ }
+ });
+ });
+ } else {
+ getProductTreeData();
+ }
+ dialogFormVisible.value = true;
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ addSupplier({
+ ...form.value,
+ supplyProduct: form.value.productModelId,
+ }).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鎻愪氦淇敼
+const submitEdit = () => {
+ updateSupplier({
+ ...form.value,
+ supplyProduct: form.value.productModelId,
+ }).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/system/supplier/export", {}, "渚涘簲鍟嗘。妗�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delSupplier(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 20a4ee6..4133c2a 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -2,7 +2,7 @@
<div>
<el-dialog
v-model="dialogFormVisible"
- :title="operationType === 'approval' ? '瀹℃壒' : '璇︽儏'"
+ :title="operationType === 'add' ? '鏂板瀹℃壒娴佺▼' : '缂栬緫瀹℃壒娴佺▼'"
width="700px"
@close="closeDia"
>
@@ -16,7 +16,7 @@
</el-row>
<el-row>
<el-col :span="24">
- <el-form-item label="鐢宠閮ㄩ棬锛�">
+ <el-form-item label="鐢宠閮ㄩ棬锛�" prop="approveDeptId">
<el-select
disabled
v-model="form.approveDeptId"
@@ -29,6 +29,14 @@
:value="user.deptId"
/>
</el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <!-- 瀹℃壒鏍囬锛堜粎鑷敱鍗忓悓瀹℃壒鏄剧ず锛� -->
+ <el-row v-if="isFreeApproval">
+ <el-col :span="24">
+ <el-form-item label="瀹℃壒鏍囬锛�" prop="approveTitle">
+ <el-input v-model="form.approveTitle" placeholder="璇疯緭鍏�" clearable disabled/>
</el-form-item>
</el-col>
</el-row>
@@ -168,6 +176,53 @@
</el-skeleton>
</div>
+ <!-- 閿�鍞鎵癸細灞曠ず閿�鍞鎯� -->
+ <div v-if="isSalesApproval" style="margin: 10px 0 18px;">
+ <el-divider content-position="left">閿�鍞鎯�</el-divider>
+ <el-skeleton :loading="salesLoading" animated>
+ <template #template>
+ <el-skeleton-item variant="h3" style="width: 30%" />
+ <el-skeleton-item variant="text" style="width: 100%" />
+ <el-skeleton-item variant="text" style="width: 100%" />
+ </template>
+ <template #default>
+ <el-empty v-if="!currentSales || !currentSales.salesContractNo" description="鏈煡璇㈠埌瀵瑰簲閿�鍞鎯�" />
+ <template v-else>
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="閿�鍞悎鍚屽彿">{{ currentSales.salesContractNo }}</el-descriptions-item>
+ <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ currentSales.customerName }}</el-descriptions-item>
+ <el-descriptions-item label="涓氬姟鍛�">{{ currentSales.salesman }}</el-descriptions-item>
+ <el-descriptions-item label="褰曞叆浜�">{{ currentSales.entryPersonName }}</el-descriptions-item>
+ <el-descriptions-item label="绛捐鏃ユ湡">{{ currentSales.executionDate }}</el-descriptions-item>
+ <el-descriptions-item label="褰曞叆鏃ユ湡">{{ currentSales.entryDate }}</el-descriptions-item>
+ <el-descriptions-item label="浠樻鏂瑰紡">{{ currentSales.paymentMethod }}</el-descriptions-item>
+ <el-descriptions-item label="鍚堝悓閲戦" :span="2">
+ <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
+ 楼{{ calculateSalesTotalAmount() }}
+ </span>
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <div style="margin-top: 20px;">
+ <h4>浜у搧鏄庣粏</h4>
+ <el-table :data="currentSales.productData || []" border style="width: 100%">
+ <el-table-column prop="productCategory" label="浜у搧鍚嶇О" />
+ <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" />
+ <el-table-column prop="unit" label="鍗曚綅" />
+ <el-table-column prop="quantity" label="鏁伴噺" />
+ <el-table-column prop="taxInclusiveUnitPrice" label="鍚◣鍗曚环">
+ <template #default="scope">楼{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
+ </el-table-column>
+ <el-table-column prop="taxInclusiveTotalPrice" label="鍚◣鎬讳环">
+ <template #default="scope">楼{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </template>
+ </template>
+ </el-skeleton>
+ </div>
+
<el-form :model="{ activities }" ref="formRef" label-position="top">
<el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
<el-step
@@ -231,7 +286,7 @@
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
-import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
+import { getPurchaseByCode, getSalesByCode } from "@/api/procurementManagement/procurementLedger.js";
const emit = defineEmits(['close'])
const { proxy } = getCurrentInstance()
@@ -253,8 +308,12 @@
const currentQuotation = ref({})
const purchaseLoading = ref(false)
const currentPurchase = ref({})
+const salesLoading = ref(false)
+const currentSales = ref({})
const isQuotationApproval = computed(() => Number(props.approveType) === 6)
const isPurchaseApproval = computed(() => Number(props.approveType) === 5)
+const isSalesApproval = computed(() => Number(props.approveType) === 9)
+const isFreeApproval = computed(() => Number(props.approveType) === 10)
const data = reactive({
form: {
@@ -309,8 +368,8 @@
getProductOptions().then(() => {
// 纭繚鍊肩被鍨嬪尮閰嶏紙濡傛灉閫夐」宸插姞杞斤級
if (productOptions.value.length > 0 && form.value.approveDeptId) {
- const matchedOption = productOptions.value.find(opt =>
- opt.deptId == form.value.approveDeptId ||
+ const matchedOption = productOptions.value.find(opt =>
+ opt.deptId == form.value.approveDeptId ||
String(opt.deptId) === String(form.value.approveDeptId)
);
if (matchedOption) {
@@ -351,6 +410,22 @@
proxy.$modal.msgError('鏌ヨ閲囪喘璇︽儏澶辫触')
}).finally(() => {
purchaseLoading.value = false
+ })
+ }
+ }
+
+ // 閿�鍞鎵癸細鐢ㄥ鎵逛簨鐢卞瓧娈垫壙杞界殑"閿�鍞悎鍚屽彿"鍘绘煡閿�鍞鎯�
+ if (isSalesApproval.value) {
+ const salesContractNo = row?.approveReason;
+ if (salesContractNo) {
+ salesLoading.value = true
+ getSalesByCode({ salesContractNo }).then((res) => {
+ currentSales.value = res
+ }).catch((err) => {
+ console.error('鏌ヨ閿�鍞鎯呭け璐�:', err)
+ proxy.$modal.msgError('鏌ヨ閿�鍞鎯呭け璐�')
+ }).finally(() => {
+ salesLoading.value = false
})
}
}
@@ -407,8 +482,20 @@
currentQuotation.value = {}
purchaseLoading.value = false
currentPurchase.value = {}
+ salesLoading.value = false
+ currentSales.value = {}
emit('close')
};
+
+// 璁$畻閿�鍞悎鍚岄噾棰濓紙浜у搧鏄庣粏鍚◣鎬讳环涔嬪拰锛�
+const calculateSalesTotalAmount = () => {
+ const products = currentSales.value?.productData || []
+ const total = products.reduce((sum, item) => {
+ return sum + Number(item.taxInclusiveTotalPrice || 0)
+ }, 0)
+ return total.toFixed(2)
+}
+
defineExpose({
openDialog,
});
diff --git a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
index 998fa33..92737fc 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -19,9 +19,12 @@
<el-form-item label="鐢宠閮ㄩ棬锛�" prop="approveDeptName">
<!-- <el-input v-model="form.approveDeptName" placeholder="璇疯緭鍏�" clearable/>-->
<el-select
- v-model="form.approveDeptId"
+ v-model="form.approveDeptIdArray"
placeholder="閫夋嫨閮ㄩ棬"
+ multiple
+ collapse-tags
@change="handleDeptChange"
+ style="width: 100%"
>
<el-option
v-for="user in productOptions"
@@ -33,9 +36,17 @@
</el-form-item>
</el-col>
</el-row>
+ <!-- 瀹℃壒鏍囬锛堜粎褰� approveType 涓� 9 鏃舵樉绀猴級 -->
+ <el-row v-if="props.approveType == 9">
+ <el-col :span="24">
+ <el-form-item label="瀹℃壒鏍囬锛�" prop="approveTitle">
+ <el-input v-model="form.approveTitle" placeholder="璇疯緭鍏ュ鎵规爣棰�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-row>
<el-col :span="24">
- <el-form-item :label="props.approveType == 5 ? '閲囪喘鍚堝悓鍙凤細' : '瀹℃壒浜嬬敱锛�'" prop="approveReason">
+ <el-form-item :label="getApproveReasonLabel()" prop="approveReason">
<el-input v-model="form.approveReason" placeholder="璇疯緭鍏�" clearable type="textarea" />
</el-form-item>
</el-col>
@@ -234,8 +245,9 @@
approveTime: "",
approveId: "",
approveUser: "",
- approveDeptId: "",
+ approveDeptIdArray: [],
approveDeptName: "",
+ approveTitle: "", // 瀹℃壒鏍囬锛堣嚜鐢卞崗鍚屽鎵逛娇鐢級
approveReason: "",
checkResult: "",
tempFileIds: [],
@@ -249,7 +261,8 @@
approveTime: [{ required: false, message: "璇疯緭鍏�", trigger: "change" },],
approveId: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
approveUser: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- approveDeptName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ approveDeptName: [{ required: true, message: "璇烽�夋嫨鐢宠閮ㄩ棬", trigger: "change" }],
+ approveTitle: [{ required: true, message: "璇疯緭鍏ュ鎵规爣棰�", trigger: "blur" }],
approveReason: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
startDate: [{ required: true, message: "璇烽�夋嫨璇峰亣寮�濮嬫椂闂�", trigger: "change" }],
@@ -268,6 +281,19 @@
}
})
+// 鑾峰彇瀹℃壒浜嬬敱鏍囩
+const getApproveReasonLabel = () => {
+ const type = Number(props.approveType)
+ if (type === 5) {
+ return '閲囪喘璁″垝璇存槑锛�'
+ } else if (type === 9) {
+ return '閿�鍞悎鍚屽彿锛�'
+ } else if (type === 10) {
+ return '瀹℃壒浜嬬敱锛�'
+ }
+ return '瀹℃壒浜嬬敱锛�'
+}
+
// 瀹℃壒浜鸿妭鐐圭浉鍏�
const approverNodes = ref([
{ id: 1, userId: null }
@@ -281,12 +307,12 @@
approverNodes.value.splice(index, 1)
}
// 澶勭悊閮ㄩ棬閫夋嫨鍙樺寲
-const handleDeptChange = (deptId) => {
- if (deptId) {
- const selectedDept = productOptions.value.find(dept => dept.deptId === deptId);
- if (selectedDept) {
- form.value.approveDeptName = selectedDept.deptName;
- }
+const handleDeptChange = (deptIds) => {
+ if (deptIds && deptIds.length > 0) {
+ const selectedNames = productOptions.value
+ .filter(dept => deptIds.includes(dept.deptId))
+ .map(dept => dept.deptName);
+ form.value.approveDeptName = selectedNames.join(',');
} else {
form.value.approveDeptName = '';
}
@@ -298,6 +324,7 @@
userListNoPageByTenantId().then((res) => {
userList.value = res.data;
});
+ getProductOptions();
form.value = {}
approverNodes.value = [
{ id: 1, userId: null }
@@ -306,16 +333,26 @@
form.value.approveTime = getCurrentDate();
// 鑾峰彇褰撳墠鐢ㄦ埛淇℃伅骞惰缃儴闂↖D
- form.value.approveDeptId = userStore.currentDeptId
-
- // 鍔犺浇閮ㄩ棬閫夐」锛屽苟鍦ㄥ姞杞藉畬鎴愬悗璁剧疆閮ㄩ棬鍚嶇О
- getProductOptions();
+ form.value.approveDeptIdArray = []
if (operationType.value === 'edit') {
fileList.value = row.commonFileList
form.value.tempFileIds = fileList.value.map(file => file.id)
currentApproveStatus.value = row.approveStatus
approveProcessGetInfo({id: row.approveId,approveReason: '1'}).then(res => {
form.value = {...res.data}
+ // 澶勭悊閮ㄩ棬鍙嶆樉锛堟牴鎹悗绔繑鍥炵殑 approveDeptId 澶勭悊涓烘暟缁勶級
+ const deptId = res.data.approveDeptId;
+ if (deptId !== undefined && deptId !== null) {
+ if (Array.isArray(deptId)) {
+ form.value.approveDeptIdArray = deptId;
+ } else if (typeof deptId === 'string' && deptId.includes(',')) {
+ form.value.approveDeptIdArray = deptId.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
+ } else if (typeof deptId === 'string' || typeof deptId === 'number') {
+ form.value.approveDeptIdArray = [parseInt(deptId)];
+ }
+ } else {
+ form.value.approveDeptIdArray = [];
+ }
// 鍙嶆樉瀹℃壒浜�
if (res.data && res.data.approveUserIds) {
const userIds = res.data.approveUserIds.split(',')
@@ -332,18 +369,8 @@
}
}
const getProductOptions = () => {
- return getDept().then((res) => {
+ getDept().then((res) => {
productOptions.value = res.data;
- // 濡傛灉宸叉湁閮ㄩ棬ID锛岃嚜鍔ㄨ缃儴闂ㄥ悕绉帮紙鐢ㄤ簬楠岃瘉锛�
- if (form.value.approveDeptId && productOptions.value.length > 0) {
- const matchedDept = productOptions.value.find(dept =>
- dept.deptId == form.value.approveDeptId ||
- String(dept.deptId) === String(form.value.approveDeptId)
- );
- if (matchedDept) {
- form.value.approveDeptName = matchedDept.deptName;
- }
- }
});
};
function convertIdToValue(data) {
@@ -403,13 +430,14 @@
}
proxy.$refs.formRef.validate(valid => {
if (valid) {
+ const submitData = { ...form.value };
if (operationType.value === "add" || currentApproveStatus.value == 3) {
- approveProcessAdd(form.value).then(res => {
+ approveProcessAdd(submitData).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
})
} else {
- approveProcessUpdate(form.value).then(res => {
+ approveProcessUpdate(submitData).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
})
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 33bde47..f30c960 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -6,9 +6,11 @@
<el-tab-pane label="璇峰亣绠$悊" name="2"></el-tab-pane>
<el-tab-pane label="鍑哄樊绠$悊" name="3"></el-tab-pane>
<el-tab-pane label="鎶ラ攢绠$悊" name="4"></el-tab-pane>
- <el-tab-pane label="閲囪喘瀹℃壒" name="5"></el-tab-pane>
- <el-tab-pane label="鎶ヤ环瀹℃壒" name="6"></el-tab-pane>
- <el-tab-pane label="鍙戣揣瀹℃壒" name="7"></el-tab-pane>
+ <el-tab-pane label="閲囪喘璁″垝瀹℃壒" name="5"></el-tab-pane>
+<!-- <el-tab-pane label="鎶ヤ环瀹℃壒" name="6"></el-tab-pane>-->
+ <el-tab-pane label="鍑哄簱瀹℃壒" name="7"></el-tab-pane>
+ <el-tab-pane label="閿�鍞鎵�" name="9"></el-tab-pane>
+ <el-tab-pane label="鑷敱鍗忓悓瀹℃壒" name="10"></el-tab-pane>
</el-tabs>
<div class="search_form">
@@ -35,18 +37,9 @@
>
</div>
<div>
- <el-button
- type="primary"
- @click="openForm('add')"
- v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
- >鏂板</el-button>
+ <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 6 && currentApproveType !== 5 && currentApproveType !== 9">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button
- type="danger"
- plain
- @click="handleDelete"
- v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
- >鍒犻櫎</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
@@ -113,7 +106,8 @@
const isLeaveType = currentApproveType.value === 2; // 璇峰亣绠$悊
const isReimburseType = currentApproveType.value === 4; // 鎶ラ攢绠$悊
const isQuotationType = currentApproveType.value === 6; // 鎶ヤ环瀹℃壒
- const isPurchaseType = currentApproveType.value === 5; // 閲囪喘瀹℃壒
+ const isSalesType = currentApproveType.value === 9; // 閿�鍞鎵�
+ const isFreeType = currentApproveType.value === 10; // 鑷敱鍗忓悓瀹℃壒
// 鍩虹鍒楅厤缃�
const baseColumns = [
@@ -159,9 +153,16 @@
prop: "approveDeptName",
width: 220
},
+ // 瀹℃壒鏍囬锛堜粎鑷敱鍗忓悓瀹℃壒鏄剧ず锛�
+ ...(isFreeType ? [{
+ label: "瀹℃壒鏍囬",
+ prop: "approveTitle",
+ width: 200
+ }] : []),
{
- label: isQuotationType ? "鎶ヤ环鍗曞彿" : isPurchaseType ? "閲囪喘鍚堝悓鍙�" : "瀹℃壒浜嬬敱",
+ label: isQuotationType ? "鎶ヤ环鍗曞彿" : (isSalesType ? "閿�鍞悎鍚屽彿" : "瀹℃壒浜嬬敱"),
prop: "approveReason",
+ width: 200
},
{
label: "鐢宠浜�",
@@ -201,61 +202,44 @@
});
// 鎿嶄綔鍒�
- const actionOperations = [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
- },
- disabled: (row) =>
- currentApproveType.value === 5 ||
- currentApproveType.value === 6 ||
- currentApproveType.value === 7 ||
- row.approveStatus == 2 ||
- row.approveStatus == 1 ||
- row.approveStatus == 4
- },
- {
- name: "瀹℃牳",
- type: "text",
- clickFun: (row) => {
- openApprovalDia("approval", row);
- },
- disabled: (row) =>
- row.approveUserCurrentId == null ||
- row.approveStatus == 2 ||
- row.approveStatus == 3 ||
- row.approveStatus == 4 ||
- row.approveUserCurrentId !== userStore.id
- },
- {
- name: "璇︽儏",
- type: "text",
- clickFun: (row) => {
- openApprovalDia("view", row);
- },
- },
- ];
-
- // 鎶ヤ环瀹℃壒锛堢被鍨� 6锛変笉灞曠ず鈥滈檮浠垛�濇搷浣�
- if (!isQuotationType) {
- actionOperations.push({
- name: "闄勪欢",
- type: "text",
- clickFun: (row) => {
- downLoadFile(row);
- },
- });
- }
-
baseColumns.push({
dataType: "action",
label: "鎿嶄綔",
align: "center",
fixed: "right",
width: 230,
- operation: actionOperations,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => currentApproveType.value === 6 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
+ },
+ {
+ name: "瀹℃牳",
+ type: "text",
+ clickFun: (row) => {
+ openApprovalDia("approval", row);
+ },
+ disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
+ },
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: (row) => {
+ openApprovalDia('view', row);
+ },
+ },
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ },
+ ],
});
return baseColumns;
@@ -310,6 +294,8 @@
5: "/approveProcess/exportFive",
6: "/approveProcess/exportSix",
7: "/approveProcess/exportSeven",
+ 9: "/approveProcess/exportEight",
+ 10: "/approveProcess/exportNine",
}
const url = urlMap[type] || urlMap[0]
const nameMap = {
@@ -320,7 +306,9 @@
4: "鎶ラ攢绠$悊瀹℃壒琛�",
5: "閲囪喘鐢宠瀹℃壒琛�",
6: "鎶ヤ环瀹℃壒琛�",
- 7: "鍙戣揣瀹℃壒琛�",
+ 7: "鍑哄簱瀹℃壒琛�",
+ 9: "閿�鍞鎵硅〃",
+ 10: "鑷敱鍗忓悓瀹℃壒琛�",
}
const fileName = nameMap[type] || nameMap[0]
proxy.download(url, {}, `${fileName}.xlsx`)
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
index 6fa6595..94aa8fb 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -32,6 +32,18 @@
disabled
/>
</el-form-item>
+ <el-form-item label="淇濆吇椤圭洰">
+ <el-input
+ v-model="form.maintenanceProject"
+ placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
+ />
+ </el-form-item>
+ <el-form-item label="淇濆吇鍐呭">
+ <el-input
+ v-model="form.maintenanceContent"
+ placeholder="璇疯緭鍏ヤ繚鍏诲唴瀹�"
+ />
+ </el-form-item>
<el-form-item label="绫荤洰">
<el-input
v-model="form.machineryCategory"
@@ -115,6 +127,8 @@
createUser: undefined, // 褰曞叆浜�
status: 0, //淇濅慨鐘舵��
machineryCategory: undefined,
+ maintenanceProject: '',
+ maintenanceContent: '',
});
const setDeviceModel = (deviceId) => {
diff --git a/src/views/equipmentManagement/upkeep/Form/formDia.vue b/src/views/equipmentManagement/upkeep/Form/formDia.vue
index 66bf067..5921c80 100644
--- a/src/views/equipmentManagement/upkeep/Form/formDia.vue
+++ b/src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -67,6 +67,24 @@
</el-row>
<el-row>
<el-col :span="12">
+ <el-form-item label="淇濆吇椤圭洰">
+ <el-input
+ v-model="form.maintenanceProject"
+ placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="淇濆吇鍐呭">
+ <el-input
+ v-model="form.maintenanceContent"
+ placeholder="璇疯緭鍏ヤ繚鍏诲唴瀹�"
+ />
+ </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"/>
@@ -159,6 +177,8 @@
frequencyDetail: '',
week: '',
time: '',
+ maintenanceProject: '',
+ maintenanceContent: '',
deviceModel: undefined, // 瑙勬牸鍨嬪彿
registrationDate: ''
},
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 1e65663..bac44f1 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -397,6 +397,16 @@
cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-",
},
{
+ label: "淇濆吇椤圭洰",
+ align: "center",
+ prop: "maintenanceProject",
+ },
+ {
+ label: "淇濆吇鍐呭",
+ align: "center",
+ prop: "maintenanceContent",
+ },
+ {
label: "淇濆吇缁撴灉",
align: "center",
prop: "maintenanceResult",
diff --git a/src/views/index.vue b/src/views/index.vue
index 838182b..31319e8 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -249,13 +249,15 @@
import Echarts from "@/components/Echarts/echarts.vue";
import * as echarts from 'echarts';
import useUserStore from "@/store/modules/user.js";
+import { ElNotification } from 'element-plus'
import {
analysisCustomerContractAmounts, getAmountHalfYear,
getBusiness,
homeTodos,
processDataProductionStatistics,
statisticsReceivablePayable,
- qualityInspectionStatistics
+ qualityInspectionStatistics,
+ overdueReceivable
} from "@/api/viewIndex.js";
import { list } from '@/api/productionManagement/productionProcess';
@@ -446,11 +448,32 @@
getBusinessData()
analysisCustomer()
todoInfoS()
+ notifyOverdueReceivable()
statisticsReceivable()
qualityStatisticsInfo()
getAmountHalfYearNum()
getProcessList()
})
+
+// 寰呭洖娆炬彁閱�
+const notifyOverdueReceivable = async () => {
+ try {
+ const res = await overdueReceivable()
+ const data = res.data
+
+ if (data > 0) {
+ ElNotification({
+ title: '寰呭洖娆炬彁閱�',
+ message: `褰撳墠鏈�${data}鏉″緟鍥炴`,
+ type: 'warning',
+ duration: 6000,
+ })
+ }
+ } catch (e) {
+ // 涓嶅奖鍝嶉椤垫甯稿姞杞�
+ console.error('overdueReceivable error:', e)
+ }
+}
// 鏁版嵁缁熻
const getBusinessData = () => {
getBusiness().then((res) => {
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index a7a8a4b..30f4670 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -129,10 +129,9 @@
const total = ref(0);
const props = defineProps({
- type: {
- type: String,
- required: true,
- default: '0'
+ productId: {
+ type: [String, Number],
+ default: ''
}
})
@@ -163,7 +162,7 @@
};
const getList = () => {
tableLoading.value = true;
- getStockOutPage({ ...searchForm.value, ...page, type: props.type })
+ getStockOutPage({ ...searchForm.value, ...page, topParentProductId: props.productId })
.then((res) => {
tableLoading.value = false;
tableData.value = res.data.records;
@@ -183,17 +182,20 @@
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
- if (props.type === '0') {
- findAllQualifiedStockOutRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
- return
- }
- findAllUnQualifiedStockOutRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
+ // 鍚屾椂鑾峰彇鍚堟牸鍜屼笉鍚堟牸鐨勬潵婧愮被鍨嬮�夐」
+ Promise.all([
+ findAllQualifiedStockOutRecordTypeOptions(),
+ findAllUnQualifiedStockOutRecordTypeOptions()
+ ]).then(([qualifiedRes, unQualifiedRes]) => {
+ const qualified = qualifiedRes.data || [];
+ const unQualified = unQualifiedRes.data || [];
+ // 鍚堝苟骞跺幓閲�
+ const allOptions = [...qualified, ...unQualified];
+ const uniqueOptions = allOptions.filter((item, index, self) =>
+ index === self.findIndex((t) => t.value === item.value)
+ );
+ stockRecordTypeOptions.value = uniqueOptions;
+ });
}
// 琛ㄦ牸閫夋嫨鏁版嵁
@@ -212,7 +214,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/stockOutRecord/exportStockOutRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx");
+ proxy.download("/stockOutRecord/exportStockOutRecord", { topParentProductId: props.productId }, "鍑哄簱鍙拌处.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
diff --git a/src/views/inventoryManagement/dispatchLog/index.vue b/src/views/inventoryManagement/dispatchLog/index.vue
index 88d9984..0dcfd06 100644
--- a/src/views/inventoryManagement/dispatchLog/index.vue
+++ b/src/views/inventoryManagement/dispatchLog/index.vue
@@ -1,38 +1,50 @@
-<!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
<template>
<div class="app-container">
- <el-tabs v-model="activeTab" @tab-change="handleTabChange">
- <el-tab-pane v-for="tab in tabs"
- :label="tab.label"
- :name="tab.name"
- :key="tab.name">
- <record :type="tab.type" v-if="activeTab === tab.name" />
- </el-tab-pane>
- </el-tabs>
+ <div v-loading="loading" element-loading-text="鍔犺浇涓�..." style="min-height: 80vh;">
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange" v-if="!loading">
+ <el-tab-pane v-for="tab in products"
+ :label="tab.productName"
+ :name="tab.id"
+ :key="tab.id">
+ <Record :product-id="tab.id" v-if="tab.id === activeTab" />
+ </el-tab-pane>
+ </el-tabs>
+ </div>
</div>
</template>
<script setup>
+import { ref, onMounted } from 'vue';
+import { productTreeList } from "@/api/basicData/product.js";
import Record from "@/views/inventoryManagement/dispatchLog/Record.vue";
-const activeTab = ref('qualified')
-const type = ref(0)
-const tabs = computed(() => {
- return [
- {
- label: '鍚堟牸鍑哄簱',
- name: 'qualified',
- type: '0'
- },
- {
- label: '涓嶅悎鏍煎嚭搴�',
- name: 'unqualified',
- type: '1'
- }
- ]
-})
+
+const products = ref([])
+const activeTab = ref(null)
+const loading = ref(false)
const handleTabChange = (tabName) => {
activeTab.value = tabName;
- type.value = tabName === 'qualified' ? 0 : 1
}
+
+const fetchProducts = async () => {
+ loading.value = true;
+ try {
+ const res = await productTreeList();
+ const productList = res.filter((item) => item.parentId === null).map(({ id, productName }) => ({ id, productName }));
+ // 灏嗙涓�涓猼ab鐨勫悕绉版敼涓�"閿�鍞�"
+ if (productList.length > 0) {
+ productList[0].productName = '閿�鍞�';
+ }
+ products.value = productList;
+ if (products.value.length > 0) {
+ activeTab.value = products.value[0].id;
+ }
+ } finally {
+ loading.value = false;
+ }
+}
+
+onMounted(() => {
+ fetchProducts();
+})
</script>
diff --git a/src/views/inventoryManagement/issueManagement/Record.vue b/src/views/inventoryManagement/issueManagement/Record.vue
new file mode 100644
index 0000000..1f30aae
--- /dev/null
+++ b/src/views/inventoryManagement/issueManagement/Record.vue
@@ -0,0 +1,570 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鍑哄簱鏃堕棿锛�</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-input v-model="searchForm.productName" style="width: 240px" placeholder="璇疯緭鍏�" @change="handleQuery"
+ clearable prefix-icon="Search" />
+ <span class="search_title ml10">鏉ユ簮锛�</span>
+ <el-select v-model="searchForm.recordType"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery">
+ <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 @click="handleOut">瀵煎嚭</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, index) => index" style="width: 100%"
+ :row-class-name="tableRowClassName" 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="productName" show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
+ <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
+ <el-table-column label="鍚堟牸搴撳瓨鏁伴噺" prop="qualifiedQuantity" show-overflow-tooltip />
+ <el-table-column label="涓嶅悎鏍煎簱瀛樻暟閲�" prop="unQualifiedQuantity" show-overflow-tooltip />
+ <el-table-column label="鍚堟牸鍐荤粨鏁伴噺" prop="qualifiedLockedQuantity" show-overflow-tooltip />
+ <el-table-column label="涓嶅悎鏍煎喕缁撴暟閲�" prop="unQualifiedLockedQuantity" show-overflow-tooltip />
+ <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" show-overflow-tooltip />
+ <el-table-column label="澶囨敞" prop="remark" show-overflow-tooltip />
+ <el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" show-overflow-tooltip />
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="90" align="center">
+ <template #default="scope">
+ <el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="scope.row.unQualifiedUnLockedQuantity === 0 && scope.row.qualifiedUnLockedQuantity === 0">{{ actionButtonText }}</el-button>
+ <el-button link type="primary" v-if="scope.row.unQualifiedUnLockedQuantity > 0 || scope.row.qualifiedUnLockedQuantity > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
+ <el-button link type="primary" v-if="scope.row.qualifiedLockedQuantity > 0 || scope.row.unQualifiedLockedQuantity > 0" @click="showThawModal(scope.row)">瑙e喕</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" />
+ </div>
+
+ <!-- 棰嗙敤/鍙戣揣寮规 -->
+ <el-dialog
+ v-model="isShowSubtractModal"
+ :title="dialogTitle"
+ width="800"
+ @close="closeSubtractModal"
+ >
+ <el-form label-width="140px" :model="subtractForm" label-position="top" ref="subtractFormRef">
+ <el-form-item
+ label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[{ required: true, message: '璇烽�夋嫨浜у搧', trigger: 'change' }]"
+ >
+ <el-button type="primary" disabled>
+ {{ subtractForm.productName ? subtractForm.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+
+ <el-form-item label="瑙勬牸" prop="productModelName">
+ <el-input v-model="subtractForm.model" disabled />
+ </el-form-item>
+
+ <el-form-item label="鍗曚綅" prop="unit">
+ <el-input v-model="subtractForm.unit" disabled />
+ </el-form-item>
+
+ <el-form-item
+ label="搴撳瓨绫诲瀷"
+ prop="type"
+ :rules="[{ required: true, message: '璇烽�夋嫨搴撳瓨绫诲瀷', trigger: 'change' }]"
+ >
+ <el-select v-model="subtractForm.type" placeholder="璇烽�夋嫨搴撳瓨绫诲瀷" @change="handleTypeChange">
+ <el-option label="鍚堟牸搴撳瓨" value="qualified" :disabled="currentRecord.qualifiedUnLockedQuantity <= 0" />
+ <el-option label="涓嶅悎鏍煎簱瀛�" value="unqualified" :disabled="currentRecord.unQualifiedUnLockedQuantity <= 0" />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="鏁伴噺" prop="qualitity">
+ <el-input-number v-model="subtractForm.qualitity" :step="1" :min="1" :max="maxQuality" style="width: 100%" />
+ </el-form-item>
+
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="subtractForm.remark" type="textarea" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleSubtractSubmit">纭</el-button>
+ <el-button @click="closeSubtractModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+
+ <!-- 鍐荤粨/瑙e喕寮规 -->
+ <el-dialog
+ v-model="isShowFrozenModal"
+ :title="frozenDialogTitle"
+ width="800"
+ @close="closeFrozenModal"
+ >
+ <el-form label-width="140px" :model="frozenForm" label-position="top" ref="frozenFormRef">
+ <el-form-item
+ label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[{ required: true, message: '璇烽�夋嫨浜у搧', trigger: 'change' }]"
+ >
+ <el-button type="primary" disabled>
+ {{ frozenForm.productName ? frozenForm.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+
+ <el-form-item label="瑙勬牸" prop="productModelName">
+ <el-input v-model="frozenForm.model" disabled />
+ </el-form-item>
+
+ <el-form-item label="鍗曚綅" prop="unit">
+ <el-input v-model="frozenForm.unit" disabled />
+ </el-form-item>
+
+ <el-form-item
+ label="搴撳瓨绫诲瀷"
+ prop="type"
+ :rules="[{ required: true, message: '璇烽�夋嫨搴撳瓨绫诲瀷', trigger: 'change' }]"
+ >
+ <el-select v-model="frozenForm.type" placeholder="璇烽�夋嫨搴撳瓨绫诲瀷" @change="handleFrozenTypeChange">
+ <el-option
+ label="鍚堟牸搴撳瓨"
+ value="qualified"
+ :disabled="frozenOperationType === 'frozen' ? currentRecord.qualifiedUnLockedQuantity <= 0 : currentRecord.qualifiedLockedQuantity <= 0"
+ />
+ <el-option
+ label="涓嶅悎鏍煎簱瀛�"
+ value="unqualified"
+ :disabled="frozenOperationType === 'frozen' ? currentRecord.unQualifiedUnLockedQuantity <= 0 : currentRecord.unQualifiedLockedQuantity <= 0"
+ />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="鏁伴噺" prop="qualitity">
+ <el-input-number v-model="frozenForm.qualitity" :step="1" :min="1" :max="frozenMaxQuality" style="width: 100%" />
+ </el-form-item>
+
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="frozenForm.remark" type="textarea" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleFrozenSubmit">纭</el-button>
+ <el-button @click="closeFrozenModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import pagination from '@/components/PIMTable/Pagination.vue'
+import { ref, reactive, toRefs, getCurrentInstance, onMounted, computed } from 'vue'
+import { ElMessageBox } from "element-plus";
+import useUserStore from '@/store/modules/user'
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import {
+ getStockInventoryListPageCombined
+} from "@/api/inventoryManagement/stockInventory.js";
+import {
+ subtractStockInventory
+} from "@/api/inventoryManagement/stockInventory.js";
+import {
+ subtractStockUnInventory
+} from "@/api/inventoryManagement/stockUninventory.js";
+import {
+ frozenStockInventory,
+ thawStockInventory
+} from "@/api/inventoryManagement/stockInventory.js";
+import {
+ frozenStockUninventory,
+ thawStockUninventory
+} from "@/api/inventoryManagement/stockUninventory.js";
+import { getCurrentDate } from "@/utils/index.js";
+import {
+ findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const props = defineProps({
+ productId: {
+ type: [String, Number],
+ default: ''
+ },
+ productName: {
+ type: String,
+ default: ''
+ }
+})
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const tableData = ref([])
+const selectedRows = ref([])
+const userList = ref([])
+const tableLoading = ref(false)
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([])
+const page = reactive({
+ current: 1,
+ size: 100,
+})
+const total = ref(0)
+
+// 褰撳墠鎿嶄綔鐨勮褰�
+const currentRecord = ref({})
+
+// 鏄惁鏄剧ず棰嗙敤/鍙戣揣寮规
+const isShowSubtractModal = ref(false)
+// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
+const isShowFrozenModal = ref(false)
+// 鍐荤粨/瑙e喕鎿嶄綔绫诲瀷
+const frozenOperationType = ref('frozen')
+
+// 鍒ゆ柇鏄惁鏄垚鍝侊紙浜у搧鍚嶇О鍖呭惈"鎴愬搧"锛�
+const isFinishedProduct = computed(() => {
+ return props.productName && props.productName.includes('鎴愬搧')
+})
+
+// 鎸夐挳鏂囧瓧锛氭垚鍝佹樉绀�"鍙戣揣"锛屽叾浠栨樉绀�"棰嗙敤"
+const actionButtonText = computed(() => {
+ return isFinishedProduct.value ? '鍙戣揣' : '棰嗙敤'
+})
+
+// 寮规鏍囬
+const dialogTitle = computed(() => {
+ return isFinishedProduct.value ? '鍙戣揣' : '棰嗙敤'
+})
+
+// 鍐荤粨/瑙e喕寮规鏍囬
+const frozenDialogTitle = computed(() => {
+ return frozenOperationType.value === 'frozen' ? '鍐荤粨' : '瑙e喕'
+})
+
+// 棰嗙敤/鍙戣揣琛ㄥ崟
+const subtractFormRef = ref(null)
+const subtractForm = ref({
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ type: "",
+ qualitity: 0,
+ remark: '',
+})
+
+// 鍐荤粨/瑙e喕琛ㄥ崟
+const frozenFormRef = ref(null)
+const frozenForm = ref({
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ type: "",
+ qualitity: 0,
+ remark: '',
+})
+
+// 棰嗙敤/鍙戣揣鏈�澶ф暟閲�
+const maxQuality = computed(() => {
+ let max = 0;
+ if (subtractForm.value.type === 'qualified') {
+ max = currentRecord.value.qualifiedUnLockedQuantity ? currentRecord.value.qualifiedUnLockedQuantity : 0;
+ } else {
+ max = currentRecord.value.unQualifiedUnLockedQuantity ? currentRecord.value.unQualifiedUnLockedQuantity : 0;
+ }
+ return Math.max(max, 1);
+})
+
+// 鍐荤粨/瑙e喕鏈�澶ф暟閲�
+const frozenMaxQuality = computed(() => {
+ let max = 0;
+ if (frozenOperationType.value === 'frozen') {
+ if (frozenForm.value.type === 'qualified') {
+ max = currentRecord.value.qualifiedUnLockedQuantity ? currentRecord.value.qualifiedUnLockedQuantity : 0;
+ } else {
+ max = currentRecord.value.unQualifiedUnLockedQuantity ? currentRecord.value.unQualifiedUnLockedQuantity : 0;
+ }
+ } else {
+ if (frozenForm.value.type === 'qualified') {
+ max = currentRecord.value.qualifiedLockedQuantity ? currentRecord.value.qualifiedLockedQuantity : 0;
+ } else {
+ max = currentRecord.value.unQualifiedLockedQuantity ? currentRecord.value.unQualifiedLockedQuantity : 0;
+ }
+ }
+ return Math.max(max, 1);
+})
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const dialogFormVisible = ref(false)
+const data = reactive({
+ searchForm: {
+ productName: '',
+ recordType: '',
+ timeStr: '',
+ topParentProductId: props.productId,
+ },
+ form: {
+ productrecordId: '',
+ },
+ rules: {
+ inboundTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ inboundQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ nickname: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }]
+ }
+})
+const { searchForm, form, rules } = toRefs(data)
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1
+ getList()
+}
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList()
+}
+const getList = () => {
+ tableLoading.value = true
+ getStockInventoryListPageCombined({ ...searchForm.value, ...page }).then(res => {
+ tableLoading.value = false
+ tableData.value = res.data.records
+ total.value = res.data.total
+ }).catch(() => {
+ tableLoading.value = false
+ })
+}
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+ Promise.all([
+ findAllQualifiedStockOutRecordTypeOptions(),
+ findAllUnQualifiedStockOutRecordTypeOptions()
+ ]).then(([qualifiedRes, unQualifiedRes]) => {
+ const qualified = qualifiedRes.data || [];
+ const unQualified = unQualifiedRes.data || [];
+ const allOptions = [...qualified, ...unQualified];
+ const uniqueOptions = allOptions.filter((item, index, self) =>
+ index === self.findIndex((t) => t.value === item.value)
+ );
+ stockRecordTypeOptions.value = uniqueOptions;
+ });
+}
+
+// 鐐瑰嚮棰嗙敤/鍙戣揣
+const showSubtractModal = (row) => {
+ currentRecord.value = row
+ subtractForm.value = {
+ ...row,
+ type: '',
+ qualitity: 0,
+ remark: '',
+ }
+ isShowSubtractModal.value = true
+}
+
+// 鍏抽棴棰嗙敤/鍙戣揣寮规
+const closeSubtractModal = () => {
+ subtractForm.value = {
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ type: "",
+ qualitity: 0,
+ remark: '',
+ }
+ isShowSubtractModal.value = false
+}
+
+// 搴撳瓨绫诲瀷鏀瑰彉
+const handleTypeChange = () => {
+ subtractForm.value.qualitity = 0;
+}
+
+// 鍐荤粨绫诲瀷鏀瑰彉
+const handleFrozenTypeChange = () => {
+ frozenForm.value.qualitity = 0;
+}
+
+// 鎻愪氦棰嗙敤/鍙戣揣
+const handleSubtractSubmit = () => {
+ proxy.$refs["subtractFormRef"].validate(valid => {
+ if (valid) {
+ if (!subtractForm.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
+ }
+ if (subtractForm.value.type === 'qualified') {
+ subtractStockInventory(subtractForm.value).then(res => {
+ isShowSubtractModal.value = false;
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ getList();
+ })
+ } else {
+ subtractStockUnInventory(subtractForm.value).then(res => {
+ isShowSubtractModal.value = false;
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ getList();
+ })
+ }
+ }
+ })
+}
+
+// 鐐瑰嚮鍐荤粨
+const showFrozenModal = (row) => {
+ currentRecord.value = row
+ frozenOperationType.value = 'frozen'
+ frozenForm.value = {
+ ...row,
+ type: '',
+ qualitity: 0,
+ remark: '',
+ }
+ isShowFrozenModal.value = true
+}
+
+// 鐐瑰嚮瑙e喕
+const showThawModal = (row) => {
+ currentRecord.value = row
+ frozenOperationType.value = 'thaw'
+ frozenForm.value = {
+ ...row,
+ type: '',
+ qualitity: 0,
+ remark: '',
+ }
+ isShowFrozenModal.value = true
+}
+
+// 鍏抽棴鍐荤粨/瑙e喕寮规
+const closeFrozenModal = () => {
+ frozenForm.value = {
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ type: "",
+ qualitity: 0,
+ remark: '',
+ }
+ isShowFrozenModal.value = false
+}
+
+// 鎻愪氦鍐荤粨/瑙e喕
+const handleFrozenSubmit = () => {
+ proxy.$refs["frozenFormRef"].validate(valid => {
+ if (valid) {
+ if (!frozenForm.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
+ }
+ const isQualified = frozenForm.value.type === 'qualified'
+ const isFrozen = frozenOperationType.value === 'frozen'
+
+ if (isQualified) {
+ if (isFrozen) {
+ frozenStockInventory(frozenForm.value).then(res => {
+ isShowFrozenModal.value = false;
+ proxy.$modal.msgSuccess("鍐荤粨鎴愬姛");
+ getList();
+ })
+ } else {
+ thawStockInventory(frozenForm.value).then(res => {
+ isShowFrozenModal.value = false;
+ proxy.$modal.msgSuccess("瑙e喕鎴愬姛");
+ getList();
+ })
+ }
+ } else {
+ if (isFrozen) {
+ frozenStockUninventory(frozenForm.value).then(res => {
+ isShowFrozenModal.value = false;
+ proxy.$modal.msgSuccess("鍐荤粨鎴愬姛");
+ getList();
+ })
+ } else {
+ thawStockUninventory(frozenForm.value).then(res => {
+ isShowFrozenModal.value = false;
+ proxy.$modal.msgSuccess("瑙e喕鎴愬姛");
+ getList();
+ })
+ }
+ }
+ }
+ })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection.filter(item => item.id);
+}
+const expandedRowKeys = ref([])
+
+// 琛ㄦ牸琛岀被鍚�
+const tableRowClassName = ({ row }) => {
+ const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
+ const warn = Number(row?.warnNum ?? 0);
+ if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
+ return '';
+ }
+ return stock < warn ? 'row-low-stock' : '';
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm(
+ '鏄惁纭瀵煎嚭锛�',
+ '瀵煎嚭', {
+ confirmButtonText: '纭',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning',
+ }
+ ).then(() => {
+ proxy.download("/stockInventory/exportStockInventory", {topParentProductId: props.productId}, '搴撳瓨淇℃伅.xlsx')
+ }).catch(() => {
+ proxy.$modal.msg("宸插彇娑�")
+ })
+}
+
+onMounted(() => {
+ getList()
+ fetchStockRecordTypeOptions()
+})
+</script>
+
+<style scoped lang="scss">
+:deep(.row-low-stock td) {
+ background-color: #fde2e2;
+ color: #c45656;
+}
+
+:deep(.row-low-stock:hover > td) {
+ background-color: #fcd4d4;
+}
+</style>
diff --git a/src/views/inventoryManagement/issueManagement/index.vue b/src/views/inventoryManagement/issueManagement/index.vue
index 2bba7d0..24a791e 100644
--- a/src/views/inventoryManagement/issueManagement/index.vue
+++ b/src/views/inventoryManagement/issueManagement/index.vue
@@ -1,285 +1,50 @@
<template>
<div class="app-container">
- <div class="search_form">
- <div>
- <span class="search_title">渚涘簲鍟嗗悕绉帮細</span>
- <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="璇疯緭鍏�" @change="handleQuery"
- clearable prefix-icon="Search" />
- <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-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
- </div>
- <div>
- <!-- <el-button type="primary" @click="openForm('add')">鏂板鍑哄簱</el-button> -->
- <el-button @click="handleOut">瀵煎嚭</el-button>
- <!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> -->
- </div>
+ <div v-loading="loading" element-loading-text="鍔犺浇涓�..." style="min-height: 80vh;">
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange" v-if="!loading">
+ <el-tab-pane v-for="tab in products"
+ :label="tab.productName"
+ :name="tab.id"
+ :key="tab.id">
+ <Record :product-id="tab.id" :product-name="tab.productName" v-if="tab.id === activeTab" />
+ </el-tab-pane>
+ </el-tabs>
</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" show-summary style="width: 100%"
- :summary-method="summarizeMainTable" 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="createTime" width="100" show-overflow-tooltip />
- <el-table-column label="鍏ュ簱鎵规" prop="inboundBatches" width="160" show-overflow-tooltip />
- <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="240" show-overflow-tooltip />
- <el-table-column label="浜у搧澶х被" prop="productCategory" width="100" show-overflow-tooltip />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="200" show-overflow-tooltip />
- <el-table-column label="鍗曚綅" prop="unit" width="70" show-overflow-tooltip />
- <el-table-column label="鍏ュ簱鏁伴噺" prop="inboundNum" width="90" show-overflow-tooltip />
- <el-table-column label="搴撳瓨鏁伴噺" prop="inboundNum0" width="90" show-overflow-tooltip />
- <el-table-column label="鍚◣鍗曚环" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip />
- <el-table-column label="鍚◣鎬讳环" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip />
- <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" show-overflow-tooltip />
- <el-table-column label="涓嶅惈绋庢�讳环" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip />
- <el-table-column label="鍏ュ簱浜�" prop="createBy" width="80" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
- <template #default="scope">
- <el-button link type="primary" @click="openForm(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" />
- </div>
- <el-dialog v-model="dialogFormVisible" :title="'鏂板鍑哄簱'" width="40%" @close="closeDia">
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <el-form-item label="鍑哄簱鏁伴噺锛�" prop="salesContractNo">
- <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inboundQuantity" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- <el-form-item label="鍑哄簱鏃ユ湡锛�" prop="projectName">
- <el-date-picker style="width: 100%" v-model="form.inboundTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
- type="date" placeholder="璇烽�夋嫨" clearable />
- </el-form-item>
- <el-form-item label="鍑哄簱浜猴細" prop="entryPerson">
- <el-select v-model="form.nickName" 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>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
</div>
</template>
<script setup>
-import pagination from '@/components/PIMTable/Pagination.vue'
-import { ref } from 'vue'
-import { ElMessageBox } from "element-plus";
-import useUserStore from '@/store/modules/user'
-import { userListNoPageByTenantId } from "@/api/system/user.js";
-import {
- getStockInPage
-} from "@/api/inventoryManagement/stockIn.js";
-import {
- getStockManagePage,
- delStockManage,
- stockOut,
-} from "@/api/inventoryManagement/stockManage.js";
+import { ref, onMounted } from 'vue';
+import { productTreeList } from "@/api/basicData/product.js";
+import Record from "@/views/inventoryManagement/issueManagement/Record.vue";
-const userStore = useUserStore()
-const { proxy } = getCurrentInstance()
-const tableData = ref([])
-const selectedRows = ref([])
-const userList = ref([])
-const tableLoading = ref(false)
-const page = reactive({
- current: 1,
- size: 100,
-})
-const total = ref(0)
-const fileList = ref([])
+const products = ref([])
+const activeTab = ref(null)
+const loading = ref(false)
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const dialogFormVisible = ref(false)
-const data = reactive({
- searchForm: {
- supplierName: '',
- inboundQuantity:'',
- inboundTime:'',
- nickName: '',
- userId: '',
- timeStr: '',
- },
- form: {
- productrecordId: '',
- },
- rules: {
- inboundTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- inboundQuantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- nickname: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }]
- }
-})
-const { searchForm, form, rules } = toRefs(data)
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1
- getList()
-}
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList()
-}
-const getList = () => {
- tableLoading.value = true
- getStockInPage({ ...searchForm.value, ...page }).then(res => {
- tableLoading.value = false
- tableData.value = res.data.records
- total.value = res.data.total
- console.log('res', res.data.records)
- }).catch(() => {
- tableLoading.value = false
- })
+const handleTabChange = (tabName) => {
+ activeTab.value = tabName;
}
-const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode.label; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter(item => item.id);
- console.log('selection', selectedRows.value)
-}
-const expandedRowKeys = ref([])
-
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']);
-};
-const currentRowId = ref(null) // 鏂板锛氬瓨鍌ㄥ綋鍓嶆搷浣滅殑琛孖D
-
-const currentRowNum = ref(0)
-const salesLedgerProductId = ref(null);
-
-// 鎵撳紑寮规
-const openForm = async (row) => {
- dialogFormVisible.value = true
- currentRowId.value = row.id
- currentRowNum.value = row.inboundNum0
- salesLedgerProductId.value = row.salesLedgerProductId
- form.value = {}
- // 鍒濆鍖栬〃鍗曟暟鎹�
- form.value = {
- productrecordId: '',
- inboundQuantity: '', // 鍑哄簱鏁伴噺娓呯┖
- inboundTime: getCurrentDate(), // 榛樿褰撳墠鏃ユ湡
- nickName: '', // 榛樿褰撳墠鐢ㄦ埛
- }
- console.log('form',form.value)
- // 鍔犺浇鐢ㄦ埛鍒楄〃
+const fetchProducts = async () => {
+ loading.value = true;
try {
- const userLists = await userListNoPageByTenantId()
- userList.value = userLists.data
- } catch (error) {
- console.error('鍔犺浇鐢ㄦ埛鍒楄〃澶辫触:', error)
- }
-}
-
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- let num = Number(form.value.inboundQuantity)
- if(num <= 0 || num > currentRowNum.value){
- return proxy.$modal.msgWarning("璇峰~鍏ユ湁鏁堟暟瀛�")
- }
- proxy.$refs["formRef"].validate(valid => {
- if (valid && currentRowId.value) {
- const outData = {
- id: currentRowId.value, // 鍘熷璁板綍ID
- salesLedgerProductId: salesLedgerProductId.value,
- quantity: form.value.inboundQuantity, // 鍑哄簱鏁伴噺
- time: form.value.inboundTime, // 鍑哄簱鏃堕棿
- userId: form.value.nickName // 鎿嶄綔浜�
- }
- console.log(outData)
-
- stockOut(outData).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛")
- closeDia()
- getList()
- }).catch(err => {
- proxy.$modal.msgError("鍑哄簱澶辫触")
- })
+ const res = await productTreeList();
+ const productList = res.filter((item) => item.parentId === null).map(({ id, productName }) => ({ id, productName }));
+ // 灏嗙涓�涓猼ab鐨勫悕绉版敼涓�"閿�鍞�"
+ if (productList.length > 0) {
+ productList[0].productName = '閿�鍞�';
}
- })
-}
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef")
- dialogFormVisible.value = false
+ products.value = productList;
+ if (products.value.length > 0) {
+ activeTab.value = products.value[0].id;
+ }
+ } finally {
+ loading.value = false;
+ }
}
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm(
- '鏄惁纭瀵煎嚭锛�',
- '瀵煎嚭', {
- confirmButtonText: '纭',
- cancelButtonText: '鍙栨秷',
- type: 'warning',
- }
- ).then(() => {
- proxy.download("/stockin/export", {}, '鍏ュ簱鍙拌处.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(() => {
- delStockManage(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
- getList()
- })
- }).catch(() => {
- proxy.$modal.msg("宸插彇娑�")
- })
-}
onMounted(() => {
- getList()
+ fetchProducts();
})
</script>
-
-<style scoped lang="scss"></style>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 3f90edf..56d4981 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -115,10 +115,9 @@
const {proxy} = getCurrentInstance();
const props = defineProps({
- type: {
- type: String,
- required: true,
- default: '0'
+ productId: {
+ type: [String, Number],
+ default: ''
}
})
@@ -160,7 +159,7 @@
const getList = () => {
tableLoading.value = true;
- const params = {...page, type: props.type};
+ const params = {...page, topParentProductId: props.productId};
params.timeStr = searchForm.value.timeStr;
params.productName = searchForm.value.productName;
params.recordType = searchForm.value.recordType;
@@ -175,17 +174,20 @@
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
- if (props.type === '0') {
- findAllQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
- return
- }
- findAllUnQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
+ // 鍚屾椂鑾峰彇鍚堟牸鍜屼笉鍚堟牸鐨勬潵婧愮被鍨嬮�夐」
+ Promise.all([
+ findAllQualifiedStockInRecordTypeOptions(),
+ findAllUnQualifiedStockInRecordTypeOptions()
+ ]).then(([qualifiedRes, unQualifiedRes]) => {
+ const qualified = qualifiedRes.data || [];
+ const unQualified = unQualifiedRes.data || [];
+ // 鍚堝苟骞跺幓閲�
+ const allOptions = [...qualified, ...unQualified];
+ const uniqueOptions = allOptions.filter((item, index, self) =>
+ index === self.findIndex((t) => t.value === item.value)
+ );
+ stockRecordTypeOptions.value = uniqueOptions;
+ });
}
// 琛ㄦ牸閫夋嫨鏁版嵁
@@ -203,8 +205,7 @@
type: "warning",
})
.then(() => {
- // 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
- proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx");
+ proxy.download("/stockInRecord/exportStockInRecord", { topParentProductId: props.productId }, "鍏ュ簱鍙拌处.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
diff --git a/src/views/inventoryManagement/receiptManagement/index.vue b/src/views/inventoryManagement/receiptManagement/index.vue
index 8ca110f..131259c 100644
--- a/src/views/inventoryManagement/receiptManagement/index.vue
+++ b/src/views/inventoryManagement/receiptManagement/index.vue
@@ -1,36 +1,45 @@
<template>
<div class="app-container">
- <el-tabs v-model="activeTab" @tab-change="handleTabChange">
- <el-tab-pane v-for="tab in tabs"
- :label="tab.label"
- :name="tab.name"
- :key="tab.name">
- <record :type="tab.type" v-if="activeTab === tab.name" />
- </el-tab-pane>
- </el-tabs>
+ <div v-loading="loading" element-loading-text="鍔犺浇涓�..." style="min-height: 80vh;">
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange" v-if="!loading">
+ <el-tab-pane v-for="tab in products"
+ :label="tab.productName"
+ :name="tab.id"
+ :key="tab.id">
+ <Record :product-id="tab.id" v-if="tab.id === activeTab" />
+ </el-tab-pane>
+ </el-tabs>
+ </div>
</div>
</template>
<script setup>
+import { ref, onMounted } from 'vue';
+import { productTreeList } from "@/api/basicData/product.js";
import Record from "@/views/inventoryManagement/receiptManagement/Record.vue";
-const activeTab = ref('qualified')
-const type = ref(0)
-const tabs = ref([
- {
- label: '鍚堟牸鍏ュ簱',
- name: 'qualified',
- type: '0'
- },
- {
- label: '涓嶅悎鏍煎叆搴�',
- name: 'unqualified',
- type: '1'
- }
-])
+const products = ref([])
+const activeTab = ref(null)
+const loading = ref(false)
const handleTabChange = (tabName) => {
activeTab.value = tabName;
- type.value = tabName === 'qualified' ? 0 : 1
}
+
+const fetchProducts = async () => {
+ loading.value = true;
+ try {
+ const res = await productTreeList();
+ products.value = res.filter((item) => item.parentId === null).map(({ id, productName }) => ({ id, productName }));
+ if (products.value.length > 0) {
+ activeTab.value = products.value[0].id;
+ }
+ } finally {
+ loading.value = false;
+ }
+}
+
+onMounted(() => {
+ fetchProducts();
+})
</script>
diff --git a/src/views/personnelManagement/contractManagement/index.vue b/src/views/personnelManagement/contractManagement/index.vue
index 1d2aab7..71e5e93 100644
--- a/src/views/personnelManagement/contractManagement/index.vue
+++ b/src/views/personnelManagement/contractManagement/index.vue
@@ -132,11 +132,6 @@
prop: "postJob",
},
{
- label: "鐜颁綇鍧�",
- prop: "adress",
- width: 200
- },
- {
label: "绗竴瀛﹀巻",
prop: "firstStudy",
},
@@ -164,15 +159,15 @@
prop: "emergencyContactPhone",
width: 150
},
- // {
- // label: "鍚堝悓骞撮檺",
- // prop: "contractTerm",
- // },
- // {
- // label: "鍚堝悓寮�濮嬫棩鏈�",
- // prop: "contractStartTime",
- // width: 120
- // },
+ {
+ label: "鍚堝悓骞撮檺",
+ prop: "contractTerm",
+ },
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ width: 120
+ },
{
label: "鍚堝悓缁撴潫鏃ユ湡",
prop: "contractExpireTime",
@@ -238,7 +233,6 @@
tableLoading.value = true;
const params = { ...searchForm.value, ...page };
params.entryDate = undefined
- params.staffState = 1
staffOnJobListPage(params).then(res => {
tableLoading.value = false;
tableData.value = res.data.records
diff --git a/src/views/personnelManagement/dimission/components/formDia.vue b/src/views/personnelManagement/dimission/components/formDia.vue
index 84922ec..9797b33 100644
--- a/src/views/personnelManagement/dimission/components/formDia.vue
+++ b/src/views/personnelManagement/dimission/components/formDia.vue
@@ -51,11 +51,6 @@
{{ currentStaffRecord.postName || '-' }}
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="鐜颁綇鍧�锛�">
- {{ currentStaffRecord.adress || '-' }}
- </el-form-item>
- </el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
@@ -135,6 +130,18 @@
/>
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="宸ヤ綔浜ゆ帴锛�" prop="remark">
+ <el-input
+ v-model="form.workTransfer"
+ type="textarea"
+ :rows="3"
+ placeholder="宸ヤ綔浜ゆ帴"
+ maxlength="500"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
</el-row>
</el-form>
@@ -186,6 +193,7 @@
leaveDate: "",
reason: "",
remark: "",
+ workTransfer: "",
},
rules: {
staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳" }],
@@ -213,6 +221,7 @@
form.value.leaveDate = row.leaveDate
form.value.reason = row.reason
form.value.remark = row.remark
+ form.value.workTransfer = row.workTransfer
personList.value = [
{
staffName: row.staffName,
diff --git a/src/views/personnelManagement/dimission/index.vue b/src/views/personnelManagement/dimission/index.vue
index 5993b3f..8889252 100644
--- a/src/views/personnelManagement/dimission/index.vue
+++ b/src/views/personnelManagement/dimission/index.vue
@@ -104,11 +104,6 @@
prop: "postName",
},
{
- label: "鐜颁綇鍧�",
- prop: "adress",
- width:200
- },
- {
label: "绗竴瀛﹀巻",
prop: "firstStudy",
},
@@ -137,6 +132,11 @@
width:150
},
{
+ label: "宸ヤ綔浜ゆ帴",
+ prop: "workTransfer",
+ width:150
+ },
+ {
dataType: "action",
label: "鎿嶄綔",
align: "center",
diff --git a/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue b/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
index 0aa4f06..08caf90 100644
--- a/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
+++ b/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
@@ -67,44 +67,61 @@
</el-form-item>
</el-col>
</el-row>
-
+ <el-row :gutter="30">
+ <el-col :span="5">
+ <el-form-item label="韬唤璇佸彿锛�"
+ prop="identityCard">
+ <el-input v-model="form.identityCard"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="钖祫锛�"
+ prop="salary">
+ <el-input v-model="form.salary"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="鍑虹敓鏃ユ湡" prop="birthDate">
+ <el-date-picker
+ v-model="form.birthDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="骞撮緞" prop="age">
+ <el-input-number
+ v-model="form.age"
+ :min="0"
+ :max="150"
+ :precision="0"
+ :step="1"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="绫嶈疮" prop="nativePlace">
+ <el-input
+ v-model="form.nativePlace"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-row :gutter="24">
- <el-col :span="5">
- <el-form-item label="鍑虹敓鏃ユ湡" prop="birthDate">
- <el-date-picker
- v-model="form.birthDate"
- type="date"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨"
- style="width: 100%"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="5">
- <el-form-item label="骞撮緞" prop="age">
- <el-input-number
- v-model="form.age"
- :min="0"
- :max="150"
- :precision="0"
- :step="1"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="5">
- <el-form-item label="绫嶈疮" prop="nativePlace">
- <el-input
- v-model="form.nativePlace"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="50"
- show-word-limit
- />
- </el-form-item>
- </el-col>
<el-col :span="5">
<el-form-item label="姘戞棌" prop="nation">
<el-input
@@ -116,7 +133,7 @@
/>
</el-form-item>
</el-col>
- <el-col :span="4">
+ <el-col :span="5">
<el-form-item label="濠氬Щ鐘跺喌" prop="maritalStatus">
<el-select
v-model="form.maritalStatus"
@@ -131,27 +148,24 @@
</el-select>
</el-form-item>
</el-col>
- </el-row>
-
- <el-row :gutter="24">
- <el-col :span="10">
- <el-form-item label="瑙掕壊" prop="roleId">
- <el-select
- v-model="form.roleId"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- >
- <el-option
- v-for="item in roleOptions"
- :key="item.roleId"
- :label="item.roleName"
- :value="item.roleId"
- :disabled="item.status == 1"
- />
- </el-select>
- </el-form-item>
- </el-col>
+ <el-col :span="5">
+ <el-form-item label="瑙掕壊" prop="roleId">
+ <el-select
+ v-model="form.roleId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in roleOptions"
+ :key="item.roleId"
+ :label="item.roleName"
+ :value="item.roleId"
+ :disabled="item.status == 1"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
</el-row>
</el-card>
</template>
diff --git a/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue b/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
index 2ad06fb..4fc7b84 100644
--- a/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
+++ b/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
@@ -111,6 +111,8 @@
hukouType: "",
email: "",
currentAddress: "",
+ identityCard: "",
+ salary: "",
// 鍦ㄨ亴淇℃伅
contractStartTime: "",
contractEndTime: "",
diff --git a/src/views/personnelManagement/employeeRecord/index.vue b/src/views/personnelManagement/employeeRecord/index.vue
index 131d37b..1b93676 100644
--- a/src/views/personnelManagement/employeeRecord/index.vue
+++ b/src/views/personnelManagement/employeeRecord/index.vue
@@ -166,6 +166,21 @@
label: "鎬у埆",
prop: "sex",
},
+ {
+ label: "韬唤璇佸彿",
+ prop: "identityCard",
+ formatData: (value) => {
+ if (!value) {
+ return "";
+ }
+ const text = String(value);
+ if (text.length <= 5) {
+ return text;
+ }
+ return text.slice(0, 5) + "*".repeat(text.length - 5);
+ },
+ width:150
+ },
{
label: "鍑虹敓鏃ユ湡",
prop: "birthDate",
@@ -298,6 +313,7 @@
tableLoading.value = true;
const params = { ...searchForm.value, ...page };
params.entryDate = undefined
+ params.staffState = 1
staffOnJobListPage({...params}).then(res => {
tableLoading.value = false;
tableData.value = res.data.records
diff --git a/src/views/procurementManagement/paymentEntry/index.vue b/src/views/procurementManagement/paymentEntry/index.vue
index 73c5a1a..342d5b3 100644
--- a/src/views/procurementManagement/paymentEntry/index.vue
+++ b/src/views/procurementManagement/paymentEntry/index.vue
@@ -21,6 +21,28 @@
@change="handleQuery"
/>
</el-form-item>
+ <el-form-item label="鐧昏鏃ユ湡">
+ <el-date-picker
+ v-model="searchForm.registrationtDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="宸蹭粯娆鹃噾棰�">
+ <el-input-number
+ v-model="searchForm.ticketsTotal"
+ :min="0"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ style="width: 180px"
+ clearable
+ @change="handleQuery"
+ />
+ </el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
</el-form-item>
@@ -322,6 +344,8 @@
status: false,
// 鍙煡璇㈠鎵圭姸鎬佷负 3 鐨勮褰�
approvalStatus: 3,
+ registrationtDate: "", // 鐧昏鏃ユ湡
+ ticketsTotal: undefined, // 宸蹭粯娆鹃噾棰�
},
form: {
purchaseContractNumber: "",
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
index b37892e..f0ea539 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -34,6 +34,17 @@
@change="getTableData"
/>
</el-form-item>
+ <el-form-item label="鏉ョエ閲戦">
+ <el-input-number
+ v-model="filters.ticketsAmount"
+ style="width: 180px"
+ placeholder="璇疯緭鍏�"
+ :min="0"
+ :precision="2"
+ clearable
+ @change="getTableData"
+ />
+ </el-form-item>
<el-form-item>
<el-button type="primary" @click="getTableData">鎼滅储</el-button>
<el-button @click="resetFilters"> 閲嶇疆 </el-button>
@@ -143,6 +154,7 @@
purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
supplierName: undefined, // 渚涘簲鍟�
createdAt: [], // 鏉ョエ鏃ユ湡
+ ticketsAmount: undefined, // 鏉ョエ閲戦
},
[
{
@@ -184,12 +196,12 @@
},
},
{
- label: "寮�绁ㄦ棩鏈�",
+ label: "鏉ョエ鏃ユ湡",
prop: "createdAt",
width: 110,
},
{
- label: "寮�绁ㄩ噾棰�",
+ label: "鏉ョエ閲戦",
prop: "ticketsAmount",
width: 200,
formatData: (cell) => {
@@ -430,7 +442,7 @@
const handleDelete = (row) => {
let ids = [];
ids.push(row.id);
- ElMessageBox.confirm("璇ュ紑绁ㄥ彴璐﹀皢琚垹闄�,鏄惁纭鍒犻櫎", {
+ ElMessageBox.confirm("璇ユ潵绁ㄥ彴璐﹀皢琚垹闄�,鏄惁纭鍒犻櫎", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 3b9dc67..25f218b 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -2,464 +2,427 @@
<div class="app-container">
<div class="search_form">
<div>
- <el-form :model="searchForm"
- :inline="true">
+ <el-form :model="searchForm" :inline="true">
<el-form-item label="渚涘簲鍟嗗悕绉帮細">
- <el-input v-model="searchForm.supplierName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
+ <el-input v-model="searchForm.supplierName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
@change="handleQuery" />
</el-form-item>
<el-form-item label="閲囪喘鍚堝悓鍙凤細">
- <el-input v-model="searchForm.purchaseContractNumber"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search" />
+ <el-input
+ v-model="searchForm.purchaseContractNumber"
+ style="width: 240px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
</el-form-item>
<el-form-item label="閿�鍞悎鍚屽彿锛�">
- <el-input v-model="searchForm.salesContractNo"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
+ <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
@change="handleQuery" />
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
+ <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+ placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
</el-form-item>
<el-form-item>
- <el-button type="primary"
- @click="handleQuery"> 鎼滅储 </el-button>
+ <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
</el-form-item>
</el-form>
</div>
+
</div>
<div class="table_list">
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
- <el-button type="primary"
- @click="openForm('add')">鏂板鍙拌处</el-button>
- <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
+ <el-button type="primary" @click="openForm('add')">鏂板鍙拌处</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- show-summary
- :summary-method="summarizeMainTable"
- @expand-change="expandChange"
- height="calc(100vh - 21.5em)">
- <el-table-column align="center"
- type="selection"
- width="55" />
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ show-summary
+ :summary-method="summarizeMainTable"
+ @expand-change="expandChange"
+ height="calc(100vh - 19em)"
+ >
+ <el-table-column align="center" type="selection" width="55" />
<el-table-column type="expand">
<template #default="props">
- <el-table :data="props.row.children"
- border
- show-summary
- :summary-method="summarizeChildrenTable">
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit" />
- <el-table-column label="鏁伴噺"
- prop="quantity" />
- <el-table-column label="鍙敤鏁伴噺"
- prop="availableQuality" />
- <el-table-column label="閫�璐ф暟閲�"
- prop="returnQuality" />
-
- <el-table-column label="绋庣巼(%)"
- prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber" />
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber" />
+ <el-table
+ :data="props.row.children"
+ border
+ show-summary
+ :summary-method="summarizeChildrenTable"
+ >
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鏁伴噺" prop="quantity" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <el-table-column
+ label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="formattedNumber"
+ />
</el-table>
</template>
</el-table-column>
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="閲囪喘鍚堝悓鍙�"
- prop="purchaseContractNumber"
- 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="瀹℃壒鐘舵��"
- prop="approvalStatus"
- width="100"
- show-overflow-tooltip>
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column
+ label="閲囪喘鍚堝悓鍙�"
+ prop="purchaseContractNumber"
+ width="200"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="閿�鍞悎鍚屽彿"
+ prop="salesContractNo"
+ width="200"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="渚涘簲鍟嗗悕绉�"
+ prop="supplierName"
+ show-overflow-tooltip
+ />
+ <el-table-column label="瀹℃壒鐘舵��"
+ prop="approvalStatus"
+ width="100"
+ show-overflow-tooltip>
+ <template #default="scope">
+ <el-tag
+ :type="getApprovalStatusType(scope.row.approvalStatus)"
+ size="small">
+ {{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="浠樻鏂瑰紡"
+ width="100"
+ prop="paymentMethod"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmount"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="褰曞叆浜�"
+ prop="recorderName"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="褰曞叆鏃ユ湡"
+ prop="entryDate"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ fixed="right"
+ label="鎿嶄綔"
+ width="100"
+ align="center"
+ >
<template #default="scope">
- <el-tag
- :type="getApprovalStatusType(scope.row.approvalStatus)"
- size="small">
- {{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="绛捐鏃ユ湡"
- prop="executionDate"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="浠樻鏂瑰紡"
- width="100"
- prop="paymentMethod"
- show-overflow-tooltip />
- <el-table-column label="鍚堝悓閲戦(鍏�)"
- prop="contractAmount"
- width="200"
- show-overflow-tooltip
- :formatter="formattedNumber" />
- <el-table-column label="褰曞叆浜�"
- prop="recorderName"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="褰曞叆鏃ユ湡"
- prop="entryDate"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="澶囨敞"
- prop="remarks"
- width="200"
- show-overflow-tooltip />
- <el-table-column fixed="right"
- label="鎿嶄綔"
- width="120"
- align="center">
- <template #default="scope">
- <el-button link
- type="primary"
- @click="openForm('edit', scope.row)"
- :disabled="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4">缂栬緫</el-button>
- <el-button link
- type="primary"
- @click="downLoadFile(scope.row)">闄勪欢</el-button>
+ <el-button
+ link
+ type="primary"
+ size="small"
+ @click="openForm('edit', scope.row)"
+ :disabled="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4"
+ >缂栬緫</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>
- <FormDialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="閲囪喘鍚堝悓鍙凤細"
- prop="purchaseContractNumber">
- <el-input v-model="form.purchaseContractNumber"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseContractNumber">
+ <el-input
+ v-model="form.purchaseContractNumber"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�"
- prop="salesLedgerId">
- <el-select v-model="form.salesLedgerId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- @change="salesLedgerChange">
- <el-option v-for="item in salesContractList"
- :key="item.id"
- :label="item.salesContractNo"
- :value="item.id" />
+ <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesLedgerId">
+ <el-select
+ v-model="form.salesLedgerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="salesLedgerChange"
+ >
+ <el-option
+ v-for="item in salesContractList"
+ :key="item.id"
+ :label="item.salesContractNo"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="渚涘簲鍟嗗悕绉帮細"
- prop="supplierId">
- <el-select v-model="form.supplierId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable>
- <el-option v-for="item in supplierList"
- :key="item.id"
- :label="item.supplierName"
- :value="item.id" >{{item.supplierName + '---' + item.supplierType}}</el-option>
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierId">
+ <el-select
+ v-model="form.supplierId"
+ placeholder="璇烽�夋嫨"
+ filterable
+ clearable
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡">
+ <el-input
+ v-model="form.paymentMethod"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.executionDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�"
- prop="executionDate">
- <el-date-picker style="width: 100%"
- v-model="form.executionDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="褰曞叆浜猴細"
- prop="recorderId">
- <el-select v-model="form.recorderId"
- placeholder="璇烽�夋嫨"
- clearable
- filterable>
- <el-option v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId" />
+ <el-form-item label="褰曞叆浜猴細" prop="recorderId">
+ <el-select
+ v-model="form.recorderId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�"
- prop="entryDate">
- <el-date-picker style="width: 100%"
- v-model="form.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable />
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
</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 :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">
- <el-button type="primary"
- @click="openProductForm('add')">娣诲姞</el-button>
- <el-button plain
- type="danger"
- @click="deleteProduct">鍒犻櫎</el-button>
+ <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
+ <el-button type="primary" @click="openProductForm('add')"
+ >娣诲姞</el-button
+ >
+ <el-button plain type="danger" @click="deleteProduct"
+ >鍒犻櫎</el-button
+ >
</el-form-item>
- <div class="select-button-group"
- 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"
- @focus="getTemplateList"
- style="width: 500px;"
- placeholder="璇烽�夋嫨妯$増鎴栬�呰緭鍏ユ柊鐨勬ā鐗堝悕绉板悗閫夋嫨"
- class="no-arrow-select">
- <el-option v-for="item in templateList"
- :key="item.id || item.value"
- :label="item.templateName"
- :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;margin-left: 8px;"
- @click="handleButtonClick"
- :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)">
- 淇濆瓨
- </el-button>
- </div>
</el-row>
- <el-table :data="productData"
- border
- @selection-change="productSelected"
- show-summary
- :summary-method="summarizeProTable">
- <el-table-column align="center"
- type="selection"
- width="55" />
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit"
- width="70" />
- <el-table-column label="鏁伴噺"
- prop="quantity"
- width="70" />
- <el-table-column label="搴撳瓨棰勮鏁伴噺"
- prop="warnNum"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="绋庣巼(%)"
- prop="taxRate"
- width="80" />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber"
- width="150" />
- <el-table-column label="鏄惁璐ㄦ"
- prop="isChecked"
- width="150">
+ <el-table
+ :data="productData"
+ border
+ @selection-change="productSelected"
+ show-summary
+ :summary-method="summarizeProTable"
+ >
+ <el-table-column align="center" type="selection" width="55" />
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" width="70" />
+ <el-table-column label="鏁伴噺" prop="quantity" width="70" />
+ <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" show-overflow-tooltip />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
+ <el-table-column
+ label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="formattedNumber"
+ width="150"
+ />
+ <el-table-column
+ label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="formattedNumber"
+ width="150"
+ />
+ <el-table-column
+ label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="formattedNumber"
+ width="150"
+ />
+ <el-table-column
+ fixed="right"
+ label="鎿嶄綔"
+ min-width="60"
+ align="center"
+ >
<template #default="scope">
- <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
- {{ scope.row.isChecked ? '鏄�' : '鍚�' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column fixed="right"
- label="鎿嶄綔"
- min-width="60"
- align="center">
- <template #default="scope">
- <el-button link
- type="primary"
- @click="openProductForm('edit', scope.row, scope.$index)">缂栬緫</el-button>
+ <el-button
+ link
+ type="primary"
+ size="small"
+ @click="openProductForm('edit', scope.row, scope.$index)"
+ >缂栬緫</el-button
+ >
</template>
</el-table-column>
</el-table>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="澶囨敞路锛�"
- prop="remarks">
- <el-input v-model="form.remarks"
- placeholder="璇疯緭鍏�"
- clearable
- type="textarea"
- :rows="2" />
+ <el-form-item label="澶囨敞路锛�" prop="remark">
+ <el-input
+ v-model="form.remark"
+ placeholder="璇疯緭鍏�"
+ clearable
+ type="textarea"
+ :rows="2"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�"
- prop="purchaseLedgerFiles">
- <el-upload v-model:file-list="fileList"
- :action="upload.url"
- multiple
- ref="fileUpload"
- auto-upload
- :headers="upload.headers"
- :before-upload="handleBeforeUpload"
- :on-error="handleUploadError"
- :on-success="handleUploadSuccess"
- :on-remove="handleRemove">
+ <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
+ <el-upload
+ v-model:file-list="fileList"
+ :action="upload.url"
+ multiple
+ ref="fileUpload"
+ auto-upload
+ :headers="upload.headers"
+ :before-upload="handleBeforeUpload"
+ :on-error="handleUploadError"
+ :on-success="handleUploadSuccess"
+ :on-remove="handleRemove"
+ >
<el-button type="primary">涓婁紶</el-button>
<template #tip>
<div class="el-upload__tip">
@@ -472,1421 +435,1013 @@
</el-col>
</el-row>
</el-form>
- </FormDialog>
- <!-- 瀵煎叆寮圭獥 -->
- <FormDialog
- v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false"
- >
- <el-upload
- ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag
- >
- <i class="el-icon-upload"></i>
- <div class="el-upload__text">
- 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
</div>
- <template #tip>
- <div class="el-upload__tip">
- 浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link type="primary" @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
- </div>
- </template>
- </el-upload>
- </FormDialog>
- <FormDialog v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
- <el-form :model="productForm"
- label-width="140px"
- label-position="top"
- :rules="productRules"
- ref="productFormRef">
+ </template>
+ </el-dialog>
+ <el-dialog
+ v-model="productFormVisible"
+ :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+ width="40%"
+ @close="closeProductDia"
+ >
+ <el-form
+ :model="productForm"
+ label-width="140px"
+ label-position="top"
+ :rules="productRules"
+ ref="productFormRef"
+ >
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="浜у搧澶х被锛�"
- prop="productId">
- <el-tree-select v-model="productForm.productId"
- placeholder="璇烽�夋嫨"
- clearable
- filterable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%" />
+ <el-form-item label="浜у搧澶х被锛�" prop="productId">
+ <el-tree-select
+ v-model="productForm.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="productModelId">
- <el-select v-model="productForm.productModelId"
- placeholder="璇烽�夋嫨"
- filterable
- clearable
- @change="getProductModel">
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select
+ v-model="productForm.productModelId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="getProductModel"
+ >
+ <el-option
+ v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍗曚綅锛�"
- prop="unit">
- <el-input v-model="productForm.unit"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input
+ v-model="productForm.unit"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绋庣巼(%)锛�" prop="taxRate">
+<!-- <el-select-->
+<!-- v-model="productForm.taxRate"-->
+<!-- placeholder="璇烽�夋嫨"-->
+<!-- clearable-->
+<!-- @change="mathNum"-->
+<!-- >-->
+<!-- <el-option label="1" value="1" />-->
+<!-- <el-option label="6" value="6" />-->
+<!-- <el-option label="13" value="13" />-->
+<!-- </el-select>-->
+ <el-input-number :step="1" :min="0" v-model="productForm.taxRate" style="width: 100%"
+ placeholder="璇疯緭鍏�" clearable @change="calculateFromTaxRate" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣/涓嶅惈绋庡崟浠�(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input-number
+ v-model="productForm.taxInclusiveUnitPrice"
+ :precision="2"
+ :step="0.1"
+ clearable
+ style="width: 100%"
+ @change="mathNum"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number
+ :step="0.1"
+ clearable
+ :precision="2"
+ style="width: 100%"
+ v-model="productForm.quantity"
+ placeholder="璇疯緭鍏�"
+ @change="mathNum"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input-number
+ v-model="productForm.taxInclusiveTotalPrice"
+ :precision="2"
+ :step="0.1"
+ clearable
+ style="width: 100%"
+ @change="reverseMathNum('taxInclusiveTotalPrice')"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绋庣巼(%)锛�"
- prop="taxRate">
- <el-select v-model="productForm.taxRate"
- placeholder="璇烽�夋嫨"
- clearable
- @change="mathNum">
- <el-option label="1"
- value="1" />
- <el-option label="6"
- value="6" />
- <el-option label="13"
- value="13" />
+ <el-form-item
+ label="涓嶅惈绋庢�讳环(鍏�)锛�"
+ prop="taxExclusiveTotalPrice"
+ >
+ <el-input
+ v-model="productForm.taxExclusiveTotalPrice"
+ @change="reverseMathNum('taxExclusiveTotalPrice')"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
+ <el-select
+ v-model="productForm.invoiceType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
</el-select>
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="搴撳瓨棰勮鏁伴噺锛�" prop="warnNum">
+ <el-input-number
+ v-model="productForm.warnNum"
+ :precision="2"
+ :step="0.1"
+ clearable
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
</el-row>
- <el-row :gutter="30">
+ </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="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="鍚◣鍗曚环(鍏�)锛�"
- prop="taxInclusiveUnitPrice">
- <el-input-number v-model="productForm.taxInclusiveUnitPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="mathNum" />
+ <el-form-item label="閲囪喘鍚堝悓鍙凤細">
+ <el-input v-model="scanForm.purchaseContractNumber" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.1"
- clearable
- :precision="2"
- :min="0"
- style="width: 100%"
- v-model="productForm.quantity"
- placeholder="璇疯緭鍏�"
- @change="mathNum" />
+ <el-form-item label="渚涘簲鍟嗗悕绉帮細">
+ <el-input v-model="scanForm.supplierName" disabled />
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30">
+ <el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�"
- prop="taxInclusiveTotalPrice">
- <el-input-number v-model="productForm.taxInclusiveTotalPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="reverseMathNum('taxInclusiveTotalPrice')" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice">
- <el-input-number v-model="productForm.taxExclusiveTotalPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="reverseMathNum('taxExclusiveTotalPrice')" />
+ <el-form-item label="鎵爜鏃堕棿锛�">
+ <el-input v-model="scanForm.scanTime" disabled />
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30">
+ <el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�"
- prop="invoiceType">
- <el-select v-model="productForm.invoiceType"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option label="澧炴櫘绁�"
- value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�"
- value="澧炰笓绁�" />
- </el-select>
+ <el-form-item label="鎵爜浜猴細">
+ <el-input v-model="scanForm.scannerName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="搴撳瓨棰勮鏁伴噺锛�"
- prop="warnNum">
- <el-input-number v-model="productForm.warnNum"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%" />
+ <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="30">
- <el-col :span="12">
- <el-form-item label="鏄惁璐ㄦ锛�"
- prop="isChecked">
- <el-radio-group v-model="productForm.isChecked">
- <el-radio label="鏄�"
- :value="true" />
- <el-radio label="鍚�"
- :value="false" />
- </el-radio-group>
+ <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>
- </FormDialog>
- <FileListDialog
- ref="fileListRef"
- v-model="fileListDialogVisible"
- title="闄勪欢鍒楄〃"
- />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitScan">纭鎵爜</el-button>
+ <el-button @click="closeScanDialog">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
- import { getToken } from "@/utils/auth";
- import pagination from "@/components/PIMTable/Pagination.vue";
- import {
- ref,
- onMounted,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
- } from "vue";
- import { Search, Delete } from "@element-plus/icons-vue";
- import { ElMessageBox, ElMessage } from "element-plus";
- import { userListNoPage } from "@/api/system/user.js";
- import FormDialog from '@/components/Dialog/FormDialog.vue';
- import FileListDialog from '@/components/Dialog/FileListDialog.vue';
- import {
- getSalesLedgerWithProducts,
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile,
- getProductInfoByContractNo,
- } from "@/api/salesManagement/salesLedger.js";
- import {
- addOrEditPurchase,
- addPurchaseTemplate,
- updatePurchaseTemplate,
- createPurchaseNo,
- delPurchase,
- getSalesNo,
- purchaseListPage,
- productList,
- getPurchaseById,
- getOptions,
- getPurchaseTemplateList,
- delPurchaseTemplate,
- } from "@/api/procurementManagement/procurementLedger.js";
- import useFormData from "@/hooks/useFormData.js";
+import { getToken } from "@/utils/auth";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, onMounted, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import {
+ getSalesLedgerWithProducts,
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInfoByContractNo,
+} from "@/api/salesManagement/salesLedger.js";
+import {
+ addOrEditPurchase,
+ delPurchase,
+ getSalesNo,
+ purchaseListPage,
+ productList,
+ getPurchaseById,
+ getOptions,
+ createPurchaseNo,
+} from "@/api/procurementManagement/procurementLedger.js";
+import useFormData from "@/hooks/useFormData.js";
+import QRCode from "qrcode";
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const productData = ref([]);
+const selectedRows = ref([]);
+const productSelectedRows = ref([]);
+const modelOptions = ref([]);
+const userList = ref([]);
+const productOptions = ref([]);
+const salesContractList = ref([]);
+const supplierList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+const fileList = ref([]);
+import useUserStore from "@/store/modules/user";
+import { modelList, productTreeList } from "@/api/basicData/product.js";
+import dayjs from "dayjs";
- const { proxy } = getCurrentInstance();
- const tableData = ref([]);
- const productData = ref([]);
- const selectedRows = ref([]);
- const productSelectedRows = ref([]);
- const modelOptions = ref([]);
- const userList = ref([]);
- const productOptions = ref([]);
- const salesContractList = ref([]);
- const supplierList = ref([]);
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
- const fileList = ref([]);
- import useUserStore from "@/store/modules/user";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import dayjs from "dayjs";
+const userStore = useUserStore();
- const userStore = useUserStore();
-
- // 瀹℃壒浜鸿妭鐐癸紙浠块攢鍞彴璐﹀彂璐у鎵逛汉锛�
- 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 = {
- 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 => {
- if (!name || name.trim() === "") {
- isTemplateNameDuplicate.value = false;
- return false;
- }
- const isDuplicate = templateList.value.some(
- item => item.templateName === name.trim()
- );
- isTemplateNameDuplicate.value = isDuplicate;
- return isDuplicate;
- };
-
- // 闃叉姈瀹氭椂鍣�
- let duplicateCheckTimer = null;
- const onTemplateFilterChange = val => {
- filterInputValue.value = val ?? "";
- // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
- if (duplicateCheckTimer) {
- clearTimeout(duplicateCheckTimer);
- }
- // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
- if (val && val.trim()) {
- duplicateCheckTimer = setTimeout(() => {
- const isDuplicate = checkTemplateNameDuplicate(val);
- if (isDuplicate) {
- ElMessage({
- message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
- type: "warning",
- duration: 2000,
- });
- }
- }, 300); // 300ms 闃叉姈
- } else {
- isTemplateNameDuplicate.value = false;
- }
- };
-
- // allow-create 鏃讹紝杈撳叆涓嶅瓨鍦ㄧ殑鍐呭浼氫綔涓� string 鍊艰繑鍥烇紱杩欓噷鍚屾鍥炶緭鍏ユ浠ョ‘淇濇枃瀛椾笉涓�
- const onTemplateChange = async val => {
- if (typeof val === "string") {
- filterInputValue.value = val;
- // 閫夋嫨鎴栬緭鍏ユ椂妫�鏌ラ噸澶�
- checkTemplateNameDuplicate(val);
- }
-
- // 杩囨护鏁版嵁锛屾煡鎵惧尮閰嶇殑妯℃澘
- const matchedTemplate = templateList.value.find(
- item => item.templateName === val
- );
-
- if (matchedTemplate?.id) {
- // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄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.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];
-
- // 濡傛灉瀵硅瘽妗嗘湭鎵撳紑锛屽厛鎵撳紑
- if (!dialogFormVisible.value) {
- operationType.value = "add";
- dialogFormVisible.value = true;
- }
-
- // 绛夊緟涓嬩竴涓� tick 鍚庢仮澶嶆暟鎹�
- await nextTick();
- form.value = {
- ...form.value,
- ...currentFormData,
- };
- productData.value = currentProductData;
- }
- };
-
- // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
- const operationType = ref("");
- const dialogFormVisible = ref(false);
- const data = reactive({
- searchForm: {
- supplierName: "", // 渚涘簲鍟嗗悕绉�
- purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- purchaseContractNumber: "",
- salesLedgerId: "",
- recorderId: "",
- entryDate: "",
- productData: [],
- supplierName: "",
- supplierId: "",
- paymentMethod: "",
- executionDate: "",
- isChecked: true,
- },
- rules: {
- purchaseContractNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- approverId: [
- { required: true, message: "璇烽�夋嫨瀹℃壒浜�", trigger: "change" },
- ],
- supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { form, rules } = toRefs(data);
- const { form: searchForm } = useFormData({
- ...data.searchForm,
- // 璁剧疆褰曞叆鏃ユ湡鑼冨洿涓哄綋澶�
- entryDate: [
- dayjs().startOf("day").format("YYYY-MM-DD"),
- dayjs().endOf("day").format("YYYY-MM-DD"),
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ supplierName: "", // 渚涘簲鍟嗗悕绉�
+ purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ form: {
+ purchaseContractNumber: "",
+ salesLedgerId: "",
+ projectName: "",
+ recorderId: "",
+ entryDate: "",
+ productData: [],
+ supplierName: "",
+ supplierId: "",
+ paymentMethod: "",
+ executionDate: "",
+ },
+ rules: {
+ purchaseContractNumber: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
],
- entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"),
- entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"),
- });
+ projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { form, rules } = toRefs(data);
+const { form: searchForm } = useFormData(data.searchForm);
- // 浜у搧琛ㄥ崟寮规鏁版嵁
- const productFormVisible = ref(false);
- const productOperationType = ref("");
- const productOperationIndex = ref("");
- const currentId = ref("");
- const productFormData = reactive({
- productForm: {
- productId: "",
- productCategory: "",
- productModelId: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- warnNum: "",
- isChecked: true,
- },
- productRules: {
- productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { productForm, productRules } = toRefs(productFormData);
- const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- });
+// 浜у搧琛ㄥ崟寮规鏁版嵁
+const productFormVisible = ref(false);
+const productOperationType = ref("");
+const productOperationIndex = ref("");
+const currentId = ref("");
+const productFormData = reactive({
+ productForm: {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ warnNum: "",
+ },
+ productRules: {
+ productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ // taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ // invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { productForm, productRules } = toRefs(productFormData);
+const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+});
+// 瀹℃壒浜鸿妭鐐癸紙浠块攢鍞彴璐﹀彂璐у鎵逛汉锛�
+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 importUploadRef = ref(null);
- const importUpload = reactive({
- title: "瀵煎叆閲囪喘鍙拌处",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: (file) => {
- const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
- return false;
- }
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
- }
- return true;
- },
- onChange: (file, fileList) => {
- // noop
- },
- onProgress: (event, file, fileList) => {
- // noop
- },
- onSuccess: (response, file, fileList) => {
- importUpload.isUploading = false;
- if (response?.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles?.();
- }
- getList();
- } else {
- proxy.$modal.msgError(response?.msg || "瀵煎叆澶辫触");
- }
- },
- onError: () => {
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
- });
+// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+const approvalStatusText = {
+ 1: "寰呭鏍�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒閫氳繃",
+ 4: "瀹℃壒澶辫触",
+};
- const handleImport = () => {
- importUpload.title = "瀵煎叆閲囪喘鍙拌处";
- importUpload.open = true;
- importUpload.isUploading = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles?.();
- }
- };
+// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+const getApprovalStatusType = (status) => {
+ const typeMap = {
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ };
+ return typeMap[status] || "info";
+};
- // 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
- const downloadTemplate = () => {
- proxy.download("/purchase/ledger/exportTemplate", {}, "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx");
- };
+const changeDaterange = (value) => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
+ }
+ handleQuery();
+};
- const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"]?.submit?.();
- };
-
- const changeDaterange = value => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
- }
- handleQuery();
- };
-
- const formattedNumber = (row, column, cellValue) => {
- return parseFloat(cellValue).toFixed(2);
- };
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
-
- // 淇濆瓨妯℃澘
- const handleButtonClick = async () => {
- // 妫�鏌ユā鏉垮悕绉版槸鍚︿负绌�
- if (!templateName.value || templateName.value.trim() === "") {
- ElMessage({
- message: "璇疯緭鍏ユā鏉垮悕绉�",
- type: "warning",
- });
- return;
- }
-
- // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
- // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
- if (!currentTemplateId.value) {
- const isDuplicate = checkTemplateNameDuplicate(templateName.value);
- if (isDuplicate) {
- ElMessage({
- message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
- type: "warning",
- });
- return;
- }
- }
-
- // 妫�鏌ヤ緵搴斿晢鏄惁閫夋嫨
- if (!form.value.supplierId) {
- 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,
- approveUserIds: approveUserIds,
- templateName: templateName.value.trim(),
- };
- 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: currentTemplateId.value ? "妯℃澘鏇存柊鎴愬姛" : "妯℃澘淇濆瓨鎴愬姛",
- type: "success",
- });
- // 淇濆瓨鎴愬姛鍚庨噸鏂拌幏鍙栨ā鏉垮垪琛�
- await getTemplateList();
- // 娓呯┖妯℃澘鍚嶇О杈撳叆
- templateName.value = "";
- filterInputValue.value = "";
- isTemplateNameDuplicate.value = false;
- // 淇濆瓨/鏇存柊瀹屾垚鍚庯紝閲嶇疆褰撳墠妯℃澘ID
- currentTemplateId.value = null;
- } else {
- ElMessage({
- message: res?.msg || "妯℃澘淇濆瓨澶辫触",
- type: "error",
- });
- }
- } catch (error) {
- console.error("淇濆瓨妯℃澘澶辫触:", error);
- ElMessage({
- message: "妯℃澘淇濆瓨澶辫触锛岃绋嶅悗閲嶈瘯",
- type: "error",
- });
- }
- };
- // 瀛愯〃鍚堣鏂规硶
- const summarizeChildrenTable = param => {
- return proxy.summarizeTable(
- param,
- [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "ticketsNum",
- "ticketsAmount",
- "futureTickets",
- "futureTicketsAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
- };
- const paginationChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const { entryDate, ...rest } = searchForm;
- purchaseListPage({ ...rest, ...page })
- .then(res => {
- tableLoading.value = false;
- // tableData.value = res.data.records;
- tableData.value = res.data.records.map(record => ({
- ...record,
- }));
- // 鍒濆鍖栧瓙鏁版嵁鏁扮粍
- tableData.value.forEach(item => {
- item.children = [];
- });
- total.value = res.data.total;
- expandedRowKeys.value = [];
- })
- .catch(() => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
- };
- const productSelected = selectedRows => {
- productSelectedRows.value = selectedRows;
- };
- const expandedRowKeys = ref([]);
- // 灞曞紑琛�
- const expandChange = async (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- const res = await productList({ salesLedgerId: row.id, type: 2 });
- const index = tableData.value.findIndex(item => item.id === row.id);
- if (index > -1) {
- tableData.value[index].children = res.data || [];
- expandedRowKeys.value.push(row.id);
- }
- } catch (error) {
- console.error("鍔犺浇浜у搧鍒楄〃澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇浜у搧鍒楄〃澶辫触");
- // 灞曞紑澶辫触鏃讹紝绉婚櫎灞曞紑鐘舵��
- const index = expandedRows.findIndex(item => item.id === row.id);
- if (index > -1) {
- expandedRows.splice(index, 1);
- }
- }
- } else {
- expandedRowKeys.value = [];
- }
- };
- // 涓昏〃鍚堣鏂规硶
- const summarizeMainTable = param => {
- return proxy.summarizeTable(param, ["contractAmount"]);
- };
- // 瀛愯〃鍚堣鏂规硶
- const summarizeProTable = param => {
- return proxy.summarizeTable(param, [
+const formattedNumber = (row, column, cellValue) => {
+ return parseFloat(cellValue).toFixed(2);
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeChildrenTable = (param) => {
+ return proxy.summarizeTable(
+ param,
+ [
"taxInclusiveUnitPrice",
"taxInclusiveTotalPrice",
"taxExclusiveTotalPrice",
- ]);
- };
- // 鎵撳紑寮规
- const openForm = async (type, row) => {
- // 缂栬緫鏃舵鏌ュ鏍哥姸鎬侊紝鍙湁寰呭鏍�(1)鍜屽鎵瑰け璐�(4)鎵嶈兘缂栬緫
- if (type === "edit" && row) {
- if (row.approvalStatus !== 1 && row.approvalStatus !== 4) {
- proxy.$modal.msgWarning("鍙湁寰呭鏍稿拰瀹℃壒澶辫触鐘舵�佺殑璁板綍鎵嶈兘缂栬緫");
- return;
- }
+ "ticketsNum",
+ "ticketsAmount",
+ "futureTickets",
+ "futureTicketsAmount",
+ ],
+ {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
}
-
- await getTemplateList();
- operationType.value = type;
- form.value = {};
- productData.value = [];
- fileList.value = [];
- templateName.value = "";
- filterInputValue.value = "";
- isTemplateNameDuplicate.value = false;
- // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
- approverNodes.value = [{ id: 1, userId: null }];
- nextApproverId = 2;
- try {
- // 骞惰鍔犺浇鍩虹鏁版嵁
- const [userRes, salesRes, supplierRes] = await Promise.all([
- userListNoPage(),
- getSalesNo(),
- getOptions(),
- ]);
-
- userList.value = userRes.data || [];
- salesContractList.value = salesRes || [];
- // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
- supplierList.value = (supplierRes.data || []).filter(
- item => item.isWhite === 0
- );
-
- // 璁剧疆榛樿鍊�
- form.value.recorderId = userStore.id;
- form.value.entryDate = getCurrentDate();
-
- if (type === "add") {
- // 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
- try {
- const purchaseNoRes = await createPurchaseNo();
- if (purchaseNoRes?.data) {
- form.value.purchaseContractNumber = purchaseNoRes.data;
- }
- } catch (error) {
- console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
- proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
- }
- } else if (type === "edit" && row?.id) {
- // 缂栬緫鏃跺姞杞芥暟鎹�
- currentId.value = row.id;
- try {
- const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
- 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("鍔犺浇鏁版嵁澶辫触");
- return;
- }
- }
-
- if (form.value.salesLedgerId == -1) {
- form.value.salesLedgerId = null;
- }
- console.log(form.value, "form.value===========");
- dialogFormVisible.value = true;
- } catch (error) {
- console.error("鎵撳紑琛ㄥ崟澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇鍩虹鏁版嵁澶辫触");
- }
- };
- // 涓婁紶鍓嶆牎妫�
- function handleBeforeUpload(file) {
- // 鏍℃鏂囦欢澶у皬
- if (file.size > 1024 * 1024 * 10) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
- return false;
- }
- proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
- return true;
- }
- // 涓婁紶澶辫触
- function handleUploadError(err) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
- proxy.$modal.closeLoading();
- }
- // 涓婁紶鎴愬姛鍥炶皟
- function handleUploadSuccess(res, file, uploadFiles) {
- proxy.$modal.closeLoading();
- if (res.code === 200) {
- file.tempId = res.data.tempId;
- proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- proxy.$refs.fileUpload.handleRemove(file);
- }
- }
- // 绉婚櫎鏂囦欢
- async function handleRemove(file) {
- if (!file?.id) {
- return;
- }
- console.log("handleRemove", file.id);
- if (file.size > 1024 * 1024 * 10) {
- // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
- return;
- }
-
- if (operationType.value === "edit" && file.id) {
- try {
- await delLedgerFile([file.id]);
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- } catch (error) {
- console.error("鍒犻櫎鏂囦欢澶辫触:", error);
- proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
- }
- }
- }
- // 鎻愪氦琛ㄥ崟
- 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) {
- // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� 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;
- }
- let tempFileIds = [];
- if (fileList.value.length > 0) {
- tempFileIds = fileList.value.map(item => item.tempId);
- }
- form.value.tempFileIds = tempFileIds;
- form.value.type = 2;
- form.value.approveUserIds = approveUserIds;
-
- // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
- if (!form.value.salesLedgerId) {
- form.value.salesContractNo = "";
- }
-
- // 鏂板鏃朵笉浼犻�抜d
- const submitData = { ...form.value };
- if (operationType.value === "add") {
- delete submitData.id;
- }
-
- addOrEditPurchase(submitData).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
- approverNodes.value = [{ id: 1, userId: null }];
- nextApproverId = 2;
- dialogFormVisible.value = false;
- };
- // 鎵撳紑浜у搧寮规
- const openProductForm = async (type, row, index) => {
- productOperationType.value = type;
- productOperationIndex.value = index;
- productForm.value = {};
- proxy.resetForm("productFormRef");
- productFormVisible.value = true;
-
- // 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
- 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 = () => {
- return productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
- return res;
- });
- };
- const getModels = value => {
- if (value) {
- productForm.value.productCategory =
- findNodeById(productOptions.value, value) || "";
- return modelList({ id: value }).then(res => {
- modelOptions.value = res;
- return res;
+ );
+};
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ purchaseListPage({ ...rest, ...page })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ tableData.value.map((item) => {
+ item.children = [];
});
- } else {
- productForm.value.productCategory = "";
- modelOptions.value = [];
- return Promise.resolve([]);
- }
- };
- const getProductModel = value => {
- const index = modelOptions.value.findIndex(item => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
- } else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
- }
- };
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
- }
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitProduct = () => {
- proxy.$refs["productFormRef"].validate(valid => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if (productOperationType.value === "add") {
- productData.value.push({ ...productForm.value });
- console.log("productData.value---", productData.value);
- } else {
- productData.value[productOperationIndex.value] = {
- ...productForm.value,
- };
- }
- closeProductDia();
- }
- }
- });
- };
- const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 2;
- addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getPurchaseById({ id: currentId.value, type: 2 }).then(res => {
- productData.value = res.productData;
- });
- });
- };
- // 鍒犻櫎浜у搧
- const deleteProduct = () => {
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- if (operationType.value === "add") {
- productSelectedRows.value.forEach(selectedRow => {
- const index = productData.value.findIndex(
- product => product.id === selectedRow.id
- );
- if (index !== -1) {
- productData.value.splice(index, 1);
- }
- });
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map(item => item.id);
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delProduct(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getPurchaseById({ id: currentId.value, type: 2 }).then(
- res => {
- productData.value = res.productData;
- }
- );
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- }
- };
- // 鍏抽棴浜у搧寮规
- const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
- };
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
+ total.value = res.data.total;
+ expandedRowKeys.value = [];
})
- .then(() => {
- proxy.download("/purchase/ledger/export", {}, "閲囪喘鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
- // 鍒犻櫎
- const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.filter(item => item.salesLedgerId === null).map(item => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delPurchase(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
- // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
- function getCurrentDate() {
- const today = new Date();
- const year = today.getFullYear();
- const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
- const day = String(today.getDate()).padStart(2, "0");
- return `${year}-${month}-${day}`;
- }
- const mathNum = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (!productForm.value.taxInclusiveUnitPrice) {
- return;
- }
- if (!productForm.value.quantity) {
- return;
- }
- // 鍚◣鎬讳环璁$畻
- productForm.value.taxInclusiveTotalPrice =
- proxy.calculateTaxIncludeTotalPrice(
- productForm.value.taxInclusiveUnitPrice,
- productForm.value.quantity
- );
- if (productForm.value.taxRate) {
- // 涓嶅惈绋庢�讳环璁$畻
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
- };
- const reverseMathNum = field => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- const taxRate = Number(productForm.value.taxRate);
- if (!taxRate) return;
-
- // 纭繚杈撳叆鍊间笉涓鸿礋鏁�
- if (
- field === "taxInclusiveTotalPrice" ||
- field === "taxExclusiveTotalPrice"
- ) {
- const value = Number(productForm.value[field]);
- if (value < 0) {
- productForm.value[field] = "0";
- proxy.$modal.msgWarning("鍊间笉鑳藉皬浜�0");
- return;
- }
- }
-
- if (field === "taxInclusiveTotalPrice") {
- // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
- if (productForm.value.quantity) {
- productForm.value.taxInclusiveUnitPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.quantity)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
- productForm.value.taxInclusiveUnitPrice = "0";
- }
- }
- // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
- else if (productForm.value.taxInclusiveUnitPrice) {
- productForm.value.quantity = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.taxInclusiveUnitPrice)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.quantity) < 0) {
- productForm.value.quantity = "0";
- }
- }
- // 鍙嶇畻涓嶅惈绋庢�讳环
- productForm.value.taxExclusiveTotalPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- (1 + taxRate / 100)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxExclusiveTotalPrice) < 0) {
- productForm.value.taxExclusiveTotalPrice = "0";
- }
- } else if (field === "taxExclusiveTotalPrice") {
- // 鍙嶇畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (
- Number(productForm.value.taxExclusiveTotalPrice) *
- (1 + taxRate / 100)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveTotalPrice) < 0) {
- productForm.value.taxInclusiveTotalPrice = "0";
- }
- // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
- if (productForm.value.quantity) {
- productForm.value.taxInclusiveUnitPrice = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.quantity)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
- productForm.value.taxInclusiveUnitPrice = "0";
- }
- }
- // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
- else if (productForm.value.taxInclusiveUnitPrice) {
- productForm.value.quantity = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.taxInclusiveUnitPrice)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.quantity) < 0) {
- productForm.value.quantity = "0";
- }
- }
- }
- };
- // 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
- const salesLedgerChange = async row => {
- console.log("row", row);
- var index = salesContractList.value.findIndex(item => item.id == row);
- console.log("index", index);
- if (index > -1) {
- await querygProductInfoByContractNo();
- }
- };
-
- const querygProductInfoByContractNo = async () => {
- const { code, data } = await getProductInfoByContractNo({
- contractNo: form.value.salesLedgerId,
+ .catch(() => {
+ tableLoading.value = false;
});
- if (code == 200) {
- productData.value = data;
- }
- };
-
- const fileListRef = ref(null);
- const fileListDialogVisible = ref(false);
- const downLoadFile = row => {
- if (fileListRef.value) {
- fileListRef.value.open(row.salesLedgerFiles);
- }
- };
-
- // 鑾峰彇妯℃澘淇℃伅
- const getTemplateList = async () => {
- 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;
- }
-
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const productSelected = (selectedRows) => {
+ productSelectedRows.value = selectedRows;
+};
+const expandedRowKeys = ref([]);
+// 灞曞紑琛�
+const expandChange = (row, expandedRows) => {
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
try {
- await ElMessageBox.confirm(
- `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
- "鍒犻櫎纭",
- {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
+ productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
+ const index = tableData.value.findIndex((item) => item.id === row.id);
+ if (index > -1) {
+ tableData.value[index].children = res.data;
}
- );
-
- 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",
- });
- }
+ expandedRowKeys.value.push(row.id);
+ });
} catch (error) {
- if (error !== "cancel") {
- console.error("鍒犻櫎妯℃澘澶辫触:", error);
- ElMessage({
- message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
- type: "error",
- });
- }
+ console.log(error);
}
- };
-
- onMounted(() => {
- getList();
- getTemplateList();
+ } else {
+ expandedRowKeys.value = [];
+ }
+};
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = (param) => {
+ return proxy.summarizeTable(param, ["contractAmount"]);
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeProTable = (param) => {
+ return proxy.summarizeTable(param, [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ fileList.value = [];
+ if (operationType.value == "add") {
+ createPurchaseNo().then((res) => {
+ form.value.purchaseContractNumber = res.data;
+ });
+ }
+ userListNoPage().then((res) => {
+ userList.value = res.data;
});
+ getSalesNo().then((res) => {
+ salesContractList.value = res;
+ });
+ getOptions().then((res) => {
+ supplierList.value = res.data;
+ });
+ form.value.recorderId = userStore.id;
+ form.value.entryDate = getCurrentDate();
+ if (type === "edit") {
+ currentId.value = row.id;
+ getPurchaseById({ id: row.id, type: 2 }).then((res) => {
+ form.value = { ...res };
+ productData.value = form.value.productData;
+ if (form.value.salesLedgerFiles) {
+ fileList.value = form.value.salesLedgerFiles;
+ } else {
+ fileList.value = [];
+ }
+ });
+ }
+ dialogFormVisible.value = true;
+};
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+ // 鏍℃鏂囦欢澶у皬
+ if (file.size > 1024 * 1024 * 10) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+ return false;
+ }
+ proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+ return true;
+}
+// 涓婁紶澶辫触
+function handleUploadError(err) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+ proxy.$modal.closeLoading();
+}
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file, uploadFiles) {
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
+}
+// 绉婚櫎鏂囦欢
+function handleRemove(file) {
+ console.log("handleRemove", file.id);
+ if (file.size > 1024 * 1024 * 10) {
+ // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
+ return;
+ }
+ if (operationType.value === "edit") {
+ let ids = [];
+ ids.push(file.id);
+ delLedgerFile(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ });
+ }
+}
+// 鎻愪氦琛ㄥ崟
+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);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ let tempFileIds = [];
+ if (fileList.value.length > 0) {
+ tempFileIds = fileList.value.map((item) => item.tempId);
+ }
+ form.value.tempFileIds = tempFileIds;
+ form.value.type = 2;
+ form.value.approveUserIds = approveUserIds;
+ addOrEditPurchase(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 鎵撳紑浜у搧寮规
+const openProductForm = (type, row, index) => {
+ productOperationType.value = type;
+ productOperationIndex.value = index;
+ productForm.value = {};
+ proxy.resetForm("productFormRef");
+ if (type === "edit") {
+ productForm.value = { ...row };
+ }
+ productFormVisible.value = true;
+ getProductOptions();
+};
+const getProductOptions = () => {
+ productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ });
+};
+const getModels = (value) => {
+ if (value) {
+ productForm.value.productCategory = findNodeById(productOptions.value, value) || "";
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ });
+ } else {
+ productForm.value.productCategory = "";
+ modelOptions.value = [];
+ }
+};
+const getProductModel = (value) => {
+ const index = modelOptions.value.findIndex((item) => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ } else {
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ }
+};
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+function convertIdToValue(data) {
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitProduct = () => {
+ proxy.$refs["productFormRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitProductEdit();
+ } else {
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ console.log("productData.value---", productData.value);
+ } else {
+ productData.value[productOperationIndex.value] = {
+ ...productForm.value,
+ };
+ }
+ closeProductDia();
+ }
+ }
+ });
+};
+const submitProductEdit = () => {
+ productForm.value.salesLedgerId = currentId.value;
+ productForm.value.type = 2;
+ addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ getPurchaseById({ id: currentId.value, type: 2 }).then((res) => {
+ productData.value = res.productData;
+ });
+ });
+};
+// 鍒犻櫎浜у搧
+const deleteProduct = () => {
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ if (operationType.value === "add") {
+ productSelectedRows.value.forEach((selectedRow) => {
+ const index = productData.value.findIndex(
+ (product) => product.id === selectedRow.id
+ );
+ if (index !== -1) {
+ productData.value.splice(index, 1);
+ }
+ });
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map((item) => item.id);
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delProduct(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then(
+ (res) => {
+ productData.value = res.productData;
+ }
+ );
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ }
+};
+// 鍏抽棴浜у搧寮规
+const closeProductDia = () => {
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/purchase/ledger/export", {}, "閲囪喘鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delPurchase(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+// 绋庣巼鍙兘涓虹┖锛氳繑鍥� number 鎴� null
+const getTaxRateNumberOrNull = () => {
+ const raw = productForm.value?.taxRate;
+ if (raw === null || raw === undefined || raw === "") return null;
+ const n = Number(raw);
+ return Number.isFinite(n) ? n : null;
+};
+const mathNum = () => {
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
+ );
+
+ // 涓嶅惈绋庢�讳环璁$畻锛堢◣鐜囧彲鑳戒负绌猴級
+ const taxRate = getTaxRateNumberOrNull();
+ if (taxRate === null) {
+ // 鏈~鍐欑◣鐜囨椂锛氭寜鈥滃惈绋�/涓嶅惈绋庝竴鑷粹�濆鐞嗭紝閬垮厤鍑虹幇 NaN
+ productForm.value.taxExclusiveTotalPrice = productForm.value.taxInclusiveTotalPrice;
+ } else {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ taxRate
+ );
+ }
+ // if (productForm.value.taxRate) {
+ // // 涓嶅惈绋庢�讳环璁$畻
+ // productForm.value.taxExclusiveTotalPrice =
+ // proxy.calculateTaxExclusiveTotalPrice(
+ // productForm.value.taxInclusiveTotalPrice,
+ // productForm.value.taxRate
+ // );
+ // }
+};
+const reverseMathNum = (field) => {
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ const taxRate = getTaxRateNumberOrNull();
+ if (field === 'taxInclusiveTotalPrice') {
+ // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice =
+ (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
+ }
+ // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity =
+ (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
+ }
+ // 鍙嶇畻涓嶅惈绋庢�讳环锛堢◣鐜囧彲鑳戒负绌猴級
+ if (taxRate === null) {
+ productForm.value.taxExclusiveTotalPrice = productForm.value.taxInclusiveTotalPrice;
+ } else {
+ productForm.value.taxExclusiveTotalPrice =
+ (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2);
+ }
+ } else if (field === 'taxExclusiveTotalPrice') {
+ // 鍙嶇畻鍚◣鎬讳环锛堢◣鐜囧彲鑳戒负绌猴級
+ if (taxRate === null) {
+ productForm.value.taxInclusiveTotalPrice = productForm.value.taxExclusiveTotalPrice;
+ } else {
+ productForm.value.taxInclusiveTotalPrice =
+ (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2);
+ }
+ // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice =
+ (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
+ }
+ // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity =
+ (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
+ }
+ }
+};
+// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
+const salesLedgerChange = async (row) => {
+ console.log("row", row);
+ var index = salesContractList.value.findIndex((item) => item.id == row);
+ console.log("index", index);
+ if (index > -1) {
+ form.value.projectName = salesContractList.value[index].projectName;
+ await querygProductInfoByContractNo();
+ }
+};
+
+const querygProductInfoByContractNo = async () => {
+ const { code, data } = await getProductInfoByContractNo({
+ contractNo: form.value.salesLedgerId,
+ });
+ if (code == 200) {
+ productData.value = data;
+ }
+};
+
+// 鎵爜鐧昏瀵硅瘽妗嗙浉鍏冲彉閲�
+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 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}`;
+}
+
+
+
+onMounted(() => {
+ getList();
+});
</script>
<style scoped lang="scss">
diff --git a/src/views/salesManagement/invoiceLedger/index.vue b/src/views/salesManagement/invoiceLedger/index.vue
index 3827854..2eadd25 100644
--- a/src/views/salesManagement/invoiceLedger/index.vue
+++ b/src/views/salesManagement/invoiceLedger/index.vue
@@ -18,6 +18,9 @@
<el-form-item label="涓嶆樉绀烘湁鍙戠エ琛�">
<el-checkbox v-model="searchForm.status" @change="handleQuery" />
</el-form-item>
+ <el-form-item label="鍙戠エ閲戦">
+ <el-input-number v-model="searchForm.invoiceTotal" :min="0" :precision="2" placeholder="璇疯緭鍏�" style="width: 180px" @change="handleQuery" />
+ </el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
<el-button @click="resetForm"> 閲嶇疆 </el-button>
@@ -178,6 +181,7 @@
invoiceDateStart: undefined,
invoiceDateEnd: undefined,
createTimeStart: "", // 褰曞叆鏃ユ湡
+ invoiceTotal: undefined, // 鍙戠エ閲戦
},
form: {
salesLedgerId: "",
@@ -203,7 +207,19 @@
},
});
const { form, rules } = toRefs(data);
-const { form: searchForm, resetForm } = useFormData(data.searchForm);
+const { form: searchForm } = useFormData(data.searchForm);
+
+// 鑷畾涔夐噸缃嚱鏁�
+const resetForm = () => {
+ searchForm.searchText = "";
+ searchForm.status = false;
+ searchForm.invoiceDate = null;
+ searchForm.invoiceDateStart = undefined;
+ searchForm.invoiceDateEnd = undefined;
+ searchForm.createTimeStart = "";
+ searchForm.invoiceTotal = undefined;
+ handleQuery();
+};
const currentId = ref("");
const userStore = useUserStore();
const maxInvoiceAmount = ref(0); // 鍙戠エ閲戦鏈�澶у��
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 0ae1a21..382a1cd 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -14,6 +14,10 @@
<el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
</el-form-item>
+ <el-form-item label="浜у搧澶х被锛�">
+ <el-input v-model="searchForm.productCategory" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
</el-form-item>
@@ -26,80 +30,27 @@
<el-button type="primary" @click="openForm('add')">
鏂板鍙拌处
</el-button>
- <el-button type="primary" plain @click="handleImport">瀵煎叆</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>
<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" :row-class-name="tableRowClassName" show-summary style="width: 100%"
+ :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%"
:summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
- <el-table-column align="center" type="selection" width="55" fixed="left"/>
- <el-table-column type="expand" width="60" fixed="left">
+ <el-table-column align="center" type="selection" width="55" />
+ <el-table-column type="expand">
<template #default="props">
- <el-table :data="props.row.children" border show-summary :summary-method="(param) => summarizeChildrenTable(param, props.row)">
- <el-table-column align="center" label="搴忓彿" type="index"/>
+ <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
<el-table-column label="浜у搧澶х被" prop="productCategory" />
<el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
<el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="浜у搧鐘舵��"
- width="100px"
- align="center">
- <template #default="scope">
-
- <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
- type="success">鍏呰冻</el-tag>
- <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
- type="success">宸插嚭搴�</el-tag>
- <el-tag v-else type="danger">涓嶈冻</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="鍙戣揣鐘舵��" width="140" align="center">
- <template #default="scope">
- <el-tag :type="getShippingStatusType(scope.row)" size="small">
- {{ getShippingStatusText(scope.row) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
- <el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
- <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
- <template #default="scope">
- <div>
- <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
- <el-tag v-else type="info">-</el-tag>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="鍙戣揣鏃ユ湡"
- minWidth="100px"
- align="center">
- <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>
<el-table-column label="鏁伴噺" prop="quantity" />
<el-table-column label="绋庣巼(%)" prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="sensitiveAmountFormatter" />
- <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="sensitiveAmountFormatter" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="sensitiveAmountFormatter" />
- <!--鎿嶄綔-->
- <el-table-column Width="60px" label="鎿嶄綔" align="center">
- <template #default="scope">
- <el-button
- link
- type="primary"
- :disabled="!canShip(scope.row)"
- @click="openDeliveryForm(scope.row)">
- 鍙戣揣
- </el-button>
- </template>
- </el-table-column>
+ <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
</el-table>
</template>
</el-table-column>
@@ -107,35 +58,63 @@
<el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" width="180" show-overflow-tooltip />
<el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" width="300" show-overflow-tooltip />
<el-table-column label="涓氬姟鍛�" prop="salesman" width="100" show-overflow-tooltip />
+ <el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" width="100" align="center" show-overflow-tooltip>
+ <template #default="scope">
+ <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)" size="small">
+ {{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
+ </el-tag>
+ </template>
+ </el-table-column>
<el-table-column label="浠樻鏂瑰紡" prop="paymentMethod" show-overflow-tooltip />
<el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" width="220" show-overflow-tooltip
:formatter="formattedNumber" />
<el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
<el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
<el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
- <el-table-column label="浜や粯鏃ユ湡" prop="deliveryDate" width="120" show-overflow-tooltip />
- <el-table-column label="澶囨敞" prop="remarks" width="200" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" width="130" align="center">
+ <el-table-column label="鍙戣揣鐘舵��" prop="shippingStatus" width="140" align="center" show-overflow-tooltip />
+ <el-table-column label="鍙戣揣鏃ユ湡" prop="shippingDate" width="140" align="center" show-overflow-tooltip />
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="140" align="center">
<template #default="scope">
- <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">缂栬緫</el-button>
- <el-button link type="primary" @click="downLoadFile(scope.row)">闄勪欢</el-button>
+ <el-button
+ link
+ type="primary"
+ size="small"
+ @click="openForm('edit', scope.row)"
+ :disabled="scope.row.approvalStatus === 3 && scope.row.entryPerson !== userStore.id"
+ >缂栬緫</el-button>
+ <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">闄勪欢</el-button>
+ <el-button
+ link
+ type="primary"
+ size="small"
+ @click="openDeliveryForm(scope.row)"
+ :disabled="scope.row.shippingStatus === '宸插彂璐�'"
+ >
+ 鍙戣揣
+ </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" />
</div>
- <FormDialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'" :width="'70%'"
- :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia">
+ <FormDialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'"
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
<el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
<!-- 鎶ヤ环鍗曞鍏ュ叆鍙o細鏀惧湪琛ㄥ崟椤堕儴锛岄�夋嫨鍚庡弽鏄惧鎴�/涓氬姟鍛樼瓑 -->
- <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;">
- <el-col :span="24" style="text-align: right;">
- <el-button type="primary" plain @click="openQuotationDialog">
- 浠庨攢鍞姤浠峰鍏�
- </el-button>
- </el-col>
- </el-row>
+<!-- <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;">-->
+<!-- <el-col :span="24" style="text-align: right;">-->
+<!-- <el-button type="primary" plain @click="openQuotationDialog">-->
+<!-- 浠庨攢鍞姤浠峰鍏�-->
+<!-- </el-button>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
@@ -144,7 +123,9 @@
</el-col>
<el-col :span="12">
<el-form-item label="涓氬姟鍛橈細" prop="salesman">
- <el-select v-model="form.salesman" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" filterable>
+ <el-select v-model="form.salesman"
+ filterable
+ :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
:value="item.nickName" />
</el-select>
@@ -157,220 +138,194 @@
<el-select v-model="form.customerId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" filterable>
<el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
{{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
+ item.customerName+'-'+item.customerType
}}
</el-option>
</el-select>
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="30">
<el-col :span="12">
<el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
<el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
+ </el-row>
+ <el-row :gutter="30">
<el-col :span="12">
<el-form-item label="褰曞叆浜猴細" prop="entryPerson">
<el-select v-model="form.entryPerson"
filterable
- default-first-option
- :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable @change="changs">
+ default-first-option
+ :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable @change="changs">
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
- <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
- type="date" placeholder="璇烽�夋嫨" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浜よ揣鏃ユ湡锛�" prop="entryDate">
- <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
- type="date" placeholder="璇烽�夋嫨" clearable />
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
+ type="date" placeholder="璇烽�夋嫨" clearable />
</el-form-item>
</el-col>
</el-row>
- <el-row>
- <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
- <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
- <el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >鍒犻櫎</el-button>
- </el-form-item>
- </el-row>
- <el-table :data="productData" border @selection-change="productSelected" show-summary
- :summary-method="summarizeMainTable">
- <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'"
- :selectable="(row) => !isProductShipped(row)" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="鏁伴噺" prop="quantity" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
- <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center" v-if="operationType !== 'view'">
- <template #default="scope">
- <el-button link type="primary" size="small"
- :disabled="isProductShipped(scope.row)"
- @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
- </template>
- </el-table-column>
- </el-table>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="澶囨敞锛�" prop="remarks">
- <el-input v-model="form.remarks" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�" prop="salesLedgerFiles">
- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
- :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
- :on-success="handleUploadSuccess" :on-remove="handleRemove">
- <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>
- <template #tip v-if="operationType !== 'view'">
- <div class="el-upload__tip">
- 鏂囦欢鏍煎紡鏀寔
- doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
- </div>
- </template>
- </el-upload>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </FormDialog>
-
- <!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
- <el-dialog
- v-model="quotationDialogVisible"
- title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
- width="80%"
- :close-on-click-modal="false"
- >
- <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
- <el-input
- v-model="quotationSearchForm.quotationNo"
- placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList"
- />
- <el-input
- v-model="quotationSearchForm.customer"
- placeholder="璇疯緭鍏ュ鎴峰悕绉�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList"
- />
- <el-button type="primary" @click="fetchQuotationList">鎼滅储</el-button>
- <el-button @click="resetQuotationSearch">閲嶇疆</el-button>
- </div>
-
- <el-table
- :data="quotationList"
- border
- stripe
- v-loading="quotationLoading"
- height="420px"
- >
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" width="180" show-overflow-tooltip />
- <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" min-width="220" show-overflow-tooltip />
- <el-table-column prop="salesperson" label="涓氬姟鍛�" width="120" show-overflow-tooltip />
- <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="140" />
- <el-table-column prop="status" label="瀹℃壒鐘舵��" width="120" align="center" />
- <el-table-column prop="totalAmount" label="鎶ヤ环閲戦(鍏�)" width="160" align="right">
- <template #default="scope">
- {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
- </template>
- </el-table-column>
- <el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
- <template #default="scope">
- <el-button type="primary" link @click="applyQuotation(scope.row)">閫夋嫨</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <pagination
- v-show="quotationPage.total > 0"
- :total="quotationPage.total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="quotationPage.current"
- :limit="quotationPage.size"
- @pagination="quotationPaginationChange"
- />
-
- <template #footer>
- <el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
- </template>
- </el-dialog>
- <FormDialog
- v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
- <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
- <el-tree-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable filterable check-strictly
- @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
- <el-select v-model="productForm.productModelId" placeholder="璇烽�夋嫨" clearable @change="getProductModel" filterable>
- <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍗曚綅锛�" prop="unit">
- <el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡">
+ <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
+ </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 v-if="operationType !== 'view'" 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 && operationType !== 'view'"
+ type="danger"
+ size="small"
+ text
+ @click="removeApproverNode(index)"
+ icon="Delete"
+ >鍒犻櫎</el-button>
+ </div>
+ <el-select
+ v-model="node.userId"
+ placeholder="璇烽�夋嫨瀹℃壒浜�"
+ filterable
+ style="width: 100%;"
+ :disabled="operationType === 'view'"
+ >
+ <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">
+ <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
+ <el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >鍒犻櫎</el-button>
+ </el-form-item>
+ </el-row>
+ <el-table :data="productData" border @selection-change="productSelected" show-summary
+ :summary-method="summarizeMainTable">
+ <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'" />
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鏁伴噺" prop="quantity" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center" v-if="operationType !== 'view'">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞路锛�" prop="remark">
+ <el-input v-model="form.remark" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
+ <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
+ :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
+ :on-success="handleUploadSuccess" :on-remove="handleRemove">
+ <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>
+ <template #tip v-if="operationType !== 'view'">
+ <div class="el-upload__tip">
+ 鏂囦欢鏍煎紡鏀寔
+ doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </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>
+ </FormDialog>
+ <el-dialog v-model="productFormVisible" :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'" width="40%"
+ @close="closeProductDia">
+ <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
+ <!-- <el-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable>
+ <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
+ </el-select> -->
+ <el-tree-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable check-strictly
+ @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select v-model="productForm.productModelId" placeholder="璇烽�夋嫨" clearable @change="getProductModel">
+ <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
<el-col :span="12">
<el-form-item label="绋庣巼(%)锛�" prop="taxRate">
- <el-select v-model="productForm.taxRate" placeholder="璇烽�夋嫨" clearable @change="calculateFromTaxRate">
- <el-option label="1" value="1" />
- <el-option label="6" value="6" />
- <el-option label="13" value="13" />
- </el-select>
+<!-- <el-select v-model="productForm.taxRate" placeholder="璇烽�夋嫨" clearable @change="calculateFromTaxRate">-->
+<!-- <el-option label="1" value="1" />-->
+<!-- <el-option label="6" value="6" />-->
+<!-- <el-option label="13" value="13" />-->
+<!-- </el-select>-->
+ <el-input-number :step="1" :min="0" v-model="productForm.taxRate" style="width: 100%"
+ placeholder="璇疯緭鍏�" clearable @change="calculateFromTaxRate" />
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
- <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣/涓嶅惈绋庡崟浠�(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
:precision="2"
placeholder="璇疯緭鍏�" clearable @change="calculateFromUnitPrice" />
- </el-form-item>
- </el-col>
+ </el-form-item>
+ </el-col>
<el-col :span="12">
<el-form-item label="鏁伴噺锛�" prop="quantity">
<el-input-number :step="0.1" :min="0" v-model="productForm.quantity" placeholder="璇疯緭鍏�" clearable
@@ -378,72 +333,37 @@
@change="calculateFromQuantity" style="width: 100%" />
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
- <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromTotalPrice" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
- <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromExclusiveTotalPrice" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
- <el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </FormDialog>
- <!-- 瀵煎叆寮圭獥 -->
- <FormDialog
- v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false"
- >
- <el-upload
- ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag
- >
- <i class="el-icon-upload"></i>
- <div class="el-upload__text">
- 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
- </div>
- <template #tip>
- <div class="el-upload__tip">
- 浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link type="primary" @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
- </div>
- </template>
- </el-upload>
- </FormDialog>
- <!-- 闄勪欢鍒楄〃寮圭獥 -->
- <FileListDialog
- ref="fileListRef"
- v-model="fileListDialogVisible"
- title="闄勪欢鍒楄〃"
- />
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromTotalPrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
+ <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromExclusiveTotalPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
+ <el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
+ <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
+ </el-select>
+ </el-form-item>
+ </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="printPreviewVisible"
@@ -467,9 +387,10 @@
<div v-for="(item, index) in printData" :key="index" class="print-page">
<div class="delivery-note">
<div class="header">
+ <div class="company-name">闈掓捣婀熸按宄″啘涓氬彂灞曟湁闄愬叕鍙�</div>
<div class="document-title">闆跺敭鍙戣揣鍗�</div>
</div>
-
+
<div class="info-section">
<div class="info-row">
<div>
@@ -484,7 +405,7 @@
<div class="info-row">
<div>
<span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">{{ item.customerName }}</span>
+ <span class="value">{{ item.customerName || '寮犵埍鏈�' }}</span>
</div>
<span class="label">鍗曞彿锛�</span>
<span class="value">{{ item.salesContractNo }}</span>
@@ -564,7 +485,7 @@
<el-dialog
v-model="deliveryFormVisible"
title="鍙戣揣淇℃伅"
- width="40%"
+ width="40%"
@close="closeDeliveryDia"
>
<el-form :model="deliveryForm" label-width="120px" label-position="top" :rules="deliveryRules" ref="deliveryFormRef">
@@ -575,6 +496,7 @@
v-model="deliveryForm.type"
placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
style="width: 100%"
+ @change="handleShippingTypeChange"
>
<el-option label="璐ц溅" value="璐ц溅" />
<el-option label="蹇��" value="蹇��" />
@@ -582,50 +504,81 @@
</el-form-item>
</el-col>
</el-row>
-
- <!-- 瀹℃壒浜洪�夋嫨锛堜豢鍗忓悓瀹℃壒閲岀殑瀹℃壒浜鸿妭鐐归�夋嫨锛� -->
- <el-row>
- <el-col :span="24">
- <el-form-item>
- <template #label>
- <span>瀹℃壒浜洪�夋嫨锛�</span>
- <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">鏂板鑺傜偣</el-button>
- </template>
- <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
- <div
- v-for="(node, index) in approverNodes"
- :key="node.id"
- style="margin-right: 20px; text-align: center; margin-bottom: 10px;"
- >
- <div>
- <span>瀹℃壒浜�</span>
- 鈫�
- </div>
- <el-select
- v-model="node.userId"
- placeholder="閫夋嫨浜哄憳"
- filterable
- style="width: 140px; margin-bottom: 8px;"
- >
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
- </el-select>
- <div>
- <el-button
- type="danger"
- @click="removeApproverNode(index)"
- v-if="approverNodes.length > 1"
- >鍒犻櫎</el-button>
- </div>
- </div>
- </div>
- </el-form-item>
- </el-col>
- </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍙戣揣鏃ユ湡锛�" prop="shippingDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="deliveryForm.shippingDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨鍙戣揣鏃ユ湡"
+ clearable
+ />
+ </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="鍙戣揣鍥剧墖锛�">
+ <el-upload
+ v-model:file-list="deliveryFileList"
+ :action="upload.url"
+ multiple
+ ref="deliveryFileUpload"
+ auto-upload
+ :headers="upload.headers"
+ :data="{ type: 9 }"
+ :before-upload="handleDeliveryBeforeUpload"
+ :on-error="handleDeliveryUploadError"
+ :on-success="handleDeliveryUploadSuccess"
+ :on-remove="handleDeliveryRemove"
+ list-type="picture-card"
+ :limit="9"
+ accept="image/png,image/jpeg,image/jpg"
+ >
+ <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
+ <template #tip>
+ <div class="el-upload__tip">
+ 鏀寔 jpg銆乯peg銆乸ng 鏍煎紡锛屾渶澶氫笂浼� 9 寮狅紝鍗曞紶澶у皬涓嶈秴杩� 10MB
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </el-col>
+ </el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
@@ -634,7 +587,64 @@
</div>
</template>
</el-dialog>
- </div>
+ <!-- 閿�鍞姤浠峰崟閫夋嫨瀵硅瘽妗� -->
+ <el-dialog
+ v-model="quotationDialogVisible"
+ title="閫夋嫨閿�鍞姤浠峰崟"
+ width="80%"
+ :close-on-click-modal="false"
+ @close="resetQuotationSearch"
+ >
+ <div class="search_form" style="margin-bottom: 15px;">
+ <el-form :model="quotationSearchForm" :inline="true">
+ <el-form-item label="鎶ヤ环鍗曞彿锛�">
+ <el-input v-model="quotationSearchForm.quotationNo" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ <el-form-item label="瀹㈡埛锛�">
+ <el-input v-model="quotationSearchForm.customer" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="fetchQuotationList">鎼滅储</el-button>
+ <el-button @click="resetQuotationSearch">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ <el-table
+ :data="quotationList"
+ border
+ v-loading="quotationLoading"
+ height="400"
+ style="width: 100%"
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="鎶ヤ环鍗曞彿" prop="quotationNo"show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛" prop="customer" show-overflow-tooltip />
+ <el-table-column label="涓氬姟鍛�" prop="salesperson" show-overflow-tooltip />
+ <el-table-column label="鎶ヤ环鏃ユ湡" prop="quotationDate" show-overflow-tooltip />
+ <el-table-column label="鐘舵��" prop="status" width="100" align="center">
+ <template #default="scope">
+ <el-tag v-if="scope.row.status === '閫氳繃'" type="success" size="small">宸查�氳繃</el-tag>
+ <el-tag v-else type="info" size="small">{{ scope.row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="100" align="center" fixed="right">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="applyQuotation(scope.row)">閫夋嫨</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination
+ v-show="quotationPage.total > 0"
+ :total="quotationPage.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="quotationPage.current"
+ :limit="quotationPage.size"
+ style="margin-bottom: 15px;"
+ @pagination="quotationPaginationChange"
+ />
+ </el-dialog>
+ <FileList ref="fileListRef" />
+ </div>
</template>
<script setup>
@@ -643,10 +653,10 @@
import {onMounted, ref, getCurrentInstance} from "vue";
import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
import { ElMessageBox, ElMessage } from "element-plus";
-import { UploadFilled, Download } from "@element-plus/icons-vue";
+import { UploadFilled, Plus } from "@element-plus/icons-vue";
import useUserStore from "@/store/modules/user";
import { userListNoPage } from "@/api/system/user.js";
-import FileListDialog from '@/components/Dialog/FileListDialog.vue';
+import FileList from '@/views/salesManagement/salesLedger/fileList.vue';
import FormDialog from '@/components/Dialog/FormDialog.vue';
import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
import {
@@ -660,6 +670,7 @@
delProduct,
delLedgerFile, getProductInventory,
} from "@/api/salesManagement/salesLedger.js";
+import { getQuotationDetail } from "@/api/salesManagement/salesQuotation.js";
import { modelList, productTreeList } from "@/api/basicData/product.js";
import useFormData from "@/hooks/useFormData.js";
import dayjs from "dayjs";
@@ -678,43 +689,53 @@
const modelOptions = ref([]);
const tableLoading = ref(false);
const page = reactive({
- current: 1,
- size: 100,
+ current: 1,
+ size: 100,
});
const total = ref(0);
const fileList = ref([]);
+const deliveryFileList = 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 operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
- searchForm: {
- customerName: "", // 瀹㈡埛鍚嶇О
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- salesContractNo: "",
- salesman: "",
- customerId: "",
- entryPerson: "",
- entryDate: "",
- deliveryDate: "",
- maintenanceTime: "",
- productData: [],
- executionDate: "",
- hasProductionRecord: false,
- },
- rules: {
- salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
+ searchForm: {
+ customerName: "", // 瀹㈡埛鍚嶇О
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ productCategory: "", // 浜у搧澶х被
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ form: {
+ salesContractNo: "",
+ salesman: "",
+ customerId: "",
+ entryPerson: "",
+ entryDate: "",
+ maintenanceTime: "",
+ productData: [],
+ executionDate: "",
+ paymentMethod: "",
+ },
+ rules: {
+ salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
});
const { form, rules } = toRefs(data);
const { form: searchForm } = useFormData(data.searchForm);
@@ -723,46 +744,46 @@
const productOperationType = ref("");
const currentId = ref("");
const productFormData = reactive({
- productForm: {
- productCategory: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- },
- productRules: {
- productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productForm: {
+ productCategory: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ },
+ productRules: {
+ productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- specificationModel: [
- { required: true, message: "璇烽�夋嫨", trigger: "change" },
- ],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
+ specificationModel: [
+ { required: true, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ // taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ // invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
});
const { productForm, productRules } = toRefs(productFormData);
// 闃叉寰幆璁$畻鐨勬爣蹇�
const isCalculating = ref(false);
const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
});
// 鎵撳嵃鐩稿叧
const printPreviewVisible = ref(false);
@@ -790,344 +811,280 @@
const deliveryFormData = reactive({
deliveryForm: {
type: "璐ц溅", // 璐ц溅, 蹇��
+ shippingDate: "",
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "", // 蹇�掑崟鍙�
+ shippingImages: "", // 鍙戣揣鍥剧墖锛屽涓敤閫楀彿鍒嗛殧
},
deliveryRules: {
type: [
{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }
- ]
+ ],
+ shippingDate: [
+ { required: true, message: "璇烽�夋嫨鍙戣揣鏃ユ湡", trigger: "change" }
+ ],
+ shippingCarNumber: [
+ { validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
+ ],
+ expressCompany: [
+ { validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
+ ],
},
});
const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
-// 鍙戣揣瀹℃壒浜鸿妭鐐癸紙浠垮崗鍚屽鎵� infoFormDia.vue锛�
-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 importUploadRef = ref(null);
-const importUpload = reactive({
- title: "瀵煎叆閿�鍞彴璐�",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: (file) => {
- const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
- return false;
- }
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
- }
- return true;
- },
- onChange: (file, fileList) => {
- console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
- },
- onProgress: (event, file, fileList) => {
- console.log('涓婁紶涓�...', event.percent);
- },
- onSuccess: (response, file, fileList) => {
- console.log('涓婁紶鎴愬姛', response, file, fileList);
- importUpload.isUploading = false;
- if (response.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
- getList();
- } else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
- }
- },
- onError: (error, file, fileList) => {
- console.error('涓婁紶澶辫触', error, file, fileList);
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
-});
-
const changeDaterange = (value) => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
- }
- handleQuery();
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
+ }
+ handleQuery();
};
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
- // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
- // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
- if (arguments.length === 0) {
- page.current = 1;
- }
+ // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
+ // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
+ if (arguments.length === 0) {
+ page.current = 1;
+ }
expandedRowKeys.value = [];
- getList();
+ 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;
- const { entryDate, ...rest } = searchForm;
- // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
- const params = { ...rest, ...page };
- // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
- delete params.entryDate;
- return ledgerListPage(params)
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.total;
- return res;
- })
- .catch(() => {
- tableLoading.value = false;
- });
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ ledgerListPage({ ...rest, ...page })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.records;
+ tableData.value.map((item) => {
+ item.children = [];
+ });
+ total.value = res.total;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
};
// 鑾峰彇浜у搧澶х被tree鏁版嵁
const getProductOptions = () => {
- // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
- return productTreeList().then((res) => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value;
- });
+ // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
+ return productTreeList().then((res) => {
+ // 鍏煎鎺ュ彛杩斿洖 { data: [] } 鎴栫洿鎺ヨ繑鍥炴暟缁�
+ const list = Array.isArray(res) ? res : (res?.data ?? []);
+ productOptions.value = convertIdToValue(list);
+ return productOptions.value;
+ });
};
const formattedNumber = (row, column, cellValue) => {
- if (cellValue === undefined || cellValue === null || cellValue === "") {
- return "0.00";
- }
- return parseFloat(cellValue).toFixed(2);
+ return parseFloat(cellValue).toFixed(2);
};
-const findLedgerRecordByRow = (row) => {
- if (!row) return null;
- if (
- row.maintainer !== undefined ||
- row.maintainerName !== undefined ||
- row.entryPerson !== undefined ||
- row.entryPersonName !== undefined
- ) {
- return row;
- }
- if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
- return tableData.value.find((item) => String(item.id) === String(row.salesLedgerId)) || null;
- }
- return null;
+
+// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+const approvalStatusText = {
+ 1: "寰呭鏍�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒閫氳繃",
+ 4: "瀹℃壒澶辫触",
};
-const isCurrentUserMaintainer = (row) => {
- const ledgerRecord = findLedgerRecordByRow(row);
- if (!ledgerRecord) return true;
- const currentUserId = String(userStore.id ?? "");
- const currentNickName = String(userStore.nickName ?? "").trim();
- const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
- const maintainerName =
- ledgerRecord.maintainerName ?? ledgerRecord.maintainer ?? ledgerRecord.entryPersonName;
- if (maintainerId !== undefined && maintainerId !== null && String(maintainerId) !== "") {
- return String(maintainerId) === currentUserId;
- }
- if (maintainerName !== undefined && maintainerName !== null && String(maintainerName).trim() !== "") {
- return String(maintainerName).trim() === currentNickName;
- }
- return true;
-};
-const canEditLedger = (row) => isCurrentUserMaintainer(row);
-const canDeleteLedger = (row) => isCurrentUserMaintainer(row);
-const sensitiveAmountFormatter = (row, column, cellValue) => {
- if (!isCurrentUserMaintainer(row)) {
- return "*****";
- }
- return formattedNumber(row, column, cellValue);
+
+// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+const getApprovalStatusType = (status) => {
+ const typeMap = {
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ };
+ return typeMap[status] || "info";
};
// 鑾峰彇tree瀛愭暟鎹�
const getModels = (value) => {
- productForm.value.productCategory = findNodeById(productOptions.value, value);
- modelList({ id: value }).then((res) => {
- modelOptions.value = res;
- });
+ productForm.value.productCategory = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ });
};
const getProductModel = (value) => {
- const index = modelOptions.value.findIndex((item) => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
- } else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
- }
+ console.log("value", value);
+ const index = modelOptions.value.findIndex((item) => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ fetchQuotationPrice();
+ } else {
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ }
};
const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+// 鏍规嵁鎶ヤ环鎺ュ彛鍥炲~鍗曚环
+const fetchQuotationPrice = async () => {
+ // 闇�瑕佸鎴风被鍨嬨�佷骇鍝佸悕绉般�佽鏍�
+ const customer = customerOption.value.find((c) => c.id === form.value.customerId);
+ const customerType = customer?.customerType || customer?.type;
+ const productName = productForm.value.productCategory;
+ const specification = productForm.value.specificationModel;
+
+ try {
+ const { data } = await getQuotationDetail({
+ type: customerType,
+ productName,
+ specification,
+ });
+ const price = data;
+ if (price !== null && price !== undefined) {
+ productForm.value.taxInclusiveUnitPrice = Number(price);
+ mathNum(); // 閲嶆柊璁$畻鎬讳环
+ }
+ } catch (error) {
+ console.error("鑾峰彇鎶ヤ环鍗曚环澶辫触", error);
+ }
};
function convertIdToValue(data) {
- return data.map((item) => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
}
// 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
function findNodeIdByLabel(nodes, label) {
- if (!label) return null;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.label === label) return node.value;
- if (node.children && node.children.length > 0) {
- const found = findNodeIdByLabel(node.children, label);
- if (found !== null && found !== undefined) return found;
- }
- }
- return null;
+ if (!label) return null;
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if (node.label === label) return node.value;
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, label);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return null;
}
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.children !== undefined);
- console.log("selection", selectedRows.value);
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter((item) => item.children !== undefined);
+ console.log("selection", selectedRows.value);
};
const productSelected = (selectedRows) => {
- productSelectedRows.value = selectedRows;
+ productSelectedRows.value = selectedRows;
};
const expandedRowKeys = ref([]);
// 灞曞紑琛�
const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === row.id);
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
- }
- } else {
- expandedRowKeys.value = [];
- }
-};
-
-// 娣诲姞琛ㄨ绫诲悕鏂规硶
-const tableRowClassName = ({ row }) => {
- if (!row.deliveryDate) return '';
- if (row.isFh) return '';
-
- const diff = row.deliveryDaysDiff;
- if (diff === 15) {
- return 'yellow';
- } else if (diff === 10) {
- return 'pink';
- } else if (diff === 2) {
- return 'purple';
- } else if (diff < 2) {
- return 'red';
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
+ try {
+ productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
+ const index = tableData.value.findIndex((item) => item.id === row.id);
+ if (index > -1) {
+ tableData.value[index].children = res.data;
+ }
+ expandedRowKeys.value.push(row.id);
+ });
+ } catch (error) {
+ console.log(error);
+ }
+ } else {
+ expandedRowKeys.value = [];
}
};
// 涓昏〃鍚堣鏂规硶
const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, [
- "contractAmount",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
+ return proxy.summarizeTable(param, [
+ "contractAmount",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
};
// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param, parentRow) => {
- if (!isCurrentUserMaintainer(parentRow)) {
- const { columns } = param;
- return columns.map((column, index) => {
- if (index === 0) {
- return "鍚堣";
- }
- if (["taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"].includes(column.property)) {
- return "*****";
- }
- return "";
- });
- }
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
+const summarizeChildrenTable = (param) => {
+ return proxy.summarizeTable(param, [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
};
// 鎵撳紑寮规
const openForm = async (type, row) => {
- if (type === "edit" && row && !canEditLedger(row)) {
- proxy.$modal.msgWarning("褰撳墠绯荤粺鐧诲綍浜轰笉鏄淮鎶や汉锛屼笉鑳界紪杈戞暟鎹�");
- return;
- }
- operationType.value = type;
- form.value = {};
- productData.value = [];
- selectedQuotation.value = null;
- let userLists = await userListNoPage();
- userList.value = userLists.data;
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
listCustomerPrivatePool({current: -1,size:-1}).then((res) => {
customerOption.value = res.data.records;
});
- form.value.entryPerson = userStore.id;
- if (type === "add") {
- // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
- form.value.entryDate = getCurrentDate();
- // 绛捐鏃ユ湡榛樿涓哄綋澶�
- form.value.executionDate = getCurrentDate();
- } else {
- currentId.value = row.id;
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- form.value = { ...res };
- form.value.entryPerson = Number(res.entryPerson);
- productData.value = form.value.productData;
- fileList.value = form.value.salesLedgerFiles;
- });
- }
- // let userAll = await userStore.getInfo()
- // userList.value.forEach(element => {
- // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
- // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
- // }
- // });
- form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
- dialogFormVisible.value = true;
+ form.value.entryPerson = userStore.id;
+ if (type === "add") {
+ // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+ form.value.entryDate = getCurrentDate();
+ // 绛捐鏃ユ湡榛樿涓哄綋澶�
+ form.value.executionDate = getCurrentDate();
+ // 鏂板鏃堕噸缃鎵逛汉鑺傜偣
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
+ } else {
+ currentId.value = row.id;
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
+ form.value = { ...res };
+ form.value.entryPerson = Number(res.entryPerson);
+ productData.value = form.value.productData;
+ fileList.value = form.value.salesLedgerFiles;
+ // 鍥炴樉瀹℃壒浜鸿妭鐐�
+ if (res.approveUserIds) {
+ const userIds = res.approveUserIds.split(",").filter(id => id);
+ approverNodes.value = userIds.map((userId, index) => ({
+ id: index + 1,
+ userId: Number(userId)
+ }));
+ nextApproverId = userIds.length + 1;
+ } else {
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
+ }
+ });
+ }
+ // let userAll = await userStore.getInfo()
+ // userList.value.forEach(element => {
+ // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
+ // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
+ // }
+ // });
+ form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
+ dialogFormVisible.value = true;
};
// 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
@@ -1227,301 +1184,287 @@
quotationDialogVisible.value = false;
};
function changs(val) {
- console.log(val);
+ console.log(val);
}
// 涓婁紶鍓嶆牎妫�
function handleBeforeUpload(file) {
- // 鏍℃鏂囦欢澶у皬
- // if (file.size > 1024 * 1024 * 10) {
- // proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
- // return false;
- // }
- proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
- return true;
+ // 鏍℃鏂囦欢澶у皬
+ // if (file.size > 1024 * 1024 * 10) {
+ // proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+ // return false;
+ // }
+ proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+ return true;
}
// 涓婁紶澶辫触
function handleUploadError(err) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
- proxy.$modal.closeLoading();
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+ proxy.$modal.closeLoading();
}
// 涓婁紶鎴愬姛鍥炶皟
function handleUploadSuccess(res, file, uploadFiles) {
- proxy.$modal.closeLoading();
- if (res.code === 200) {
- file.tempId = res.data.tempId;
- proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- proxy.$refs.fileUpload.handleRemove(file);
- }
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
}
// 绉婚櫎鏂囦欢
function handleRemove(file) {
- if (operationType.value === "edit") {
- let ids = [];
- ids.push(file.id);
- delLedgerFile(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- });
- }
+ if (operationType.value === "edit") {
+ let ids = [];
+ ids.push(file.id);
+ delLedgerFile(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ });
+ }
+}
+// 鍙戣揣鍥剧墖涓婁紶鍓嶆牎妫�
+function handleDeliveryBeforeUpload(file) {
+ // 鏍℃鏂囦欢绫诲瀷
+ const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg';
+ if (!isImage) {
+ proxy.$modal.msgError("鍙兘涓婁紶 jpg銆乯peg銆乸ng 鏍煎紡鐨勫浘鐗�!");
+ return false;
+ }
+ // 鏍℃鏂囦欢澶у皬
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鍥剧墖澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
+ proxy.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��...");
+ return true;
+}
+// 鍙戣揣鍥剧墖涓婁紶澶辫触
+function handleDeliveryUploadError(err) {
+ proxy.$modal.msgError("涓婁紶鍥剧墖澶辫触");
+ proxy.$modal.closeLoading();
+}
+// 鍙戣揣鍥剧墖涓婁紶鎴愬姛鍥炶皟
+function handleDeliveryUploadSuccess(res, file, uploadFiles) {
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.deliveryFileUpload.handleRemove(file);
+ }
+}
+// 绉婚櫎鍙戣揣鍥剧墖
+function handleDeliveryRemove(file) {
+ // 浠庢枃浠跺垪琛ㄤ腑绉婚櫎
+ const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
+ if (index > -1) {
+ deliveryFileList.value.splice(index, 1);
+ }
}
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
console.log('productData.value--', productData.value)
- if (productData.value !== null && productData.value.length > 0) {
- form.value.productData = proxy.HaveJson(productData.value);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- let tempFileIds = [];
- if (fileList.value !== null && fileList.value.length > 0) {
- tempFileIds = fileList.value.map((item) => item.tempId);
- }
- form.value.tempFileIds = tempFileIds;
- form.value.type = 1;
- addOrUpdateSalesLedger(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- expandedRowKeys.value = [];
- getList();
- });
- }
- });
+ if (productData.value !== null && productData.value.length > 0) {
+ form.value.productData = proxy.HaveJson(productData.value);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ // 鏍¢獙瀹℃壒浜烘槸鍚﹀凡閫夋嫨
+ const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
+ if (hasEmptyApprover) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瀹℃壒浜�");
+ return;
+ }
+ let tempFileIds = [];
+ if (fileList.value !== null && fileList.value.length > 0) {
+ tempFileIds = fileList.value.map((item) => item.tempId);
+ }
+ form.value.tempFileIds = tempFileIds;
+ form.value.type = 1;
+ // 灏嗗鎵逛汉鑺傜偣杞崲涓洪�楀彿鍒嗛殧鐨勫瓧绗︿覆
+ const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
+ form.value.approveUserIds = approveUserIds;
+ addOrUpdateSalesLedger(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ });
};
// 鍏抽棴寮规
const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ // 閲嶇疆瀹℃壒浜鸿妭鐐�
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
};
const productIndex = ref(0);
// 鎵撳紑浜у搧寮规
const openProductForm = async (type, row, index) => {
- // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
- if (type === "edit" && isProductShipped(row)) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
- return;
- }
-
- productOperationType.value = type;
- productForm.value = {};
- proxy.resetForm("productFormRef");
- if (type === "edit") {
- productForm.value = { ...row };
- productIndex.value = index;
- // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
- try {
- const options = productOptions.value && productOptions.value.length > 0
- ? productOptions.value
- : await getProductOptions();
- const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
- if (categoryId) {
- const models = await modelList({ id: categoryId });
- modelOptions.value = models || [];
- // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
- const currentModel = (modelOptions.value || []).find(
- (m) => m.model === productForm.value.specificationModel
- );
- if (currentModel) {
- productForm.value.productModelId = currentModel.id;
- }
- }
- } catch (e) {
- // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
- console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
- }
- } else {
- getProductOptions()
- }
- productFormVisible.value = true;
+ productOperationType.value = type;
+ productForm.value = {};
+ proxy.resetForm("productFormRef");
+ // 鏂板銆佺紪杈戦兘闇�鍏堝姞杞戒骇鍝佹爲锛屽惁鍒� el-tree-select 鏃犳暟鎹�
+ try {
+ await getProductOptions();
+ } catch (e) {
+ console.error("鍔犺浇浜у搧鏍戝け璐�", e);
+ }
+ if (type === "edit") {
+ productForm.value = { ...row };
+ productIndex.value = index;
+ // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+ try {
+ const options = productOptions.value && productOptions.value.length > 0
+ ? productOptions.value
+ : await getProductOptions();
+ const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
+ if (categoryId) {
+ const models = await modelList({ id: categoryId });
+ modelOptions.value = models || [];
+ // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
+ const currentModel = (modelOptions.value || []).find(
+ (m) => m.model === productForm.value.specificationModel
+ );
+ if (currentModel) {
+ productForm.value.productModelId = currentModel.id;
+ }
+ }
+ } catch (e) {
+ // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
+ console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+ }
+ }
+ productFormVisible.value = true;
+ getProductOptions();
};
// 鎻愪氦浜у搧琛ㄥ崟
const submitProduct = () => {
- proxy.$refs["productFormRef"].validate((valid) => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if(productOperationType.value === "add"){
- productData.value.push({ ...productForm.value });
- }else{
- productData.value[productIndex.value] = { ...productForm.value }
- }
- closeProductDia();
- }
- }
- });
+ proxy.$refs["productFormRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitProductEdit();
+ } else {
+ if(productOperationType.value === "add"){
+ productData.value.push({ ...productForm.value });
+ }else{
+ productData.value[productIndex.value] = { ...productForm.value }
+ }
+ closeProductDia();
+ }
+ }
+ });
};
const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 1
- addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
- productData.value = res.productData;
- });
- });
+ productForm.value.salesLedgerId = currentId.value;
+ productForm.value.type = 1
+ addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
+ productData.value = res.productData;
+ });
+ });
};
// 鍒犻櫎浜у搧
const deleteProduct = () => {
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
- const shippedProducts = productSelectedRows.value.filter(row => isProductShipped(row));
- if (shippedProducts.length > 0) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
- return;
- }
-
- if (operationType.value === "add") {
- productSelectedRows.value.forEach((selectedRow) => {
- const index = productData.value.findIndex(
- (product) => product.id === selectedRow.id
- );
- if (index !== -1) {
- productData.value.splice(index, 1);
- }
- });
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map((item) => item.id);
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delProduct(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
- (res) => {
- productData.value = res.productData;
- }
- );
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- }
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ if (operationType.value === "add") {
+ productSelectedRows.value.forEach((selectedRow) => {
+ const index = productData.value.findIndex(
+ (product) => product.id === selectedRow.id
+ );
+ if (index !== -1) {
+ productData.value.splice(index, 1);
+ }
+ });
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map((item) => item.id);
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delProduct(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
+ (res) => {
+ productData.value = res.productData;
+ }
+ );
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ }
};
// 鍏抽棴浜у搧寮规
const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
};
-// 瀵煎叆
-const handleImport = () => {
- importUpload.title = "瀵煎叆閿�鍞彴璐�";
- importUpload.open = true;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
-};
-
-// 涓嬭浇瀵煎叆妯℃澘
-const downloadTemplate = () => {
- proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
-};
-
-// 鎻愪氦瀵煎叆鏂囦欢
-const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"].submit();
-};
-
// 瀵煎嚭
const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
-/** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
-const isProductShipped = (product) => {
- if (!product) return false;
- const status = String(product.shippingStatus || "").trim();
- // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
- return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
-};
-
-/** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
-const hasShippedProducts = (products) => {
- if (!products || !products.length) return false;
- return products.some((p) => {
- const status = String(p.shippingStatus || "").trim();
- // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
- if (p.shippingDate || p.shippingCarNumber) return true;
- // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
- return status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�";
- });
-};
-
// 鍒犻櫎
-const handleDelete = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const unauthorizedRows = selectedRows.value.filter((row) => !canDeleteLedger(row));
- if (unauthorizedRows.length > 0) {
- proxy.$modal.msgWarning("褰撳墠鐧诲綍鐢ㄦ埛涓嶆槸褰曞叆浜猴紝涓嶈兘鍒犻櫎璇ユ暟鎹�");
- return;
- }
- const ids = selectedRows.value.map((item) => item.id);
-
- // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
- const cannotDeleteNames = [];
- for (const row of selectedRows.value) {
- let products = row.children && row.children.length > 0 ? row.children : null;
- if (!products) {
- try {
- const res = await productList({ salesLedgerId: row.id, type: 1 });
- products = res.data || [];
- } catch {
- products = [];
- }
- }
- if (hasShippedProducts(products)) {
- cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
- }
- }
- if (cannotDeleteNames.length > 0) {
- proxy.$modal.msgWarning("宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�"));
- return;
- }
-
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delLedger(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .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;
+ }
+ // 妫�鏌ユ槸鍚︽湁瀹℃牳閫氳繃涓旂淮鎶や汉涓嶆槸褰撳墠鐧诲綍鐢ㄦ埛鐨勬暟鎹�
+ const cannotDeleteRows = selectedRows.value.filter(
+ (item) => item.approvalStatus === 3 && item.entryPerson !== userStore.id
+ );
+ if (cannotDeleteRows.length > 0) {
+ proxy.$modal.msgWarning("瀹℃牳閫氳繃涓旂淮鎶や汉涓嶆槸褰撳墠鐧诲綍鐢ㄦ埛鐨勬暟鎹笉鍙垹闄�");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delLedger(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鎵撳嵃鍔熻兘
@@ -1530,7 +1473,7 @@
proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
return;
}
-
+
// 鏄剧ず鍔犺浇鐘舵��
proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
@@ -1721,6 +1664,7 @@
<div class="print-page">
<div class="delivery-note">
<div class="header">
+ <div class="company-name">闈掓捣婀熸按宄″啘涓氬彂灞曟湁闄愬叕鍙�</div>
<div class="document-title">闆跺敭鍙戣揣鍗�</div>
</div>
@@ -1765,8 +1709,8 @@
<td>${product.taxInclusiveTotalPrice || '0'}</td>
</tr>
`).join('') :
- '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
- }
+ '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
+ }
</tbody>
<tfoot>
<tr>
@@ -1884,6 +1828,20 @@
return total.toFixed(2);
};
+// 鍙戣揣绫诲瀷鏍¢獙锛氳揣杞︽椂瑕佹眰杞︾墝锛屽揩閫掓椂瑕佹眰蹇�掑叕鍙�
+const validateShippingCarNumber = (value, callback) => {
+ if (deliveryForm.value.type === "璐ц溅") {
+ if (!value) return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
+ }
+ callback();
+};
+const validateExpressCompany = (value, callback) => {
+ if (deliveryForm.value.type === "蹇��") {
+ if (!value) return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
+ }
+ callback();
+};
+
const mathNum = () => {
console.log("productForm.value", productForm.value);
if (!productForm.value.taxInclusiveUnitPrice) {
@@ -1910,267 +1868,178 @@
// 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
const calculateFromTotalPrice = () => {
- if (isCalculating.value) return;
-
- const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
-
- if (!totalPrice || !quantity || quantity <= 0) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- totalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
+ if (isCalculating.value) return;
+
+ const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+ const quantity = parseFloat(productForm.value.quantity);
+ const taxRate = Number(productForm.value.taxRate) || 0;
+
+ if (!totalPrice || !quantity || quantity <= 0) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ totalPrice,
+ taxRate
+ );
+
+ isCalculating.value = false;
};
// 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
const calculateFromExclusiveTotalPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
- const taxRateDecimal = taxRate / 100;
- const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
- productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
-
- isCalculating.value = false;
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ if (isCalculating.value) return;
+
+ const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
+ const quantity = parseFloat(productForm.value.quantity);
+ const taxRate = Number(productForm.value.taxRate) || 0;
+
+ // if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+ // return;
+ // }
+ if (!exclusiveTotalPrice || !quantity || quantity <= 0) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+ const taxRateDecimal = taxRate / 100;
+ const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+ productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
+
+ isCalculating.value = false;
};
// 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
const calculateFromQuantity = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+ const taxRate = Number(productForm.value.taxRate) || 0;
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ taxRate
+ );
+
+ isCalculating.value = false;
};
// 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
const calculateFromUnitPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+ const taxRate = Number(productForm.value.taxRate) || 0;
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ taxRate
+ );
+
+ isCalculating.value = false;
};
// 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
const calculateFromTaxRate = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!inclusiveTotalPrice || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻涓嶅惈绋庢�讳环
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- inclusiveTotalPrice,
- taxRate
- );
-
- isCalculating.value = false;
-};
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusText = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
- if (row.shippingDate || row.shippingCarNumber) {
- return '宸插彂璐�';
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
- if (status === null || status === undefined || status === '') {
- return '寰呭彂璐�';
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const statusTextMap = {
- '寰呭彂璐�': '寰呭彂璐�',
- '寰呭鏍�': '寰呭鏍�',
- '瀹℃牳涓�': '瀹℃牳涓�',
- '瀹℃牳鎷掔粷': '瀹℃牳鎷掔粷',
- '瀹℃牳閫氳繃': '瀹℃牳閫氳繃',
- '宸插彂璐�': '宸插彂璐�'
- };
- return statusTextMap[statusStr] || '寰呭彂璐�';
-};
+ // if (!productForm.value.taxRate) {
+ // proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ // return;
+ // }
+ if (isCalculating.value) return;
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusType = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
- if (row.shippingDate || row.shippingCarNumber) {
- return 'success';
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
- if (status === null || status === undefined || status === '') {
- return 'info';
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const typeTextMap = {
- '寰呭彂璐�': 'info',
- '寰呭鏍�': 'info',
- '瀹℃牳涓�': 'warning',
- '瀹℃牳鎷掔粷': 'danger',
- '瀹℃牳閫氳繃': 'success',
- '宸插彂璐�': 'success'
- };
- return typeTextMap[statusStr] || 'info';
-};
+ const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+ const taxRate = Number(productForm.value.taxRate) || 0;
-/**
- * 鍒ゆ柇鏄惁鍙互鍙戣揣
- * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
- * @param row 琛屾暟鎹�
- */
-const canShip = (row) => {
- // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
- if (row.approveStatus !== 1) {
- return false;
- }
-
- // 鑾峰彇鍙戣揣鐘舵��
- const shippingStatus = row.shippingStatus;
-
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
- if (row.shippingDate || row.shippingCarNumber) {
- return false;
- }
-
- // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
- const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
- return statusStr === '寰呭彂璐�' || statusStr === '瀹℃牳鎷掔粷';
-};
+ // if (!inclusiveTotalPrice || !taxRate) {
+ // return;
+ // }
+ if (!inclusiveTotalPrice) {
+ return;
+ }
+ isCalculating.value = true;
+
+ // 璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ inclusiveTotalPrice,
+ taxRate
+ );
+
+ isCalculating.value = false;
+};
/**
* 涓嬭浇鏂囦欢
*
* @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
*/
const fileListRef = ref(null)
-const fileListDialogVisible = ref(false)
const downLoadFile = (row) => {
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- if (fileListRef.value) {
- fileListRef.value.open(res.salesLedgerFiles)
- }
- });
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
+ fileListRef.value.open(res.salesLedgerFiles)
+ });
}
// 鎵撳紑鍙戣揣寮规
const openDeliveryForm = (row) => {
- // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
- if (!canShip(row)) {
- proxy.$modal.msgWarning("鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣");
- return;
- }
-
currentDeliveryRow.value = row;
deliveryForm.value = {
type: "璐ц溅",
+ shippingDate: getCurrentDate(),
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "", // 鍒濆鍖栧揩閫掑崟鍙蜂负绌�
+ shippingImages: "", // 鍒濆鍖栧浘鐗囦负绌�
};
- // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
- approverNodes.value = [{ id: 1, userId: null }];
- nextApproverId = 2;
+ deliveryFileList.value = []; // 鍒濆鍖栨枃浠跺垪琛ㄤ负绌�
deliveryFormVisible.value = true;
};
@@ -2178,45 +2047,27 @@
const submitDelivery = () => {
proxy.$refs["deliveryFormRef"].validate((valid) => {
if (valid) {
- // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
- const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
- if (hasEmptyApprover) {
- proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
- return;
+ let tempFileIds = [];
+ if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
+ tempFileIds = deliveryFileList.value.map((item) => item.tempId);
}
- const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
- // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
- const currentExpandedKeys = [...expandedRowKeys.value];
- const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
addShippingInfo({
- salesLedgerId: salesLedgerId,
- salesLedgerProductId: currentDeliveryRow.value.id,
+ salesLedgerId: currentDeliveryRow.value.id,
type: deliveryForm.value.type,
- approveUserIds,
+ shippingDate: deliveryForm.value.shippingDate,
+ shippingCarNumber: deliveryForm.value.type === "璐ц溅" ? deliveryForm.value.shippingCarNumber : "",
+ expressCompany: deliveryForm.value.type === "蹇��" ? deliveryForm.value.expressCompany : "",
+ expressNumber: deliveryForm.value.type === "蹇��" ? deliveryForm.value.expressNumber : "",
+ tempFileIds: tempFileIds,
})
.then(() => {
proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
closeDeliveryDia();
- // 鍒锋柊涓昏〃鏁版嵁
- getList().then(() => {
- // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
- if (currentExpandedKeys.length > 0) {
- // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
- const loadPromises = currentExpandedKeys.map(ledgerId => {
- return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === ledgerId);
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- });
- });
- Promise.all(loadPromises).then(() => {
- // 鎭㈠灞曞紑鐘舵��
- expandedRowKeys.value = currentExpandedKeys;
- });
- }
- });
+ getList();
})
+ .catch(() => {
+ proxy.$modal.msgError("鍙戣揣澶辫触锛岃閲嶈瘯");
+ });
}
});
};
@@ -2224,20 +2075,25 @@
// 鍏抽棴鍙戣揣寮规
const closeDeliveryDia = () => {
proxy.resetForm("deliveryFormRef");
+ deliveryFileList.value = []; // 娓呯┖鏂囦欢鍒楄〃
+ deliveryForm.value.shippingImages = ""; // 娓呯┖鍥剧墖
+ deliveryForm.value.expressNumber = ""; // 娓呯┖蹇�掑崟鍙�
deliveryFormVisible.value = false;
currentDeliveryRow.value = null;
};
-const currentFactoryName = ref("");
-const getCurrentFactoryName = async () => {
- let res = await userStore.getInfo();
- currentFactoryName.value = res.user.currentFactoryName;
+
+// 鍙戣揣绫诲瀷鍒囨崲鏃舵竻绌哄搴斿瓧娈�
+const handleShippingTypeChange = (val) => {
+ if (val === "璐ц溅") {
+ deliveryForm.value.expressCompany = "";
+ deliveryForm.value.expressNumber = "";
+ } else {
+ deliveryForm.value.shippingCarNumber = "";
+ }
};
+
onMounted(() => {
getList();
- userListNoPage().then(res => {
- userList.value = res.data;
- })
- getCurrentFactoryName();
});
</script>
@@ -2437,4 +2293,62 @@
page-break-after: avoid;
}
}
+
+// 闅愯棌鍥剧墖涓婁紶缁勪欢鐨勯瑙堟寜閽紙鏀惧ぇ闀滐級
+:deep(.el-upload-list--picture-card .el-upload-list__item-actions) {
+ .el-upload-list__item-preview {
+ display: none;
+ }
+}
+
+// 瀹℃壒浜鸿妭鐐规牱寮�
+.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%;
+ }
+}
</style>
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index 01174d7..7da8b7e 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -15,15 +15,6 @@
</template>
</el-input>
</el-col>
- <el-col :span="8">
- <el-select v-model="searchForm.customer" placeholder="璇烽�夋嫨瀹㈡埛" clearable>
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.customerName">
- {{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
- }}
- </el-option>
- </el-select>
- </el-col>
<!-- <el-col :span="6">-->
<!-- <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鎶ヤ环鐘舵��" clearable>-->
<!-- <el-option label="鑽夌" value="鑽夌"></el-option>-->
@@ -52,26 +43,12 @@
>
<el-table-column align="center" label="搴忓彿" type="index" width="60" />
<el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" />
- <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" />
- <el-table-column prop="salesperson" label="涓氬姟鍛�" width="100" />
- <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="120" />
- <el-table-column prop="validDate" label="鏈夋晥鏈熻嚦" width="120" />
- <el-table-column prop="status" label="瀹℃壒鐘舵��" width="120" align="center">
- <template #default="{ row }">
- <el-tag :type="getStatusType(row.status)" disable-transitions>
- {{ row.status || '--' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="totalAmount" label="鎶ヤ环閲戦" width="120">
- <template #default="scope">
- 楼{{ scope.row.totalAmount.toFixed(2) }}
- </template>
- </el-table-column>
+ <el-table-column prop="salesperson" label="涓氬姟鍛�" />
+ <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" />
<el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
<template #default="scope">
+ <el-button link type="primary" @click="handleView(scope.row)">鏌ョ湅</el-button>
<el-button link type="primary" @click="handleEdit(scope.row)" :disabled="!['寰呭鎵�','鎷掔粷'].includes(scope.row.status)">缂栬緫</el-button>
- <el-button link type="primary" @click="handleView(scope.row)" style="color: #67C23A">鏌ョ湅</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
</template>
</el-table-column>
@@ -91,7 +68,7 @@
<FormDialog v-model="dialogVisible" :title="dialogTitle" width="85%" :close-on-click-modal="false" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false">
<div class="quotation-form-container">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="quotation-form">
- <!-- 鍩烘湰淇℃伅 -->
+ <!-- 鍩烘湰淇℃伅锛堜粎淇濈暀涓氬姟鍛樺拰鎶ヤ环鏃ユ湡锛� -->
<el-card class="form-card" shadow="hover">
<template #header>
<div class="card-header-wrapper">
@@ -102,22 +79,17 @@
<div class="form-content">
<el-row :gutter="24">
<el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О" prop="customer">
- <el-select v-model="form.customer" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%" clearable filterable>
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id"></el-option>
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
<el-form-item label="涓氬姟鍛�" prop="salesperson">
- <el-select v-model="form.salesperson" placeholder="璇烽�夋嫨涓氬姟鍛�" style="width: 100%" clearable filterable>
- <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
- :value="item.nickName" />
+ <el-select v-model="form.salesperson" placeholder="璇烽�夋嫨涓氬姟鍛�" style="width: 100%" clearable>
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
</el-select>
</el-form-item>
</el-col>
- </el-row>
- <el-row :gutter="24">
<el-col :span="12">
<el-form-item label="鎶ヤ环鏃ユ湡" prop="quotationDate">
<el-date-picker
@@ -129,83 +101,6 @@
value-format="YYYY-MM-DD"
clearable
/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏈夋晥鏈熻嚦" prop="validDate">
- <el-date-picker
- v-model="form.validDate"
- type="date"
- placeholder="閫夋嫨鏈夋晥鏈�"
- style="width: 100%"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- clearable
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
- <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- </div>
- </el-card>
-
- <!-- 瀹℃壒浜轰俊鎭� -->
- <el-card class="form-card" shadow="hover">
- <template #header>
- <div class="card-header-wrapper">
- <el-icon class="card-icon"><UserFilled /></el-icon>
- <span class="card-title">瀹℃壒浜洪�夋嫨</span>
- <el-button type="primary" size="small" @click="addApproverNode" class="header-btn">
- <el-icon><Plus /></el-icon>
- 鏂板鑺傜偣
- </el-button>
- </div>
- </template>
- <div class="form-content">
- <el-row>
- <el-col :span="24">
- <el-form-item>
- <div class="approver-nodes-container">
- <div
- v-for="(node, index) in approverNodes"
- :key="node.id"
- class="approver-node-item"
- >
- <div class="approver-node-label">
- <span class="node-step">{{ index + 1 }}</span>
- <span class="node-text">瀹℃壒浜�</span>
- <el-icon class="arrow-icon"><ArrowRight /></el-icon>
- </div>
- <el-select
- v-model="node.userId"
- placeholder="閫夋嫨浜哄憳"
- class="approver-select"
- filterable
- clearable
- >
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
- </el-select>
- <el-button
- type="danger"
- size="small"
- :icon="Delete"
- @click="removeApproverNode(index)"
- v-if="approverNodes.length > 1"
- class="remove-btn"
- >鍒犻櫎</el-button>
- </div>
- </div>
</el-form-item>
</el-col>
</el-row>
@@ -228,52 +123,53 @@
<el-table :data="form.products" border style="width: 100%" class="product-table" v-if="form.products.length > 0">
<el-table-column prop="product" label="浜у搧鍚嶇О" width="200">
<template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.productId`" class="product-table-form-item">
- <el-tree-select
- v-model="scope.row.productId"
- placeholder="璇烽�夋嫨"
- clearable
- check-strictly
- @change="getModels($event, scope.row)"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%"
- />
- </el-form-item>
+ <el-tree-select
+ v-model="scope.row.productId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels($event, scope.row)"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
</template>
</el-table-column>
- <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" width="200">
+ <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" width="150">
<template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.specificationId`" class="product-table-form-item">
- <el-select
- v-model="scope.row.specificationId"
- placeholder="璇烽�夋嫨"
- clearable
- @change="getProductModel($event, scope.row)"
- style="width: 100%"
- >
- <el-option
- v-for="item in scope.row.modelOptions || []"
- :key="item.id"
- :label="item.model"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
+ <el-select
+ v-model="scope.row.specificationId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="getProductModel($event, scope.row)"
+ >
+ <el-option
+ v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id"
+ />
+ </el-select>
</template>
</el-table-column>
<el-table-column prop="unit" label="鍗曚綅">
<template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.unit`" class="product-table-form-item">
- <el-input v-model="scope.row.unit" placeholder="鍗曚綅" clearable/>
- </el-form-item>
+ <el-input v-model="scope.row.unit" placeholder="鍗曚綅" />
</template>
</el-table-column>
- <el-table-column prop="unitPrice" label="鍗曚环">
+ <el-table-column prop="unitPrice" label="涓�鎵瑰晢鍗曚环">
<template #default="scope">
- <el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item">
- <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
- </el-form-item>
+ <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" />
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitPriceTwo" label="缁堢鍟嗗崟浠�">
+ <template #default="scope">
+ <el-input-number v-model="scope.row.unitPriceTwo" :min="0" :precision="2" style="width: 100%" />
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitPriceThree" label="鍗曚环">
+ <template #default="scope">
+ <el-input-number v-model="scope.row.unitPriceThree" :min="0" :precision="2" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="鎿嶄綔" width="80" align="center">
@@ -315,28 +211,29 @@
<el-dialog v-model="viewDialogVisible" title="鎶ヤ环璇︽儏" width="800px">
<el-descriptions :column="2" border>
<el-descriptions-item label="鎶ヤ环鍗曞彿">{{ currentQuotation.quotationNo }}</el-descriptions-item>
- <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ currentQuotation.customer }}</el-descriptions-item>
<el-descriptions-item label="涓氬姟鍛�">{{ currentQuotation.salesperson }}</el-descriptions-item>
<el-descriptions-item label="鎶ヤ环鏃ユ湡">{{ currentQuotation.quotationDate }}</el-descriptions-item>
- <el-descriptions-item label="鏈夋晥鏈熻嚦">{{ currentQuotation.validDate }}</el-descriptions-item>
- <el-descriptions-item label="浠樻鏂瑰紡">{{ currentQuotation.paymentMethod }}</el-descriptions-item>
-<!-- <el-descriptions-item label="鎶ヤ环鐘舵��">-->
-<!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>-->
-<!-- </el-descriptions-item>-->
- <el-descriptions-item label="鎶ヤ环鎬婚" :span="2">
- <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{ currentQuotation.totalAmount?.toFixed(2) }}</span>
- </el-descriptions-item>
</el-descriptions>
- <div style="margin: 20px 0;">
+ <div style="margin-top: 20px;">
<h4>浜у搧鏄庣粏</h4>
<el-table :data="currentQuotation.products" border style="width: 100%">
<el-table-column prop="product" label="浜у搧鍚嶇О" />
<el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
<el-table-column prop="unit" label="鍗曚綅" />
- <el-table-column prop="unitPrice" label="鍗曚环">
+ <el-table-column prop="unitPrice" label="涓�鎵瑰晢鍗曚环">
<template #default="scope">
楼{{ scope.row.unitPrice.toFixed(2) }}
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitPriceTwo" label="缁堢鍟嗗崟浠�">
+ <template #default="scope">
+ 楼{{ scope.row.unitPriceTwo?.toFixed(2) }}
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitPriceThree" label="鍗曚环">
+ <template #default="scope">
+ 楼{{ scope.row.unitPriceThree?.toFixed(2) }}
</template>
</el-table-column>
</el-table>
@@ -353,20 +250,18 @@
<script setup>
import { ref, reactive, computed, onMounted, markRaw, shallowRef } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
-import { Search, Document, UserFilled, Box, EditPen, Plus, ArrowRight, Delete } from '@element-plus/icons-vue'
+import { Search, Document, Box, EditPen, Plus } from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
import FormDialog from '@/components/Dialog/FormDialog.vue'
import {getQuotationList,addQuotation,updateQuotation,deleteQuotation} from '@/api/salesManagement/salesQuotation.js'
import {userListNoPage} from "@/api/system/user.js";
import {customerList} from "@/api/salesManagement/salesLedger.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
-import {listCustomerPrivatePool} from "@/api/basicData/customerFile.js";
// 鍝嶅簲寮忔暟鎹�
const loading = ref(false)
const searchForm = reactive({
quotationNo: '',
- customer: '',
status: ''
})
@@ -400,57 +295,27 @@
totalAmount: 0
})
-const baseRules = {
- customer: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
+const rules = {
salesperson: [{ required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change' }],
- quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }],
- validDate: [{ required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change' }],
- paymentMethod: [{ required: true, message: '璇疯緭鍏ヤ粯娆炬柟寮�', trigger: 'blur' }]
+ quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }]
}
-
-const productRowRules = {
- productId: [{ required: true, message: '璇烽�夋嫨浜у搧鍚嶇О', trigger: 'change' }],
- specificationId: [{ required: true, message: '璇烽�夋嫨瑙勬牸鍨嬪彿', trigger: 'change' }],
- unit: [{ required: true, message: '璇峰~鍐欏崟浣�', trigger: 'blur' }],
- unitPrice: [{ required: true, message: '璇峰~鍐欏崟浠�', trigger: 'change' }]
-}
-const rules = computed(() => {
- const r = { ...baseRules }
- ;(form.products || []).forEach((_, i) => {
- r[`products.${i}.productId`] = productRowRules.productId
- r[`products.${i}.specificationId`] = productRowRules.specificationId
- r[`products.${i}.unit`] = productRowRules.unit
- r[`products.${i}.unitPrice`] = productRowRules.unitPrice
- })
- return r
-})
const userList = ref([]);
const customerOption = ref([]);
-
-// 瀹℃壒浜鸿妭鐐圭浉鍏�
-const approverNodes = ref([
- { id: 1, userId: null }
-])
-let nextApproverId = 2
const isEdit = ref(false)
const editId = ref(null)
const currentQuotation = ref({})
const formRef = ref()
-// 娣诲姞瀹℃壒浜鸿妭鐐�
-function addApproverNode() {
- approverNodes.value.push({ id: nextApproverId++, userId: null })
-}
-
-// 鍒犻櫎瀹℃壒浜鸿妭鐐�
-function removeApproverNode(index) {
- approverNodes.value.splice(index, 1)
-}
-
// 璁$畻灞炴��
const filteredList = computed(() => {
let list = quotationList.value
+ if (searchForm.quotationNo) {
+ list = list.filter(item => item.quotationNo.includes(searchForm.quotationNo))
+ }
+ if (searchForm.status) {
+ list = list.filter(item => item.status === searchForm.status)
+ }
return list
})
@@ -467,20 +332,13 @@
const resetSearch = () => {
searchForm.quotationNo = ''
- searchForm.customer = ''
searchForm.status = ''
- // 閲嶇疆鍒扮涓�椤靛苟閲嶆柊鏌ヨ
- pagination.currentPage = 1
- handleSearch()
}
const handleAdd = async () => {
dialogTitle.value = '鏂板鎶ヤ环'
isEdit.value = false
resetForm()
- // 閲嶇疆瀹℃壒浜鸿妭鐐�
- approverNodes.value = [{ id: 1, userId: null }]
- nextApproverId = 2
dialogVisible.value = true
let userLists = await userListNoPage();
// 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
@@ -490,8 +348,13 @@
userName: item.userName || ''
}));
getProductOptions();
- listCustomerPrivatePool({current: -1,size:-1}).then((res) => {
- customerOption.value = res.data.records;
+ customerList().then((res) => {
+ // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
+ customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
+ id: item.id,
+ customerName: item.customerName || '',
+ taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
+ }))
});
}
const getProductOptions = () => {
@@ -534,7 +397,7 @@
if (!value) {
row.productId = '';
row.product = '';
- row.modelOptions = [];
+ modelOptions.value = [];
row.specificationId = '';
row.specification = '';
row.unit = '';
@@ -547,9 +410,9 @@
if (label) {
row.product = label;
}
- // 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃锛岃缃埌褰撳墠琛岀殑 modelOptions
+ // 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃
modelList({ id: value }).then((res) => {
- row.modelOptions = res || [];
+ modelOptions.value = res || [];
});
};
const getProductModel = (value, row) => {
@@ -563,11 +426,10 @@
}
// 鏇存柊 specificationId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
row.specificationId = value;
- const modelOptions = row.modelOptions || [];
- const index = modelOptions.findIndex((item) => item.id === value);
+ const index = modelOptions.value.findIndex((item) => item.id === value);
if (index !== -1) {
- row.specification = modelOptions[index].model;
- row.unit = modelOptions[index].unit;
+ row.specification = modelOptions.value[index].model;
+ row.unit = modelOptions.value[index].unit;
} else {
row.specification = '';
row.unit = '';
@@ -605,7 +467,9 @@
specification: product.specification || '',
quantity: product.quantity || 0,
unit: product.unit || '',
- unitPrice: product.unitPrice || 0,
+ unitPrice: product.unitPrice || 0, // 涓�鎵瑰晢鍗曚环
+ unitPriceTwo: product.unitPriceTwo || product.dealerUnitPrice || 0, // 缁堢鍟嗗崟浠�
+ unitPriceThree: product.unitPriceThree || 0, // 鍗曚环
amount: product.amount || 0
})) : [],
totalAmount: row.totalAmount || 0
@@ -630,65 +494,31 @@
form.paymentMethod = row.paymentMethod || ''
form.status = row.status || '鑽夌'
form.remark = row.remark || ''
- form.products = row.products ? await Promise.all(row.products.map(async (product) => {
+ form.products = row.products ? row.products.map(product => {
const productName = product.product || product.productName || ''
// 浼樺厛鐢� productId锛涘鏋滃彧鏈夊悕绉帮紝灏濊瘯鍙嶆煡 id 浠ヤ究鏍戦�夋嫨鍣ㄥ弽鏄�
- const resolvedProductId = product.productId
+ const resolvedId = product.productId
? Number(product.productId)
: findNodeIdByLabel(productOptions.value, productName) || ''
-
- // 濡傛灉鏈変骇鍝両D锛屽姞杞藉搴旂殑瑙勬牸鍨嬪彿鍒楄〃
- let modelOptions = [];
- let resolvedSpecificationId = product.specificationId || '';
-
- if (resolvedProductId) {
- try {
- const res = await modelList({ id: resolvedProductId });
- modelOptions = res || [];
-
- // 濡傛灉杩斿洖鐨勬暟鎹病鏈� specificationId锛屼絾鏈� specification 鍚嶇О锛屾牴鎹悕绉版煡鎵� ID
- if (!resolvedSpecificationId && product.specification) {
- const foundModel = modelOptions.find(item => item.model === product.specification);
- if (foundModel) {
- resolvedSpecificationId = foundModel.id;
- }
- }
- } catch (error) {
- console.error('鍔犺浇瑙勬牸鍨嬪彿澶辫触:', error);
- }
- }
-
return {
- productId: resolvedProductId,
+ productId: resolvedId,
product: productName,
- specificationId: resolvedSpecificationId,
+ specificationId: product.specificationId || '',
specification: product.specification || '',
quantity: product.quantity || 0,
unit: product.unit || '',
unitPrice: product.unitPrice || 0,
- amount: product.amount || 0,
- modelOptions: modelOptions // 涓烘瘡琛屾坊鍔犵嫭绔嬬殑瑙勬牸鍨嬪彿鍒楄〃
+ unitPriceTwo: product.unitPriceTwo || product.dealerUnitPrice || 0,
+ unitPriceThree: product.unitPriceThree || 0,
+ amount: product.amount || 0
}
- })) : []
+ }) : []
form.subtotal = row.subtotal || 0
form.freight = row.freight || 0
form.otherFee = row.otherFee || 0
form.discountRate = row.discountRate || 0
form.discountAmount = row.discountAmount || 0
form.totalAmount = row.totalAmount || 0
-
- // 鍙嶆樉瀹℃壒浜�
- if (row.approveUserIds) {
- const userIds = row.approveUserIds.split(',')
- approverNodes.value = userIds.map((userId, idx) => ({
- id: idx + 1,
- userId: parseInt(userId.trim())
- }))
- nextApproverId = userIds.length + 1
- } else {
- approverNodes.value = [{ id: 1, userId: null }]
- nextApproverId = 2
- }
// 鍔犺浇鐢ㄦ埛鍒楄〃
let userLists = await userListNoPage();
@@ -750,9 +580,10 @@
specification: '',
quantity: 1,
unit: '',
+ unitPriceTwo: 0,
+ unitPriceThree: 0,
unitPrice: 0,
- amount: 0,
- modelOptions: [] // 涓烘瘡琛屾坊鍔犵嫭绔嬬殑瑙勬牸鍨嬪彿鍒楄〃
+ amount: 0
})
}
@@ -776,6 +607,10 @@
form.totalAmount = form.subtotal + form.freight + form.otherFee - form.discountAmount
}
+const handleCustomerChange = () => {
+ // 鍙互鏍规嵁瀹㈡埛淇℃伅鑷姩濉厖涓�浜涢粯璁ゅ��
+}
+
const handleSubmit = () => {
formRef.value.validate((valid) => {
if (valid) {
@@ -783,16 +618,6 @@
ElMessage.warning('璇疯嚦灏戞坊鍔犱竴涓骇鍝�')
return
}
-
- // 瀹℃壒浜哄繀濉牎楠�
- const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
- if (hasEmptyApprover) {
- ElMessage.error('璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒')
- return
- }
-
- // 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
- form.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
// 璁$畻鎵�鏈変骇鍝佺殑鍗曚环鎬诲拰
form.totalAmount = form.products.reduce((sum, product) => {
@@ -831,14 +656,10 @@
const handleCurrentChange = (val) => {
pagination.currentPage = val.page
pagination.pageSize = val.limit
- // 鍒嗛〉鍙樺寲鏃堕噸鏂版煡璇㈠垪琛�
- handleSearch()
}
const handleSearch = ()=>{
const params = {
- // 鍚庣鍒嗛〉鍙傛暟锛歝urrent / size
- current: pagination.currentPage,
- size: pagination.pageSize,
+ ...pagination,
...searchForm
}
getQuotationList(params).then(res=>{
@@ -854,8 +675,6 @@
validDate: item.validDate || '',
paymentMethod: item.paymentMethod || '',
status: item.status || '鑽夌',
- // 瀹℃壒浜猴紙鐢ㄤ簬缂栬緫鏃跺弽鏄撅級
- approveUserIds: item.approveUserIds || '',
remark: item.remark || '',
products: item.products ? item.products.map(product => ({
productId: product.productId || '',
@@ -865,6 +684,8 @@
quantity: product.quantity || 0,
unit: product.unit || '',
unitPrice: product.unitPrice || 0,
+ unitPriceTwo: product.unitPriceTwo || product.dealerUnitPrice || 0,
+ unitPriceThree: product.unitPriceThree || 0,
amount: product.amount || 0
})) : [],
subtotal: item.subtotal || 0,
@@ -878,7 +699,12 @@
}
})
customerList().then((res) => {
- customerOption.value = res;
+ // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
+ customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
+ id: item.id,
+ customerName: item.customerName || '',
+ taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
+ }))
});
}
@@ -962,82 +788,6 @@
.form-content {
padding: 8px 0;
-}
-
-.product-table-form-item {
- margin-bottom: 0;
- :deep(.el-form-item__content) {
- margin-left: 0 !important;
- }
- :deep(.el-form-item__label) {
- width: auto;
- min-width: auto;
- }
-}
-
-.approver-nodes-container {
- display: flex;
- flex-wrap: wrap;
- gap: 24px;
- padding: 12px 0;
-}
-
-.approver-node-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 12px;
- padding: 16px;
- background: #f8f9fa;
- border-radius: 8px;
- border: 1px solid #e4e7ed;
- transition: all 0.3s ease;
- min-width: 180px;
-
- &:hover {
- border-color: #409eff;
- background: #f0f7ff;
- box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
- }
-}
-
-.approver-node-label {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 14px;
- color: #606266;
-
- .node-step {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 24px;
- height: 24px;
- background: #409eff;
- color: #fff;
- border-radius: 50%;
- font-size: 12px;
- font-weight: 600;
- }
-
- .node-text {
- font-weight: 500;
- }
-
- .arrow-icon {
- color: #909399;
- font-size: 14px;
- }
-}
-
-.approver-select {
- width: 100%;
- min-width: 150px;
-}
-
-.remove-btn {
- margin-top: 4px;
}
.product-table {
--
Gitblit v1.9.3