From c391bf92060a370c1f22e5e3b7d17c2ebfd048c7 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 08 四月 2026 14:25:36 +0800
Subject: [PATCH] fix: 销售台账新增修改
---
src/views/procurementManagement/procurementLedger/index.vue | 743 +++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 537 insertions(+), 206 deletions(-)
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index e40a68a..1eb1e39 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -33,6 +33,18 @@
prefix-icon="Search"
@change="handleQuery" />
</el-form-item>
+ <el-form-item label="渚涘簲鍟嗙被鍨嬶細">
+ <el-select v-model="searchForm.supplierType"
+ placeholder="璇烽�夋嫨"
+ style="width: 220px"
+ clearable
+ @change="handleQuery">
+ <el-option label="瀵瑰叕"
+ value="1" />
+ <el-option label="瀵圭"
+ value="2" />
+ </el-select>
+ </el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
<el-date-picker v-model="searchForm.entryDate"
value-format="YYYY-MM-DD"
@@ -53,6 +65,9 @@
<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 @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger"
plain
@@ -89,17 +104,33 @@
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" />
+ prop="taxRate"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="鍚◣鍗曚环(鍏�)"
prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="鍚◣鎬讳环(鍏�)"
prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
+ <el-table-column label="鍗曚环锛堝绉侊級"
+ prop="unitPrice"
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 2" />
+ <el-table-column label="鎬讳环锛堝绉侊級"
+ prop="totalPrice"
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 2" />
</el-table>
</template>
</el-table-column>
@@ -113,12 +144,20 @@
show-overflow-tooltip />
<el-table-column label="閿�鍞悎鍚屽彿"
prop="salesContractNo"
- width="160"
+ width="160"
show-overflow-tooltip />
<el-table-column label="渚涘簲鍟嗗悕绉�"
prop="supplierName"
- width="160"
+ width="160"
show-overflow-tooltip />
+ <el-table-column label="渚涘簲鍟嗙被鍨�"
+ prop="supplierType"
+ width="100"
+ show-overflow-tooltip>
+ <template #default="scope">
+ {{ scope.row.supplierType === 1 ? '瀵瑰叕' : '瀵圭' }}
+ </template>
+ </el-table-column>
<el-table-column label="椤圭洰鍚嶇О"
prop="projectName"
width="320"
@@ -128,9 +167,8 @@
width="100"
show-overflow-tooltip>
<template #default="scope">
- <el-tag
- :type="getApprovalStatusType(scope.row.approvalStatus)"
- size="small">
+ <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)"
+ size="small">
{{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
</el-tag>
</template>
@@ -156,6 +194,10 @@
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"
@@ -163,12 +205,10 @@
<template #default="scope">
<el-button link
type="primary"
- size="small"
@click="openForm('edit', scope.row)"
:disabled="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== 4">缂栬緫</el-button>
<el-button link
type="primary"
- size="small"
@click="downLoadFile(scope.row)">闄勪欢</el-button>
</template>
</el-table-column>
@@ -181,12 +221,12 @@
@pagination="paginationChange" />
</div>
<FormDialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
+ :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
<el-form :model="form"
label-width="140px"
label-position="top"
@@ -224,11 +264,12 @@
<el-select v-model="form.supplierId"
placeholder="璇烽�夋嫨"
filterable
- clearable>
+ clearable
+ @change="handleSupplierChange">
<el-option v-for="item in supplierList"
:key="item.id"
:label="item.supplierName"
- :value="item.id" />
+ :value="item.id">{{item.supplierName + '---' + (item.supplierType === 1 ? item.taxpayerIdentificationNum || '鏃�' : '瀵圭')}}</el-option>
</el-select>
</el-form-item>
</el-col>
@@ -296,38 +337,33 @@
<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>
+ <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 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>
+ <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 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>
@@ -338,6 +374,7 @@
<el-form-item label="浜у搧淇℃伅锛�"
prop="entryDate">
<el-button type="primary"
+ v-if="currentSupplierType"
@click="openProductForm('add')">娣诲姞</el-button>
<el-button plain
type="danger"
@@ -365,11 +402,10 @@
: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;">
+ <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>
@@ -412,19 +448,33 @@
show-overflow-tooltip />
<el-table-column label="绋庣巼(%)"
prop="taxRate"
- width="80" />
+ width="80"
+ v-if="currentSupplierType === 1" />
<el-table-column label="鍚◣鍗曚环(鍏�)"
prop="taxInclusiveUnitPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
<el-table-column label="鍚◣鎬讳环(鍏�)"
prop="taxInclusiveTotalPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
<el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
prop="taxExclusiveTotalPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
+ <el-table-column label="鍗曚环锛堝绉侊級"
+ prop="unitPrice"
+ :formatter="formattedNumber"
+ width="150"
+ v-if="currentSupplierType === 2" />
+ <el-table-column label="鎬讳环锛堝绉侊級"
+ prop="totalPrice"
+ :formatter="formattedNumber"
+ width="150"
+ v-if="currentSupplierType === 2" />
<el-table-column label="鏄惁璐ㄦ"
prop="isChecked"
width="150">
@@ -441,7 +491,6 @@
<template #default="scope">
<el-button link
type="primary"
- size="small"
@click="openProductForm('edit', scope.row, scope.$index)">缂栬緫</el-button>
</template>
</el-table-column>
@@ -449,8 +498,8 @@
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="澶囨敞路锛�"
- prop="remark">
- <el-input v-model="form.remark"
+ prop="remarks">
+ <el-input v-model="form.remarks"
placeholder="璇疯緭鍏�"
clearable
type="textarea"
@@ -461,7 +510,7 @@
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="闄勪欢鏉愭枡锛�"
- prop="remark">
+ prop="purchaseLedgerFiles">
<el-upload v-model:file-list="fileList"
:action="upload.url"
multiple
@@ -485,17 +534,50 @@
</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>
<FormDialog v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
+ :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"
+ :rules="getProductRules()"
ref="productFormRef">
<el-row :gutter="30">
<el-col :span="24">
@@ -539,7 +621,8 @@
</el-col>
<el-col :span="12">
<el-form-item label="绋庣巼(%)锛�"
- prop="taxRate">
+ prop="taxRate"
+ v-if="currentSupplierType === 1">
<el-select v-model="productForm.taxRate"
placeholder="璇烽�夋嫨"
clearable
@@ -556,18 +639,6 @@
</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"
- :min="0"
- 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"
@@ -577,14 +648,39 @@
style="width: 100%"
v-model="productForm.quantity"
placeholder="璇疯緭鍏�"
+ @change="currentSupplierType === 1 ? mathNum() : mathNumPrivate()" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
+ prop="taxInclusiveUnitPrice"
+ v-if="currentSupplierType === 1">
+ <el-input-number v-model="productForm.taxInclusiveUnitPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
@change="mathNum" />
+ </el-form-item>
+ <el-form-item label="鍗曚环锛堝绉侊級锛�"
+ prop="unitPrice"
+ v-else>
+ <el-input-number v-model="productForm.unitPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
+ @change="mathNumPrivate" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="鍚◣鎬讳环(鍏�)锛�"
- prop="taxInclusiveTotalPrice">
+ prop="taxInclusiveTotalPrice"
+ v-if="currentSupplierType === 1">
<el-input-number v-model="productForm.taxInclusiveTotalPrice"
:precision="2"
:step="0.1"
@@ -593,10 +689,34 @@
style="width: 100%"
@change="reverseMathNum('taxInclusiveTotalPrice')" />
</el-form-item>
+ <el-form-item label="鎬讳环锛堝绉侊級锛�"
+ prop="totalPrice"
+ v-else>
+ <el-input-number v-model="productForm.totalPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
+ @change="reverseMathNumPrivate('totalPrice')" />
+ </el-form-item>
+ </el-col>
+ <el-col v-if="currentSupplierType === 2"
+ :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>
</el-col>
<el-col :span="12">
<el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice">
+ prop="taxExclusiveTotalPrice"
+ v-if="currentSupplierType === 1">
<el-input-number v-model="productForm.taxExclusiveTotalPrice"
:precision="2"
:step="0.1"
@@ -610,7 +730,8 @@
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="鍙戠エ绫诲瀷锛�"
- prop="invoiceType">
+ prop="invoiceType"
+ v-if="currentSupplierType === 1">
<el-select v-model="productForm.invoiceType"
placeholder="璇烽�夋嫨"
clearable>
@@ -621,7 +742,8 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col v-if="currentSupplierType === 1"
+ :span="12">
<el-form-item label="搴撳瓨棰勮鏁伴噺锛�"
prop="warnNum">
<el-input-number v-model="productForm.warnNum"
@@ -648,11 +770,9 @@
</el-row>
</el-form>
</FormDialog>
- <FileListDialog
- ref="fileListRef"
- v-model="fileListDialogVisible"
- title="闄勪欢鍒楄〃"
- />
+ <FileListDialog ref="fileListRef"
+ v-model="fileListDialogVisible"
+ title="闄勪欢鍒楄〃" />
</div>
</template>
@@ -670,8 +790,8 @@
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 FormDialog from "@/components/Dialog/FormDialog.vue";
+ import FileListDialog from "@/components/Dialog/FileListDialog.vue";
import {
getSalesLedgerWithProducts,
addOrUpdateSalesLedgerProduct,
@@ -706,6 +826,7 @@
const salesContractList = ref([]);
const supplierList = ref([]);
const tableLoading = ref(false);
+ const currentSupplierType = ref(null); // 璺熻釜褰撳墠閫夋嫨鐨勪緵搴斿晢绫诲瀷
const page = reactive({
current: 1,
size: 100,
@@ -724,11 +845,31 @@
const addApproverNode = () => {
approverNodes.value.push({ id: nextApproverId++, userId: null });
};
- const removeApproverNode = (index) => {
+ const removeApproverNode = index => {
approverNodes.value.splice(index, 1);
};
- // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+ // 澶勭悊渚涘簲鍟嗛�夋嫨鍙樺寲
+ const handleSupplierChange = async supplierId => {
+ const selectedSupplier = supplierList.value.find(
+ item => item.id === supplierId
+ );
+ if (selectedSupplier) {
+ // 鍙湁褰撳綋鍓嶄緵搴斿晢绫诲瀷涓嶄负 null 涓斿彂鐢熷彉鍖栨椂锛屾墠娓呯┖浜у搧琛�
+ // 杩欐牱鍦ㄧ紪杈戞椂鍔犺浇鏁版嵁鍚庤皟鐢ㄨ鍑芥暟涓嶄細娓呯┖浜у搧鏁版嵁
+ if (
+ currentSupplierType.value !== null &&
+ currentSupplierType.value !== selectedSupplier.supplierType
+ ) {
+ productData.value = [];
+ }
+ currentSupplierType.value = selectedSupplier.supplierType;
+ } else {
+ currentSupplierType.value = null;
+ productData.value = [];
+ }
+ await getTemplateList();
+ };
const approvalStatusText = {
1: "寰呭鏍�",
2: "瀹℃壒涓�",
@@ -737,12 +878,12 @@
};
// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
- const getApprovalStatusType = (status) => {
+ const getApprovalStatusType = status => {
const typeMap = {
- 1: "info", // 寰呭鏍� - 鐏拌壊
- 2: "warning", // 瀹℃壒涓� - 姗欒壊
- 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
- 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
};
return typeMap[status] || "";
};
@@ -824,7 +965,8 @@
form.value.paymentMethod = matchedTemplate.paymentMethod;
}
// 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
- productData.value = matchedTemplate.productList || matchedTemplate.productData || [];
+ productData.value =
+ matchedTemplate.productList || matchedTemplate.productData || [];
} else {
// 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
currentTemplateId.value = null;
@@ -860,6 +1002,7 @@
entryDate: null, // 褰曞叆鏃ユ湡
entryDateStart: undefined,
entryDateEnd: undefined,
+ supplierType: "", // 渚涘簲鍟嗙被鍨�
},
form: {
purchaseContractNumber: "",
@@ -943,12 +1086,118 @@
},
});
const { productForm, productRules } = toRefs(productFormData);
+ const getProductRules = () => {
+ const baseRules = {
+ productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ };
+
+ if (currentSupplierType.value === 1) {
+ // 瀵瑰叕渚涘簲鍟嗛渶瑕侀獙璇佺殑瀛楁
+ return {
+ ...baseRules,
+ 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" }],
+ };
+ } else if (currentSupplierType.value === 2) {
+ // 瀵圭渚涘簲鍟嗛渶瑕侀獙璇佺殑瀛楁
+ return {
+ ...baseRules,
+ unitPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ totalPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ };
+ } else {
+ return baseRules;
+ }
+ };
const upload = reactive({
// 涓婁紶鐨勫湴鍧�
url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
// 璁剧疆涓婁紶鐨勮姹傚ご閮�
headers: { Authorization: "Bearer " + getToken() },
});
+
+ // 瀵煎叆鐩稿叧
+ 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 handleImport = () => {
+ importUpload.title = "瀵煎叆閲囪喘鍙拌处";
+ importUpload.open = true;
+ importUpload.isUploading = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles?.();
+ }
+ };
+
+ // 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
+ const downloadTemplate = () => {
+ proxy.download(
+ "/purchase/ledger/exportTemplate",
+ {},
+ "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
+ );
+ };
+
+ const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"]?.submit?.();
+ };
const changeDaterange = value => {
if (value) {
@@ -1007,8 +1256,8 @@
// 妫�鏌ユ槸鍚︽湁浜у搧鏁版嵁
if (!productData.value || productData.value.length === 0) {
ElMessage({
- message: '璇峰厛娣诲姞浜у搧淇℃伅',
- type: 'warning',
+ message: "璇峰厛娣诲姞浜у搧淇℃伅",
+ type: "warning",
});
return;
}
@@ -1019,7 +1268,7 @@
.filter(node => node.userId)
.map(node => node.userId)
.join(",");
-
+
let params = {
productData: proxy.HaveJson(productData.value),
supplierId: form.value.supplierId,
@@ -1029,7 +1278,12 @@
approveUserIds: approveUserIds,
templateName: templateName.value.trim(),
};
- console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
+ console.log(
+ "template params ===>",
+ params,
+ "currentTemplateId:",
+ currentTemplateId.value
+ );
// 濡傛灉 currentTemplateId 鏈夊�硷紝璇存槑褰撳墠鏄�滅紪杈戝凡鏈夋ā鏉库�� 鈫� 璋冪敤鏇存柊鎺ュ彛
// 鍚﹀垯涓衡�滄柊寤烘ā鏉库�� 鈫� 璋冪敤鏂板鎺ュ彛
@@ -1040,7 +1294,10 @@
...params,
});
} else {
- res = await addPurchaseTemplate(params);
+ res = await addPurchaseTemplate({
+ ...params,
+ templateType: currentSupplierType.value,
+ });
}
if (res && res.code === 200) {
@@ -1072,22 +1329,34 @@
};
// 瀛愯〃鍚堣鏂规硶
const summarizeChildrenTable = param => {
- return proxy.summarizeTable(
- param,
- [
+ // 妫�鏌ユ槸鍚︽湁鏁版嵁锛屼互鍙婃暟鎹殑渚涘簲鍟嗙被鍨�
+ const hasData = param && param.data && param.data.length > 0;
+ const supplierType = hasData ? param.data[0].supplierType : null;
+
+ // 鏍规嵁渚涘簲鍟嗙被鍨嬬‘瀹氳鍚堣鐨勫瓧娈�
+ const fields = [
+ "ticketsNum",
+ "ticketsAmount",
+ "futureTickets",
+ "futureTicketsAmount",
+ ];
+
+ if (supplierType === 1) {
+ // 瀵瑰叕渚涘簲鍟�
+ fields.unshift(
"taxInclusiveUnitPrice",
"taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "ticketsNum",
- "ticketsAmount",
- "futureTickets",
- "futureTicketsAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
+ "taxExclusiveTotalPrice"
+ );
+ } else if (supplierType === 2) {
+ // 瀵圭渚涘簲鍟�
+ fields.unshift("unitPrice", "totalPrice");
+ }
+
+ return proxy.summarizeTable(param, fields, {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ });
};
const paginationChange = obj => {
page.current = obj.page;
@@ -1131,7 +1400,12 @@
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 || [];
+ // 涓哄瓙琛ㄦ牸鏁版嵁娣诲姞渚涘簲鍟嗙被鍨嬩俊鎭�
+ const children = (res.data || []).map(item => ({
+ ...item,
+ supplierType: row.supplierType, // 浠庣埗琛岃幏鍙栦緵搴斿晢绫诲瀷
+ }));
+ tableData.value[index].children = children;
expandedRowKeys.value.push(row.id);
}
} catch (error) {
@@ -1153,11 +1427,17 @@
};
// 瀛愯〃鍚堣鏂规硶
const summarizeProTable = param => {
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
+ const fields = [];
+ if (currentSupplierType.value === 1) {
+ fields.push(
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice"
+ );
+ } else if (currentSupplierType.value === 2) {
+ fields.push("unitPrice", "totalPrice");
+ }
+ return proxy.summarizeTable(param, fields);
};
// 鎵撳紑寮规
const openForm = async (type, row) => {
@@ -1168,8 +1448,8 @@
return;
}
}
-
- await getTemplateList();
+ currentSupplierType.value = null;
+
operationType.value = type;
form.value = {};
productData.value = [];
@@ -1200,6 +1480,7 @@
form.value.entryDate = getCurrentDate();
if (type === "add") {
+ await getTemplateList();
// 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
try {
const purchaseNoRes = await createPurchaseNo();
@@ -1223,9 +1504,13 @@
const approverIds = purchaseRes.approveUserIds.split(",");
approverNodes.value = approverIds.map((id, index) => ({
id: index + 1,
- userId: Number(id)
+ userId: Number(id),
}));
nextApproverId = approverIds.length + 1;
+ }
+ // 璁剧疆褰撳墠渚涘簲鍟嗙被鍨�
+ if (form.value.supplierId) {
+ handleSupplierChange(form.value.supplierId);
}
} catch (error) {
console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
@@ -1301,8 +1586,10 @@
proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
return;
}
- const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
-
+ const approveUserIds = approverNodes.value
+ .map(node => node.userId)
+ .join(",");
+
if (productData.value.length > 0) {
// 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
let processedProductData = productData.value;
@@ -1331,7 +1618,10 @@
}
// 鏂板鏃朵笉浼犻�抜d
- const submitData = { ...form.value };
+ const submitData = {
+ ...form.value,
+ purchaseType: currentSupplierType.value,
+ };
if (operationType.value === "add") {
delete submitData.id;
}
@@ -1356,20 +1646,39 @@
const openProductForm = async (type, row, index) => {
productOperationType.value = type;
productOperationIndex.value = index;
- productForm.value = {};
+ productForm.value = {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ // 瀵瑰叕瀛楁
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ // 瀵圭瀛楁
+ unitPrice: "",
+ totalPrice: "",
+ // 鍏叡瀛楁
+ warnNum: "",
+ isChecked: true,
+ };
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) {
@@ -1380,25 +1689,34 @@
return nodes[i].value;
}
if (nodes[i].children && nodes[i].children.length > 0) {
- const found = findProductIdByCategory(nodes[i].children, categoryName);
+ const found = findProductIdByCategory(
+ nodes[i].children,
+ categoryName
+ );
if (found) return found;
}
}
return null;
};
-
- const productId = findProductIdByCategory(productOptions.value, productForm.value.productCategory);
+
+ 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) {
+ if (
+ productForm.value.specificationModel &&
+ modelOptions.value.length > 0
+ ) {
const modelItem = modelOptions.value.find(
item => item.model === productForm.value.specificationModel
);
@@ -1412,15 +1730,15 @@
} 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();
}
@@ -1504,15 +1822,21 @@
});
};
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;
- });
- });
+ // 鐩存帴淇敼鏈湴鏁版嵁锛屼笉鍐嶈皟鐢ㄦ帴鍙�
+ if (productOperationType.value === "add") {
+ // 鏂板浜у搧
+ productData.value.push({ ...productForm.value });
+ } else if (productOperationType.value === "edit") {
+ // 缂栬緫浜у搧
+ if (
+ productOperationIndex.value !== "" &&
+ productOperationIndex.value !== null
+ ) {
+ productData.value[productOperationIndex.value] = { ...productForm.value };
+ }
+ }
+ proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
+ closeProductDia();
};
// 鍒犻櫎浜у搧
const deleteProduct = () => {
@@ -1520,40 +1844,27 @@
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("宸插彇娑�");
+ // 鐩存帴浠庢湰鍦版暟鎹腑鍒犻櫎锛屼笉鍐嶈皟鐢ㄦ帴鍙�
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ productSelectedRows.value.forEach(selectedRow => {
+ const index = productData.value.findIndex(
+ product => product.id === selectedRow.id
+ );
+ if (index !== -1) {
+ productData.value.splice(index, 1);
+ }
});
- }
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍏抽棴浜у搧寮规
const closeProductDia = () => {
@@ -1578,14 +1889,6 @@
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("璇烽�夋嫨鏁版嵁");
@@ -1727,6 +2030,27 @@
}
}
};
+
+ // 瀵圭渚涘簲鍟嗙殑浠锋牸璁$畻
+ const mathNumPrivate = () => {
+ const { unitPrice, quantity } = productForm.value;
+ if (unitPrice && quantity) {
+ productForm.value.totalPrice = (unitPrice * quantity).toFixed(2);
+ }
+ };
+
+ // 瀵圭渚涘簲鍟嗙殑鍙嶅悜浠锋牸璁$畻
+ const reverseMathNumPrivate = type => {
+ const { unitPrice, quantity, totalPrice } = productForm.value;
+ if (type === "totalPrice") {
+ if (quantity) {
+ productForm.value.unitPrice = (totalPrice / quantity).toFixed(2);
+ } else if (unitPrice) {
+ productForm.value.quantity = (totalPrice / unitPrice).toFixed(2);
+ }
+ }
+ };
+
// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
const salesLedgerChange = async row => {
console.log("row", row);
@@ -1756,19 +2080,26 @@
// 鑾峰彇妯℃澘淇℃伅
const getTemplateList = async () => {
- let res = await getPurchaseTemplateList();
- if (res && res.code === 200 && Array.isArray(res.data)) {
- templateList.value = res.data;
+ console.log("currentSupplierType.value", currentSupplierType.value);
+ if (currentSupplierType.value) {
+ let res = await getPurchaseTemplateList({
+ templateType: currentSupplierType.value,
+ });
+ if (res && res.code === 200 && Array.isArray(res.data)) {
+ templateList.value = res.data;
+ }
+ } else {
+ templateList.value = [];
}
};
// 鍒犻櫎妯℃澘
- const handleDeleteTemplate = async (item) => {
+ const handleDeleteTemplate = async item => {
if (!item.id) {
proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
return;
}
-
+
try {
await ElMessageBox.confirm(
`纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
@@ -1779,7 +2110,7 @@
type: "warning",
}
);
-
+
const res = await delPurchaseTemplate([item.id]);
if (res && res.code === 200) {
ElMessage({
@@ -1832,7 +2163,7 @@
display: flex;
align-items: center;
}
-
+
// 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
.approver-nodes-container {
display: flex;
@@ -1843,7 +2174,7 @@
border-radius: 4px;
border: 1px solid #e4e7ed;
}
-
+
.approver-node-item {
flex: 0 0 calc(33.333% - 12px);
min-width: 200px;
@@ -1852,38 +2183,38 @@
border-radius: 4px;
border: 1px solid #dcdfe6;
transition: all 0.3s;
-
+
&:hover {
border-color: #409eff;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}
}
-
+
.approver-node-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
-
+
.approver-node-label {
font-size: 13px;
font-weight: 500;
color: #606266;
}
-
+
@media (max-width: 1200px) {
.approver-node-item {
flex: 0 0 calc(50% - 8px);
}
}
-
+
@media (max-width: 768px) {
.approver-node-item {
flex: 0 0 100%;
}
}
-
+
// 鍒犻櫎鍥炬爣鏍峰紡
.delete-icon {
transition: all 0.3s;
--
Gitblit v1.9.3