From aaa700a2efc44c2f633f2c83885bc67ddcbcd770 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期三, 23 九月 2026 09:10:36 +0800
Subject: [PATCH] feat: 台账品名/材质/规格手工录入与产品编号选填、审批模板启用锁定编辑
---
src/views/procurementManagement/procurementLedger/index.vue | 354 +++++++++++++++++++++++------------------------------------
1 files changed, 138 insertions(+), 216 deletions(-)
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index dad6a26..fa55d87 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -66,6 +66,9 @@
</div>
<div class="table_list">
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
+ <el-button type="success"
+ plain
+ @click="handleBatchGenerate">鎵归噺鐢熸垚鏁版嵁</el-button>
<el-button type="primary"
@click="openForm('add')">鏂板鍙拌处</el-button>
<el-button type="primary"
@@ -102,11 +105,13 @@
width="60" />
<el-table-column label="浜у搧澶х被"
prop="productCategory" />
+ <el-table-column label="鏉愯川"
+ prop="material" />
<el-table-column label="瑙勬牸鍨嬪彿"
prop="specificationModel" />
<el-table-column label="鍗曚綅"
prop="unit" />
- <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
+ <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
prop="stockInApprovalStatus"
width="120">
<template #default="scope">
@@ -118,10 +123,12 @@
</el-table-column>
<el-table-column label="鏁伴噺"
prop="quantity" />
+ <el-table-column label="閿�鍞彂璐ф暟閲�"
+ prop="shippedQuantity" />
<el-table-column label="鍙敤鏁伴噺"
prop="availableQuality" />
<el-table-column label="閫�璐ф暟閲�"
- prop="returnQuality" />
+ prop="returnQuantity" />
<el-table-column label="绋庣巼(%)"
prop="taxRate" />
<el-table-column label="鍚◣鍗曚环(鍏�)"
@@ -144,10 +151,10 @@
prop="purchaseContractNumber"
width="160"
show-overflow-tooltip />
- <el-table-column label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- width="160"
- show-overflow-tooltip />
+<!-- <el-table-column label="閿�鍞悎鍚屽彿"-->
+<!-- prop="salesContractNo"-->
+<!-- width="160"-->
+<!-- show-overflow-tooltip />-->
<el-table-column label="渚涘簲鍟嗗悕绉�"
prop="supplierName"
width="160"
@@ -191,6 +198,11 @@
width="200"
show-overflow-tooltip
:formatter="formattedNumber" />
+ <el-table-column label="瀹為檯鍚堝悓閲戦(鍏�)"
+ prop="netContractAmount"
+ width="200"
+ show-overflow-tooltip
+ :formatter="(_, __, cellValue) => formatMoney(cellValue)" />
<el-table-column label="褰曞叆浜�"
prop="recorderName"
width="120"
@@ -211,7 +223,7 @@
<el-button link
type="primary"
@click="openForm('edit', scope.row)"
- :disabled="scope.row.stockInStatus === '瀹屽叏鍏ュ簱'">缂栬緫
+ :disabled="scope.row.approvalStatus === 3">缂栬緫
</el-button>
<el-button link
type="primary"
@@ -247,21 +259,21 @@
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-select>
- </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-select>-->
+<!-- </el-form-item>-->
+<!-- </el-col>-->
</el-row>
<el-row :gutter="30">
<el-col :span="12">
@@ -402,6 +414,8 @@
width="60" />
<el-table-column label="浜у搧澶х被"
prop="productCategory" />
+ <el-table-column label="鏉愯川"
+ prop="material" />
<el-table-column label="瑙勬牸鍨嬪彿"
prop="specificationModel" />
<el-table-column label="鍗曚綅"
@@ -530,34 +544,31 @@
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="productCategory">
+ <el-input v-model="productForm.productCategory"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鏉愯川锛�"
+ prop="material">
+ <el-input v-model="productForm.material"
+ placeholder="璇疯緭鍏�"
+ clearable />
</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-select>
+ prop="specificationModel">
+ <el-input v-model="productForm.specificationModel"
+ placeholder="璇疯緭鍏�"
+ clearable />
</el-form-item>
</el-col>
</el-row>
@@ -721,6 +732,7 @@
getOptions,
getPurchaseTemplateList,
delPurchaseTemplate,
+ batchGeneratePurchaseInboundSteps,
} from "@/api/procurementManagement/procurementLedger.js";
import useFormData from "@/hooks/useFormData.js";
const FileList = defineAsyncComponent(() =>
@@ -733,9 +745,7 @@
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);
@@ -748,7 +758,6 @@
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";
import FileUpload from "@/components/AttachmentUpload/file/index.vue";
@@ -776,9 +785,9 @@
// 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
const getStockInStatusType = status => {
const typeMap = {
- "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
- "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
- "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+ 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+ 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
};
return typeMap[status] || "";
};
@@ -786,9 +795,9 @@
// 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
const getStockInApprovalStatusType = status => {
const typeMap = {
- "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
- "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
- "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+ 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+ 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
};
return typeMap[status] || "";
};
@@ -923,7 +932,7 @@
},
rules: {
purchaseContractNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ { required: false, message: "璇疯緭鍏�", trigger: "blur" },
],
projectName: [
{ required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" },
@@ -934,16 +943,7 @@
},
});
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"),
- ],
- entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"),
- entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"),
- });
+ const { form: searchForm } = useFormData(data.searchForm);
// 浜у搧琛ㄥ崟寮规鏁版嵁
const productFormVisible = ref(false);
@@ -952,9 +952,8 @@
const currentId = ref("");
const productFormData = reactive({
productForm: {
- productId: "",
productCategory: "",
- productModelId: "",
+ material: "",
specificationModel: "",
unit: "",
quantity: "",
@@ -967,8 +966,11 @@
isChecked: false,
},
productRules: {
- productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productCategory: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ material: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ specificationModel: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
taxInclusiveUnitPrice: [
@@ -1260,7 +1262,14 @@
};
// 涓昏〃鍚堣鏂规硶
const summarizeMainTable = param => {
- return proxy.summarizeTable(param, ["contractAmount"]);
+ return proxy.summarizeTable(param, ["contractAmount", "netContractAmount"]);
+ };
+ const formatMoney = value => {
+ if (value === null || value === undefined || value === "") {
+ return "--";
+ }
+ const num = Number(value);
+ return Number.isFinite(num) ? num.toFixed(2) : "--";
};
// 瀛愯〃鍚堣鏂规硶
const summarizeProTable = param => {
@@ -1274,7 +1283,7 @@
const openForm = async (type, row) => {
// 缂栬緫鏃舵鏌ュ叆搴撶姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
if (type === "edit" && row) {
- if (row.stockInStatus === '瀹屽叏鍏ュ簱') {
+ if (row.stockInStatus === "瀹屽叏鍏ュ簱") {
proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑璁板綍涓嶈兘缂栬緫");
return;
}
@@ -1306,18 +1315,7 @@
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) {
+ if (type === "edit" && row?.id) {
// 缂栬緫鏃跺姞杞芥暟鎹�
currentId.value = row.id;
try {
@@ -1325,7 +1323,10 @@
form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
fileList.value = purchaseRes.storageBlobVOS || [];
// 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
- const productRes = await productList({ salesLedgerId: row.id, type: 2 });
+ const productRes = await productList({
+ salesLedgerId: row.id,
+ type: 2,
+ });
productData.value = productRes.data || [];
} catch (error) {
console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
@@ -1398,7 +1399,7 @@
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
- proxy.$refs["formRef"].validate(valid => {
+ proxy.$refs["formRef"].validate(async valid => {
if (valid) {
if (productData.value.length > 0) {
// 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
@@ -1428,6 +1429,20 @@
delete submitData.id;
}
+ // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
+ if (!submitData.purchaseContractNumber) {
+ try {
+ const purchaseNoRes = await createPurchaseNo(submitData.entryDate);
+ if (purchaseNoRes?.data) {
+ submitData.purchaseContractNumber = purchaseNoRes.data;
+ }
+ } catch (error) {
+ console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+ proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
+ return;
+ }
+ }
+
addOrEditPurchase(submitData).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
@@ -1442,9 +1457,9 @@
dialogFormVisible.value = false;
};
// 鎵撳紑浜у搧寮规
- const openProductForm = async (type, row, index) => {
+ const openProductForm = (type, row, index) => {
// 缂栬緫鏃舵鏌ヤ骇鍝佸叆搴撳鏍哥姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
- if (type === "edit" && row && row.stockInApprovalStatus === '瀹屽叏鍏ュ簱') {
+ if (type === "edit" && row && row.stockInApprovalStatus === "瀹屽叏鍏ュ簱") {
proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑浜у搧涓嶈兘缂栬緫");
return;
}
@@ -1455,12 +1470,6 @@
proxy.resetForm("productFormRef");
productFormVisible.value = true;
- // 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
- await getProductOptions();
-
- // 绛夊緟 DOM 鏇存柊
- await nextTick();
-
if (type === "add") {
productForm.value.isChecked = false;
}
@@ -1468,130 +1477,8 @@
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;
- });
- } 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 = () => {
@@ -1627,13 +1514,17 @@
};
// 鍒犻櫎浜у搧
const deleteProduct = () => {
+ if (productData.value.length <= 1) {
+ proxy.$modal.msgWarning("閲囪喘鍙拌处鑷冲皯闇�瑕佷繚鐣欎竴鏉′骇鍝佹暟鎹�");
+ return;
+ }
if (productSelectedRows.value.length === 0) {
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
// 妫�鏌ラ�変腑鐨勪骇鍝佷腑鏄惁鏈夊畬鍏ㄥ叆搴撶殑
const hasFullyStocked = productSelectedRows.value.some(
- row => row.stockInApprovalStatus === '瀹屽叏鍏ュ簱'
+ row => row.stockInApprovalStatus === "瀹屽叏鍏ュ簱"
);
if (hasFullyStocked) {
proxy.$modal.msgWarning("閫変腑鐨勪骇鍝佷腑鍖呭惈瀹屽叏鍏ュ簱鐨勪骇鍝侊紝鏃犳硶鍒犻櫎");
@@ -1709,6 +1600,37 @@
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ const handleBatchGenerate = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map((item) => item.id);
+
+ ElMessageBox.confirm("纭鎵归噺鐢熸垚鏁版嵁锛�", "鎵归噺鐢熸垚", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "info",
+ })
+ .then(() => {
+ proxy.$modal.loading("姝e湪鎵归噺鐢熸垚鏁版嵁锛岃绋嶅��...");
+ batchGeneratePurchaseInboundSteps({ ids })
+ .then((res) => {
+ proxy.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鎵归噺鐢熸垚澶辫触");
+ })
+ .finally(() => {
+ proxy.$modal.closeLoading();
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
@@ -1852,7 +1774,7 @@
contractNo: form.value.salesLedgerId,
});
if (code == 200) {
- productData.value = data;
+ productData.value = data || [];
}
};
--
Gitblit v1.9.3