From f02160e1f583f063dc01499634311ef981cfe894 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 27 一月 2026 16:40:05 +0800
Subject: [PATCH] 库存管理: 新增库存增加预警数量
---
src/views/inventoryManagement/stockManagement/index.vue | 593 ++---------------------------------------------------------
1 files changed, 21 insertions(+), 572 deletions(-)
diff --git a/src/views/inventoryManagement/stockManagement/index.vue b/src/views/inventoryManagement/stockManagement/index.vue
index 08d05bd..347de38 100644
--- a/src/views/inventoryManagement/stockManagement/index.vue
+++ b/src/views/inventoryManagement/stockManagement/index.vue
@@ -1,584 +1,33 @@
<template>
<div class="app-container">
- <el-tabs v-model="activeTab"
- @tab-change="handleTabChange">
- <el-tab-pane label="鎴愬搧搴撳瓨"
- name="production">
- <div class="search_form">
- <div>
- <span class="search_title ml10">鍏ュ簱鏃ユ湡锛�</span>
- <el-date-picker v-model="searchForm.timeStr"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- @change="handleQuery" />
- <span class="search_title ml10">浜у搧澶х被锛�</span>
- <el-input v-model="searchForm.productCategory"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- clearable />
- <el-button type="primary"
- @click="handleQuery"
- style="margin-left: 10px">鎼滅储</el-button>
- </div>
- <div>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- <!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
- </div>
- </div>
- <div class="table_list">
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="row => row.id"
- show-summary
- style="width: 100%"
- :row-class-name="tableRowClassName"
- :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="productName"
- width="180"
- show-overflow-tooltip />
- <el-table-column label="浜у搧缂栧彿"
- prop="productCode"
- width="180"
- show-overflow-tooltip />
- <el-table-column label="浜у搧瑙勬牸"
- prop="model"
- show-overflow-tooltip />
- <el-table-column label="鍗曚綅"
- prop="unit"
- width="80"
- show-overflow-tooltip />
- <el-table-column label="宸插嚭搴撴暟閲�"
- prop="outboundNum"
- show-overflow-tooltip />
- <el-table-column label="鍓╀綑搴撳瓨"
- prop="stockQuantity"
- show-overflow-tooltip />
- <!-- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
- <template #default="scope">
- <el-button link type="primary" size="small" @click="openForm('edit', 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-tab-pane>
- <el-tab-pane label="鍘熸枡搴撳瓨"
- name="purchase">
- <div class="search_form">
- <div>
- <span class="search_title ml10">鍏ュ簱鏃ユ湡锛�</span>
- <el-date-picker v-model="searchForm.timeStr"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- @change="handleQuery" />
- <span class="search_title ml10">浜у搧澶х被锛�</span>
- <el-input v-model="searchForm.productCategory"
- style="width: 240px"
- placeholder="璇疯緭鍏�"
- clearable />
- <el-button type="primary"
- @click="handleQuery"
- style="margin-left: 10px">鎼滅储</el-button>
- </div>
- <div>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- <!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
- </div>
- </div>
- <div class="table_list">
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="row => row.id"
- show-summary
- style="width: 100%"
- :row-class-name="tableRowClassName"
- :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="purchaseContractNumber"
- width="180"
- show-overflow-tooltip />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory"
- show-overflow-tooltip />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- show-overflow-tooltip />
- <el-table-column label="鍗曚綅"
- prop="unit"
- width="80"
- show-overflow-tooltip />
- <el-table-column label="宸插嚭搴撴暟閲�"
- prop="totalInboundNum"
- show-overflow-tooltip />
- <el-table-column label="鍓╀綑搴撳瓨"
- prop="inboundNum0"
- show-overflow-tooltip />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- width="150"></el-table-column>
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- width="150"></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-tabs v-model="activeTab" @tab-change="handleTabChange">
+ <el-tab-pane v-for="tab in tabs"
+ :label="tab.label"
+ :name="tab.name"
+ :key="tab.name">
+ <component :is="tab.name === 'qualified' ? QualifiedRecord : UnqualifiedRecord" />
</el-tab-pane>
</el-tabs>
- <!-- 鎴愬搧搴撳瓨寮规 -->
- <FormDiaProduction v-model:dialogFormVisible="productionDialogVisible"
- :operationType="operationType"
- :formData="form"
- @submit="submitForm"
- @close="closeDia" />
- <!-- 鍘熸枡搴撳瓨寮规 -->
- <FormDiaPurchase v-model:dialogFormVisible="purchaseDialogVisible"
- :operationType="operationType"
- :formData="form"
- @submit="submitForm"
- @close="closeDia" />
</div>
</template>
<script setup>
- import pagination from "@/components/PIMTable/Pagination.vue";
- import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
- import { ElMessageBox } from "element-plus";
- import useUserStore from "@/store/modules/user";
- import { userListNoPageByTenantId } from "@/api/system/user.js";
- import { productTreeList, modelList } from "@/api/basicData/product.js";
- import {
- getStockManagePage,
- getStockManagePageByProduction,
- delStockManage, getStockManageProduction,
- } from "@/api/inventoryManagement/stockManage.js";
- import {
- updateManagement,
- updateManagementByCustom,
- updateStockIn,
- } from "@/api/inventoryManagement/stockIn.js";
+import QualifiedRecord from "@/views/inventoryManagement/stockManagement/Qualified.vue";
+import UnqualifiedRecord from "@/views/inventoryManagement/stockManagement/Unqualified.vue";
- // 瀵煎叆涓や釜鐙珛鐨勫脊妗嗙粍浠�
- import FormDiaProduction from "./components/FormDiaProduction.vue";
- import FormDiaPurchase from "./components/FormDiaPurchase.vue";
-
- const userStore = useUserStore();
- const { proxy } = getCurrentInstance();
- const tableData = ref([]);
- const productData = ref([]);
- const selectedRows = ref([]);
- const userList = ref([]);
- const productList = ref([]);
- const productModelList = ref([]);
- // const customerOption = ref([])
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
- const fileList = ref([]);
- const loading = ref(false);
- // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
- const operationType = ref("");
- const activeTab = ref("production");
-
- // 寮规鏄剧ず鐘舵��
- const productionDialogVisible = ref(false);
- const purchaseDialogVisible = ref(false);
-
- const data = reactive({
- searchForm: {
- // supplierName: '',
- productCategory: "",
- customerName: "",
- timeStr: "",
- },
- form: {
- supplierId: null,
- // supplierName: '',
- productId: null,
- productName: "",
- userId: userStore.userId,
- nickName: "",
- productModelId: null,
- model: "",
- unit: "",
- productrecordId: null,
- unitPrice: "", // 娣诲姞鎴愬搧搴撳瓨鐨勫崟浠峰瓧娈�
- taxInclusiveUnitPrice: "",
- taxInclusiveTotalPrice: "",
- taxRate: "",
- taxExclusiveTotalPrice: "",
- inboundTime: "",
- inboundBatch: "",
- stockQuantity: "",
- boundTime: "",
- warnNum: "", // 鏂板鏈�浣庡簱瀛樺瓧娈�
- salesLedgerProductId: null,
- },
- rules: {
- // supplierName: [{ required: true, message: '璇疯緭鍏ヤ緵搴斿晢鍚嶇О', trigger: 'blur' }],
- productCategory: [
- { required: true, message: "璇烽�夋嫨浜у搧澶х被", trigger: "change" },
- ],
- specificationModel: [
- { required: true, message: "璇疯緭鍏ヨ鏍煎瀷鍙�", trigger: "blur" },
- ],
- unit: [{ required: true, message: "璇疯緭鍏ュ崟浣�", trigger: "blur" }],
- stockQuantity: [
- { required: true, message: "璇疯緭鍏ュ嚭搴撴暟閲�", trigger: "blur" },
- ],
- unitPrice: [{ required: true, message: "璇疯緭鍏ュ崟浠�", trigger: "blur" }], // 娣诲姞鎴愬搧搴撳瓨鍗曚环鐨勯獙璇佽鍒�
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏ュ惈绋庡崟浠�", trigger: "blur" },
- ],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏ュ惈绋庢�讳环", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇疯緭鍏ョ◣鐜�", trigger: "blur" }],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏ヤ笉鍚◣鎬讳环", trigger: "blur" },
- ],
- boundTime: [
- { required: true, message: "璇烽�夋嫨搴撳瓨鏃堕棿", trigger: "change" },
- ],
- inboundTime: [
- { required: true, message: "璇烽�夋嫨鍏ュ簱鏃堕棿", trigger: "change" },
- ],
- inboundPerson: [
- { required: true, message: "璇烽�夋嫨鍑哄簱浜�", trigger: "change" },
- ],
- warnNum: [{ required: true, message: "璇疯緭鍏ユ渶浣庡簱瀛�", trigger: "blur" }],
- },
- });
- 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 buildQueryParams = () => {
- const params = {
- ...page,
- timeStr: searchForm.value.timeStr,
- };
- params.productCategory = searchForm.value.productCategory;
- if (activeTab.value === "production") {
- params.customerName = searchForm.value.customerName;
- } else {
- // params.supplierName = searchForm.value.supplierName
- }
- return params;
- };
-
- const getList = () => {
- tableLoading.value = true;
- const params = buildQueryParams();
- const apiCall =
- activeTab.value === "production"
- ? getStockManageProduction(params)
- : getStockManagePage(params);
- apiCall
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
-
- // 涓鸿〃鏍兼暟鎹嚜鍔ㄨ绠楁�讳环
- // tableData.value = tableData.value.map(item => {
- // // 璁$畻鍓╀綑搴撳瓨
- // const stockQuantity = parseFloat(item.inboundNum) || 0;
- // const outboundQuantity = parseFloat(item.totalInboundNum) || 0;
- // const remainingStock = Math.max(stockQuantity - outboundQuantity, 0);
- //
- // // 鏍规嵁鏍囩椤电被鍨嬭绠楁�讳环
- // if (activeTab.value === "production") {
- // // 鎴愬搧搴撳瓨锛氭�讳环 = 鍗曚环 脳 鍓╀綑搴撳瓨
- // const unitPrice = parseFloat(item.unitPrice) || 0;
- // item.totalPrice = (unitPrice * remainingStock).toFixed(2);
- // } else if (activeTab.value === "purchase") {
- // // 鍘熸枡搴撳瓨锛氬惈绋庢�讳环 = 鍚◣鍗曚环 脳 鍓╀綑搴撳瓨
- // const taxInclusiveUnitPrice =
- // parseFloat(item.taxInclusiveUnitPrice) || 0;
- // item.taxInclusiveTotalPrice = (
- // taxInclusiveUnitPrice * remainingStock
- // ).toFixed(2);
- // }
- //
- // return item;
- // });
-
- total.value = res.data.total;
- // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
- // checkStockAndCreatePurchase();
- })
- .catch(() => {
- tableLoading.value = false;
- });
- };
-
- // 鍒囨崲 tab
- const handleTabChange = () => {
- page.current = 1;
- // searchForm.value.supplierName = ''
- searchForm.value.customerName = "";
- searchForm.value.timeStr = "";
- selectedRows.value = [];
- searchForm.value.productCategory = "";
- getList();
- };
-
- // 琛ㄦ牸閫夋嫨鏁版嵁
- 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 tableRowClassName = ({ row }) => {
- const stock = Number(row?.inboundNum0 ?? 0);
- const warn = Number(row?.warnNum ?? 0);
- if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
- return "";
- }
- return stock < warn ? "row-low-stock" : "";
- };
-
- // 鎵撳紑寮规
- const openForm = async (type, row) => {
- operationType.value = type;
- form.value = {};
- productData.value = [];
- let userLists = await userListNoPageByTenantId();
- userList.value = userLists.data;
- if (type === "edit") {
- form.value = { ...row };
- productTreeList().then(res => {
- productList.value = res;
- productList.value.forEach(i => {
- if (i.label === row.productCategory) {
- modelList({ id: i.id }).then(res => {
- productModelList.value = res;
- });
- }
- });
- });
- }
- form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
-
- // 鏍规嵁褰撳墠鏍囩椤垫樉绀哄搴旂殑寮规
- if (activeTab.value === "production") {
- productionDialogVisible.value = true;
- } else if (activeTab.value === "purchase") {
- purchaseDialogVisible.value = true;
- }
- };
-
- // 鎻愪氦琛ㄥ崟
- const submitForm = submittedData => {
- console.log("瀛愮粍浠舵彁浜ょ殑鏁版嵁:", submittedData);
-
- // 浣跨敤瀛愮粍浠舵彁浜ょ殑鏁版嵁锛岃�屼笉鏄埗缁勪欢鐨刦orm瀵硅薄
- const submitData = { ...submittedData };
-
- // 鏍规嵁褰撳墠鏍囩椤电Щ闄ゅ搴旂殑鎬讳环瀛楁
- if (activeTab.value === "production") {
- // 鎴愬搧搴撳瓨锛氱Щ闄ゆ�讳环瀛楁
- delete submitData.totalPrice;
- } else if (activeTab.value === "purchase") {
- // 鍘熸枡搴撳瓨锛氱Щ闄ゅ惈绋庢�讳环瀛楁
- delete submitData.taxInclusiveTotalPrice;
- }
-
- // 绉婚櫎鍏朵粬鍙兘鐨勬�讳环瀛楁
- delete submitData.taxExclusiveTotalPrice;
-
- console.log("鎻愪氦缁欏悗绔殑鏁版嵁锛堝凡绉婚櫎鎬讳环瀛楁锛�:", submitData);
-
- // 鏍规嵁褰撳墠鏍囩椤佃皟鐢ㄤ笉鍚岀殑鎻愪氦鎺ュ彛
- let apiCall;
- if (activeTab.value === "production") {
- // 鎴愬搧搴撳瓨浣跨敤 updateManagement 鎺ュ彛
- apiCall = updateManagement(submitData);
- } else {
- // 鍘熸枡搴撳瓨浣跨敤 updateManagementByCustom 鎺ュ彛
- apiCall = updateManagementByCustom(submitData);
- }
-
- apiCall
- .then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- // 鎻愪氦鍚庢鏌ュ簱瀛樺苟灏濊瘯鍒涘缓璇疯喘鍗�
- // checkStockAndCreatePurchase();
- })
- .catch(error => {
- console.error("鎻愪氦澶辫触:", error);
- proxy.$modal.msgError("鎻愪氦澶辫触锛岃閲嶈瘯");
- });
- };
- // 妫�鏌ュ簱瀛樺苟鍒涘缓璇疯喘鍗�
- // const checkStockAndCreatePurchase = async () => {
- // const stockList = tableData.value;
- // // handList()
- // for (const item of stockList) {
- // if (item.inboundNum0 < item.warnNum) {
- // try {
- // const stockInData = {
- // id: item.id,
- // quantityStock: item.warnNum + item.totalInboundNum,// 浣跨敤鏂版牸寮忓寲鍑芥暟
- // };
- // loading.value = true
- // await updateStockIn(stockInData)
- // proxy.$modal.msgSuccess(`浜у搧 ${item.productCategory} 淇敼鍏ュ簱鎴愬姛`)
- // loading.value = false
- // } catch (error) {
- // proxy.$modal.msgError(`浜у搧 ${item.productCategory} 鐢熸垚璇疯喘鍗曞け璐ワ紝璇锋墜鍔ㄥ鐞哷);
- //
- // }
- // }
- // }
- // };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- productionDialogVisible.value = false;
- purchaseDialogVisible.value = false;
- };
-
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- const exportParams = buildQueryParams();
- // 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
- let exportUrl = "/stockin/exportCopy";
- if (activeTab.value === "production") {
- exportUrl = "/stockin/exportCopyOne";
- }
- proxy.download(exportUrl, exportParams, "搴撳瓨淇℃伅.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: 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 activeTab = ref('qualified')
+const tabs = ref([
+ {
+ label: '鍚堟牸搴撳瓨',
+ name: 'qualified'
+ },
+ {
+ label: '涓嶅悎鏍煎簱瀛�',
+ name: 'unqualified'
}
- onMounted(() => {
- getList();
- // checkStockAndCreatePurchase();
- // 姣忓皬鏃舵鏌ヤ竴娆″簱瀛�
- // const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000);
+])
- // onUnmounted(() => {
- // // 缁勪欢鍗歌浇鏃舵竻闄ゅ畾鏃跺櫒
- // clearInterval(intervalId);
- // });
- });
+const handleTabChange = (tabName) => {
+ activeTab.value = tabName;
+}
</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>
\ No newline at end of file
--
Gitblit v1.9.3