From fbad57aa29d1600dcb0c08817dc3d91522e1afb6 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 09 一月 2026 17:35:41 +0800
Subject: [PATCH] 浪潮 1.仓储物流添加新增功能以及bug修改
---
src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue | 147 +
src/views/inventoryManagement/index.vue | 309 +++
src/views/inventoryManagement/issueManagement/index.vue | 167 +
src/api/inventoryManagement/stockIn.js | 78
src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue | 300 +++
src/views/inventoryManagement/stockWarning/index.vue | 583 ++----
src/api/inventoryManagement/stockManage.js | 20
src/api/inventoryManagement/stockWarning.js | 15
src/api/inventoryManagement/stockReport.js | 55
src/api/inventoryManagement/stockOut.js | 12
src/views/inventoryManagement/receiptManagement/index.vue | 500 +----
src/views/inventoryManagement/stockManagement/index.vue | 371 ++--
src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue | 310 +++
src/utils/index.js | 13
src/views/inventoryManagement/receiptManagement/components/formDia.vue | 401 ++++
src/views/inventoryManagement/stockReport/index.vue | 713 ++++++++
src/views/salesManagement/receiptPaymentHistory/index.vue | 13
src/views/inventoryManagement/dispatchLog/index.vue | 558 +++--
src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue | 154 +
src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue | 147 +
20 files changed, 3,601 insertions(+), 1,265 deletions(-)
diff --git a/src/api/inventoryManagement/stockIn.js b/src/api/inventoryManagement/stockIn.js
index 5e104f7..70f07a7 100644
--- a/src/api/inventoryManagement/stockIn.js
+++ b/src/api/inventoryManagement/stockIn.js
@@ -9,6 +9,41 @@
});
};
+// 鏌ヨ鐢熶骇鍏ュ簱淇℃伅鍒楄〃
+export const getStockInPageByProduction = (params) => {
+ return request({
+ url: "/stockin/listPageByProduction",
+ method: "get",
+ params,
+ });
+};
+
+// 鍑哄簱鍙拌处-鏌ヨ鑷畾涔夊叆搴撲俊鎭垪琛�
+export const getStockInPageByCustom = (params) => {
+ return request({
+ url: "/stockmanagement/listPageByCustom",
+ method: "get",
+ params,
+ });
+};
+// 鍏ュ簱绠$悊-鏌ヨ鑷畾涔夊叆搴撲俊鎭垪琛�
+export const getInPageByCustom = (params) => {
+ return request({
+ url: "/stockin/listPageByCustom",
+ method: "get",
+ params,
+ });
+};
+
+// 鍑哄簱鍙拌处-鏌ヨ鐢熶骇鍑哄簱淇℃伅鍒楄〃
+export const getStockInPageByProduct = (params) => {
+ return request({
+ url: "/stockmanagement/listPageByProduct",
+ method: "get",
+ params,
+ });
+};
+
// 淇敼鍏ュ簱瀛樹俊鎭�
export const updateStockIn = (data) => {
return request({
@@ -26,6 +61,14 @@
data,
});
};
+// 淇敼鏉愭枡搴撳瓨淇℃伅
+export const updateManagementByCustom = (data) => {
+ return request({
+ url: "/stockin/updateManagementByCustom ",
+ method: "post",
+ data,
+ });
+};
// 鏂板鍟嗗搧鍏ュ簱淇℃伅
export function addSutockIn(data) {
@@ -36,6 +79,32 @@
})
}
+// 鏂板鑷畾涔夊叆搴撲俊鎭�
+export function addStockInCustom(data) {
+ return request({
+ url: '/stockin/addCustom',
+ method: 'post',
+ data: data
+ })
+}
+
+// 缂栬緫鑷畾涔夊叆搴撲俊鎭�
+export function updateStockInCustom(data) {
+ return request({
+ url: '/stockin/updateCustom',
+ method: 'post',
+ data: data
+ })
+}
+// 缂栬緫鎴愬搧鍏ュ簱淇℃伅
+export function updateProduct(data) {
+ return request({
+ url: '/stockin/update',
+ method: 'post',
+ data: data
+ })
+}
+
// 鍒犻櫎鍏ュ簱淇℃伅
export function delStockIn(ids) {
return request({
@@ -45,6 +114,15 @@
})
}
+// 鍒犻櫎鑷畾涔夊叆搴撲俊鎭�
+export function delStockInCustom(ids) {
+ return request({
+ url: '/stockin/delteCustom',
+ method: 'post',
+ data: ids
+ })
+}
+
// 瀵煎嚭鍏ュ簱淇℃伅
export function exportStockIn(query) {
return request({
diff --git a/src/api/inventoryManagement/stockManage.js b/src/api/inventoryManagement/stockManage.js
index bb2081b..4f5d957 100644
--- a/src/api/inventoryManagement/stockManage.js
+++ b/src/api/inventoryManagement/stockManage.js
@@ -9,6 +9,24 @@
});
};
+// 鏌ヨ鐢熶骇鍏ュ簱搴撳瓨淇℃伅鍒楄〃
+export const getStockManagePageByProduction = (params) => {
+ return request({
+ url: "/stockin/listPageCopyByProduction",
+ method: "get",
+ params,
+ });
+};
+
+// 鏌ヨ鑷畾涔夊叆搴撳簱瀛樹俊鎭垪琛�
+export const getStockManagePageByCustom = (params) => {
+ return request({
+ url: "/stockin/listPageCopyByCustom",
+ method: "get",
+ params,
+ });
+};
+
// 淇敼搴撳瓨淇℃伅
export const updateStockManage = (data) => {
@@ -38,7 +56,7 @@
})
}
-//鍑哄簱鎺ュ彛
+// 鍑哄簱绠$悊-棰嗙敤鎺ュ彛
export const stockOut = (data) => {
return request({
url: '/stockmanagement/stockout',
diff --git a/src/api/inventoryManagement/stockOut.js b/src/api/inventoryManagement/stockOut.js
index 5d410d9..7d188af 100644
--- a/src/api/inventoryManagement/stockOut.js
+++ b/src/api/inventoryManagement/stockOut.js
@@ -1,6 +1,6 @@
import request from "@/utils/request";
-//鏌ヨ鍑哄簱鍒楄〃
+// 鍑哄簱鍙拌处-閲囪喘鍑哄簱鏌ヨ鍑哄簱鍒楄〃
export const getStockOutPage = (params) => {
return request({
url: "/stockmanagement/listPage",
@@ -35,13 +35,3 @@
data: ids
})
}
-
-//瀵煎嚭鍑哄簱淇℃伅
-export const exportStockOut = (query) => {
- return request({
- url: '/stockmanagement/export',
- method: 'get',
- params: query,
- responseType: 'blob'
- })
-}
\ No newline at end of file
diff --git a/src/api/inventoryManagement/stockReport.js b/src/api/inventoryManagement/stockReport.js
new file mode 100644
index 0000000..6d1a3ce
--- /dev/null
+++ b/src/api/inventoryManagement/stockReport.js
@@ -0,0 +1,55 @@
+import request from "@/utils/request";
+
+// 鑾峰彇搴撳瓨鏃ユ姤缁熻
+export const getStockDailyReport = (params) => {
+ return request({
+ url: "/stockin/getReportList",
+ method: "get",
+ params,
+ });
+};
+// 鑾峰彇搴撳瓨鏈堟姤缁熻
+export const getStockMonthlyReport = (params) => {
+ return request({
+ url: "/stockin/getReportList",
+ method: "get",
+ params,
+ });
+};
+
+// 鑾峰彇浣滀笟鎶ヨ〃缁熻
+export const getWorkReport = (params) => {
+ return request({
+ url: "/stockin/getReportList",
+ method: "get",
+ params,
+ });
+};
+
+// 鑾峰彇搴撳瓨杩涘嚭瀛樼粺璁�
+export const getStockInOutReport = (params) => {
+ return request({
+ url: "/stockin/getReportList",
+ method: "get",
+ params,
+ });
+};
+
+// 瀵煎嚭搴撳瓨鎶ヨ〃
+export const exportStockReport = (params) => {
+ return request({
+ url: "/stockin/exportCopy",
+ method: "post",
+ params,
+ responseType: 'blob'
+ });
+};
+
+// 鑾峰彇搴撳瓨瓒嬪娍鏁版嵁
+export const getStockTrendData = (params) => {
+ return request({
+ url: "/stockreport/trend",
+ method: "get",
+ params,
+ });
+};
diff --git a/src/api/inventoryManagement/stockWarning.js b/src/api/inventoryManagement/stockWarning.js
index 092fb80..65e641a 100644
--- a/src/api/inventoryManagement/stockWarning.js
+++ b/src/api/inventoryManagement/stockWarning.js
@@ -1,11 +1,14 @@
import request from "@/utils/request";
// 鏌ヨ鍌ㄦ皵缃愰璀﹀垪琛�
-export const getStockWarningPage = (params) => {
+export const getStockWarningPage = (page, params) => {
return request({
url: "/gasTankWarning/listPage",
method: "get",
- params,
+ params: {
+ ...page,
+ ...params
+ },
});
};
@@ -14,7 +17,7 @@
return request({
url: "/gasTankWarning/add",
method: "post",
- data,
+ data: data,
});
};
@@ -22,8 +25,8 @@
export const updateStockWarning = (data) => {
return request({
url: "/gasTankWarning/update",
- method: "put",
- data,
+ method: "post",
+ data: data,
});
};
@@ -32,7 +35,7 @@
return request({
url: "/gasTankWarning/delete",
method: "delete",
- data: { ids },
+ data: ids,
});
};
diff --git a/src/utils/index.js b/src/utils/index.js
index e522c3c..809593f 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -396,3 +396,16 @@
export function isEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
+
+/**
+ * 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+ * @returns {string} 鏍煎紡鍖栫殑鏃ユ湡瀛楃涓�
+ */
+export 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}`;
+}
+
diff --git a/src/views/inventoryManagement/dispatchLog/index.vue b/src/views/inventoryManagement/dispatchLog/index.vue
index 6fe0473..c15e73f 100644
--- a/src/views/inventoryManagement/dispatchLog/index.vue
+++ b/src/views/inventoryManagement/dispatchLog/index.vue
@@ -1,285 +1,371 @@
<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"
- />
- <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>
- <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)"
- stripe
- >
- <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"
- min-width="130"
- show-overflow-tooltip
- />
- <el-table-column
- label="渚涘簲鍟嗗悕绉�"
- prop="supplierName"
- width="250"
- show-overflow-tooltip
- />
- <el-table-column
- label="浜у搧澶х被"
- prop="productCategory"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="specificationModel"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍗曚綅"
- prop="unit"
- width="80"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍑哄簱鏁伴噺"
- prop="inboundNum"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- width="200"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- width="200"
- show-overflow-tooltip
- />
- <el-table-column
- label="绋庣巼(%)"
- prop="taxRate"
- width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- width="180"
- 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"
- 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>
- </div>
+ <div class="app-container">
+ <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%"
+ :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" show-overflow-tooltip width="130"/>
+ <el-table-column label="鎵规鍙�" prop="code" width="130" 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" show-overflow-tooltip />
+ <el-table-column label="鐗╁搧绫诲瀷" prop="itemType" show-overflow-tooltip />
+ <el-table-column label="鍙戞枡鏁伴噺" prop="inboundNum" 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-column label="鍙戞枡浜�" prop="createBy" show-overflow-tooltip />
+ </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>
+ </div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref } from "vue";
+import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
import { ElMessageBox } from "element-plus";
-import useUserStore from "@/store/modules/user";
-import { userListNoPage } from "@/api/system/user.js";
import {
- getStockOutPage,
- delStockOut,
+ delStockOut,
} from "@/api/inventoryManagement/stockOut.js";
-
-const userStore = useUserStore();
+import {
+ getStockInPageByCustom,
+} from "@/api/inventoryManagement/stockIn.js";
+import { getCurrentDate } from "@/utils/index.js";
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const selectedRows = ref([]);
-const userList = ref([]);
const tableLoading = ref(false);
-const productList = ref([])
const page = reactive({
- current: 1,
- size: 100,
+ current: 1,
+ size: 100,
});
const total = ref(0);
-const fileList = ref([]);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
+// 鏌ヨ琛ㄥ崟鏁版嵁
const data = reactive({
- searchForm: {
- supplierName: "",
- },
- form: {
- supplierId: null,
- supplierName: '',
- productId: null,
- productName: '',
- userId: userStore.userId,
- nickname: '',
- model: '',
- productModelId: null,
- unit: '',
- productrecordId: null,
- taxInclusiveUnitPrice: '',
- taxInclusiveTotalPrice: '',
- taxRate: '',
- taxExclusiveTotalPrice: '',
- inboundTime: '',
- inboundBatch: '',
- inboundQuantity: ''
- },
+ searchForm: {
+ supplierName: "",
+ customerName: "",
+ productCategory:'',
+ timeStr: getCurrentDate(),
+ },
});
const { searchForm } = toRefs(data);
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
- page.current = 1;
- getList();
+ page.current = 1;
+ 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;
- getStockOutPage({ ...searchForm.value, ...page })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.data.total;
- })
- .catch(() => {
- tableLoading.value = false;
- });
+ tableLoading.value = true;
+ const params = { ...page }
+ params.supplierName = searchForm.value.supplierName
+ params.timeStr = searchForm.value.timeStr
+ params.productCategory = searchForm.value.productCategory
+
+ // 鏉愭枡鍑哄簱锛氳皟鐢ㄨ嚜瀹氫箟鍑哄簱璁板綍鎺ュ彛
+ const apiCall = getStockInPageByCustom(params)
+
+ apiCall
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ tableData.value.map((item) => {
+ item.children = [];
+ // 鍓嶇璁$畻鎬讳环
+ const inboundNum = Number(item.inboundNum) || 0;
+ // 鏉愭枡鍑哄簱锛氭�讳环 = taxInclusiveUnitPrice 脳 inboundNum
+ const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0;
+ item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * inboundNum).toFixed(2);
+ });
+ total.value = res.data.total;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
};
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.id);
- console.log("selection", selectedRows.value);
+ // 杩囨护鎺夊瓙鏁版嵁
+ 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",
- ]);
+ return proxy.summarizeTable(param, [
+ "contractAmount",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
};
// 瀵煎嚭
const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/stockmanagement/export", {}, "鍑哄簱鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ // 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
+ const exportUrl = "/stockmanagement/exportTwo"
+ proxy.download(exportUrl, {}, "鍑哄簱鍙拌处.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(() => {
- delStockOut({ids:ids}).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ 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(() => {
+ delStockOut({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}`;
-}
onMounted(() => {
- getList();
+ getList();
});
</script>
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+.print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
+ }
+}
+
+.print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
+ text-align: center;
+
+ .el-button {
+ margin: 0 10px;
+ }
+ }
+
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+}
+
+.print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+}
+
+.delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+}
+
+.header {
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+}
+
+.info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 14px;
+ }
+
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 14px;
+ }
+ }
+}
+
+.table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th, td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+}
+
+.footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 14px;
+ }
+
+ .value {
+ min-width: 80px;
+ font-size: 14px;
+ }
+
+ &.address-item {
+ .address-value {
+ min-width: 200px;
+ }
+ }
+ }
+ }
+}
+
+@media print {
+ .app-container {
+ display: none;
+ }
+
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+}
+</style>
+
+
diff --git a/src/views/inventoryManagement/index.vue b/src/views/inventoryManagement/index.vue
new file mode 100644
index 0000000..f371e26
--- /dev/null
+++ b/src/views/inventoryManagement/index.vue
@@ -0,0 +1,309 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鍙戞斁瀛e害锛�</span>
+ <el-select
+ style="width: 200px;"
+ @change="handleQuery"
+ v-model="searchForm.season"
+ placeholder="璇烽�夋嫨"
+ :clearable="false"
+ >
+ <el-option :label="item.label" :value="item.value" v-for="(item,index) in jidu" :key="item.value" />
+ </el-select>
+ <span class="search_title ml10">鍛樺伐鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.staffName"
+ 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="add" icon="Plus"> 鏂板 </el-button>
+ <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
+ <el-button
+ type="danger"
+ icon="Delete"
+ :disabled="multipleList.length <= 0"
+ @click="deleteRow(multipleList.map((item) => item.id))"
+ >
+ 鎵归噺鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <el-table
+ ref="tableRef"
+ v-loading="tableLoading"
+ :data="tableData"
+ border
+ height="calc(100vh - 21em)"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ style="width: 100%"
+ @selection-change="handleSelectionChange"
+ >
+ <!-- 閫夋嫨鍒� -->
+ <el-table-column
+ align="center"
+ type="selection"
+ width="55"
+ fixed="left"
+ />
+
+ <!-- 搴忓彿鍒� -->
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ fixed="left"
+ />
+
+ <!-- 鍥哄畾鍒楋細濮撳悕 -->
+ <el-table-column
+ label="濮撳悕"
+ prop="staffName"
+ width="100"
+ show-overflow-tooltip
+ align="center"
+ fixed="left"
+ />
+
+ <!-- 鍥哄畾鍒楋細宸ュ彿 -->
+ <el-table-column
+ label="宸ュ彿"
+ prop="staffNo"
+ width="100"
+ show-overflow-tooltip
+ align="center"
+ fixed="left"
+ />
+
+ <!-- 鍔ㄦ�佸垪锛氭牴鎹瓧鍏告覆鏌� -->
+ <el-table-column
+ v-for="(dictItem, index) in sys_lavor_issue"
+ :key="dictItem.value"
+ :label="dictItem.label"
+ :prop="dictItem.value"
+ show-overflow-tooltip
+ >
+ </el-table-column>
+
+ <!-- 鎿嶄綔鍒� -->
+ <el-table-column
+ label="鎿嶄綔"
+ width="150"
+ align="center"
+ fixed="right"
+ >
+ <template #default="scope">
+ <el-button
+ type="primary"
+ link
+ size="small"
+ @click="edit(scope.row)"
+ >
+ 缂栬緫
+ </el-button>
+ <el-button
+ type="danger"
+ link
+ size="small"
+ :disabled="!!scope.row.adoptedDate"
+ @click="adopted(scope.row)"
+ >
+ 棰嗙敤
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination :total="total" layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current" :limit="page.size" @pagination="paginationChange" />
+ </div>
+ <!-- <Modal ref="modalRef" @success="handleQuery"></Modal> -->
+ <!-- <files-dia ref="filesDia"></files-dia> -->
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, reactive, toRefs, nextTick, getCurrentInstance } from 'vue'
+import dayjs from "dayjs";
+// import Modal from "./Modal.vue";
+// import FilesDia from "./filesDia.vue";
+import Pagination from "@/components/Pagination/index.vue";
+import {listPage, deleteLedger, update} from "@/api/lavorissce/ledger.js";
+import {ElMessageBox, ElMessage} from "element-plus";
+const { proxy } = getCurrentInstance();
+import { getCurrentMonth } from "@/utils/util"
+
+const page = ref({
+ current: 1,
+ size: 100,
+})
+const total = ref(0)
+// 鍝嶅簲寮忔暟鎹�
+const tableRef = ref(null)
+const tableData = ref([])
+const tableLoading = ref(false)
+const { sys_lavor_issue } = proxy.useDict("sys_lavor_issue")
+const data = reactive({
+ searchForm: {
+ season: "",
+ staffName: "",
+ },
+});
+const { searchForm } = toRefs(data);
+
+const modalRef = ref();
+// const filesDia = ref();
+const multipleList = ref([]);
+const jidu = ref([
+ {
+ value: '1',
+ label: '绗竴瀛e害'
+ },
+ {
+ value: '2',
+ label: '绗簩瀛e害'
+ },
+ {
+ value: '3',
+ label: '绗笁瀛e害'
+ },
+ {
+ value: '4',
+ label: '绗洓瀛e害'
+ }
+])
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.value.current = 1;
+ getList();
+};
+// 鑾峰彇瀛楀吀鏁版嵁
+const getList = async () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page.value };
+ listPage(params).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+}
+const add = () => {
+ modalRef.value.openModal();
+};
+const edit = (row) => {
+ modalRef.value.loadForm(row);
+};
+const deleteRow = (id) => {
+ ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(async () => {
+ const { code } = await deleteLedger(id);
+ if (code == 200) {
+ ElMessage({
+ type: "success",
+ message: "鍒犻櫎鎴愬姛",
+ });
+ await getList();
+ }
+ });
+};
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(`/lavorIssue/exportCopy`, {season: searchForm.value.season}, "鍔充繚鍙拌处.xlsx");
+ })
+ .catch(() => {
+ ElMessage.info("宸插彇娑�");
+ });
+};
+const adopted = (row) => {
+ ElMessageBox.confirm("鏄惁纭棰嗙敤?", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(async () => {
+ const params = {
+ id: row.id,
+ adoptedDate: dayjs().format("YYYY-MM-DD")
+ }
+ const { code } = await update(params);
+ if (code == 200) {
+ ElMessage({
+ type: "success",
+ message: "棰嗙敤鎴愬姛",
+ });
+ await getList();
+ }
+ })
+}
+// 鎵撳紑闄勪欢寮规
+// const openFilesFormDia = (row) => {
+// nextTick(() => {
+// filesDia.value?.openDialog( row,'鏀跺叆')
+// })
+// };
+// 浜嬩欢澶勭悊鍑芥暟
+const handleSelectionChange = (selection) => {
+ multipleList.value = selection;
+}
+
+const paginationChange = (pagination) => {
+ page.value.current = pagination.page;
+ page.value.size = pagination.limit;
+ getList();
+}
+
+// 缁勪欢鎸傝浇鏃跺姞杞藉瓧鍏告暟鎹�
+onMounted(() => {
+ handleQuery()
+})
+</script>
+
+<style scoped>
+.dynamic-table-container {
+ width: 100%;
+}
+
+.pagination-container {
+ margin-top: 20px;
+ display: flex;
+ justify-content: flex-end;
+}
+
+:deep(.el-table .el-table__header-wrapper th) {
+ background-color: #F0F1F5 !important;
+ color: #333333;
+ font-weight: 600;
+}
+
+:deep(.el-table .el-table__body-wrapper td) {
+ padding: 8px 0;
+}
+
+:deep(.el-select) {
+ width: 100%;
+}
+
+:deep(.el-input) {
+ width: 100%;
+}
+</style>
diff --git a/src/views/inventoryManagement/issueManagement/index.vue b/src/views/inventoryManagement/issueManagement/index.vue
index cc4d8e1..0577fe1 100644
--- a/src/views/inventoryManagement/issueManagement/index.vue
+++ b/src/views/inventoryManagement/issueManagement/index.vue
@@ -2,56 +2,70 @@
<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-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 type="primary" @click="openForm('add')">鏂板鍑哄簱</el-button> -->
<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%"
- :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)" stripe>
+ <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="code" width="130" 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="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">
+ <el-table-column label="鐗╁搧绫诲瀷" prop="itemType" show-overflow-tooltip />
+ <el-table-column label="鍓╀綑搴撳瓨" prop="inboundNum0" width="90" show-overflow-tooltip />
+ <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
<template #default="scope">
- <el-button link type="primary" size="small" @click="openForm(scope.row);">棰嗙敤</el-button>
+ <el-button link type="primary" size="small" @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" />
+ <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-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="40%" @close="closeDia" draggable>
<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 />
+ <div>{{getAvailableQuantityText()}}:{{currentRowNum}}</div>
+ <el-form-item :label="getQuantityLabel()" prop="salesContractNo">
+ <el-input-number :step="0.01" :min="0" :max="currentRowNum" style="width: 100%" v-model="form.inboundQuantity" placeholder="璇疯緭鍏�" clearable />
</el-form-item>
- <el-form-item label="鍑哄簱鏃ユ湡锛�" prop="projectName">
+ <el-form-item :label="getDateLabel()" 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-form-item :label="getPersonLabel()" prop="entryPerson">
+ <el-select v-model="form.nickName"
+ filterable
+ default-first-option
+ :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable>
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</el-form-item>
@@ -68,18 +82,18 @@
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
-import { ref } from '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 {
- getStockInPage
+ getInPageByCustom
} from "@/api/inventoryManagement/stockIn.js";
import {
- getStockManagePage,
delStockManage,
stockOut,
} from "@/api/inventoryManagement/stockManage.js";
+import { getCurrentDate } from "@/utils/index.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
@@ -98,11 +112,12 @@
const dialogFormVisible = ref(false)
const data = reactive({
searchForm: {
- supplierName: '',
inboundQuantity:'',
inboundTime:'',
nickName: '',
userId: '',
+ productCategory:'',
+ // timeStr: getCurrentDate(),
},
form: {
productrecordId: '',
@@ -128,11 +143,14 @@
}
const getList = () => {
tableLoading.value = true
- getStockInPage({ ...searchForm.value, ...page }).then(res => {
+ const params = { ...page }
+ params.productCategory = searchForm.value.productCategory
+ params.flag = true
+ const apiCall = getInPageByCustom(params)
+ apiCall.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
})
@@ -176,37 +194,52 @@
currentRowNum.value = row.inboundNum0
salesLedgerProductId.value = row.salesLedgerProductId
form.value = {}
- // 鍒濆鍖栬〃鍗曟暟鎹�
- form.value = {
- productrecordId: '',
- inboundQuantity: '', // 鍑哄簱鏁伴噺娓呯┖
- inboundTime: getCurrentDate(), // 榛樿褰撳墠鏃ユ湡
- nickName: '', // 榛樿褰撳墠鐢ㄦ埛
- }
- console.log('form',form.value)
+
// 鍔犺浇鐢ㄦ埛鍒楄〃
try {
const userLists = await userListNoPageByTenantId()
userList.value = userLists.data
+
+ // 鏉愭枡鍑哄簱榛樿鍙戞枡浜�
+ const defaultPersonName = '鍚寸帀姊�'
+ const defaultPerson = userList.value.find(user => user.nickName === defaultPersonName)
+ const defaultUserId = defaultPerson ? defaultPerson.userId : ''
+
+ // 鍒濆鍖栬〃鍗曟暟鎹�
+ form.value = {
+ productrecordId: '',
+ inboundQuantity: currentRowNum.value, // 浣跨敤currentRowNum浣滀负榛樿鍊�
+ inboundTime: getCurrentDate(), // 榛樿褰撳墠鏃ユ湡
+ nickName: defaultUserId, // 鏍规嵁tab绫诲瀷璁剧疆榛樿鍙戣揣浜�
+ }
+ console.log('form',form.value)
} catch (error) {
console.error('鍔犺浇鐢ㄦ埛鍒楄〃澶辫触:', error)
+ // 濡傛灉鍔犺浇澶辫触锛屼娇鐢ㄧ┖鍊煎垵濮嬪寲
+ form.value = {
+ productrecordId: '',
+ inboundQuantity: currentRowNum.value,
+ inboundTime: getCurrentDate(),
+ nickName: '',
+ }
}
}
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
let num = Number(form.value.inboundQuantity)
- if(num < 1 || num > currentRowNum.value){
+ 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,
+ salesLedgerProductId: 0,
quantity: form.value.inboundQuantity, // 鍑哄簱鏁伴噺
time: form.value.inboundTime, // 鍑哄簱鏃堕棿
- userId: form.value.nickName // 鎿嶄綔浜�
+ userId: form.value.nickName, // 鎿嶄綔浜�
+ type: 3 // 鍑哄簱绫诲瀷锛氳嚜瀹氫箟/鏉愭枡
}
console.log(outData)
@@ -236,7 +269,8 @@
type: 'warning',
}
).then(() => {
- proxy.download("/stockin/export", {}, '鍏ュ簱鍙拌处.xlsx')
+ const exportUrl = "/stockin/exportTwo"
+ proxy.download(exportUrl, {}, '鍑哄簱鍙拌处.xlsx')
}).catch(() => {
proxy.$modal.msg("宸插彇娑�")
})
@@ -266,17 +300,38 @@
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}`;
-}
+
+// 鏍规嵁tab绫诲瀷鑾峰彇寮规鏍囬
+const getDialogTitle = () => {
+ return '鏂板鍙戞枡';
+};
+
+// 鏍规嵁tab绫诲瀷鑾峰彇鍙嚭搴撴暟閲忔枃鏈�
+const getAvailableQuantityText = () => {
+ return '鍙彂鏂欐暟閲�';
+};
+
+// 鏍规嵁tab绫诲瀷鑾峰彇鏁伴噺瀛楁鏍囩
+const getQuantityLabel = () => {
+ return '鍙戞枡鏁伴噺锛�';
+};
+
+// 鏍规嵁tab绫诲瀷鑾峰彇鏃ユ湡瀛楁鏍囩
+const getDateLabel = () => {
+ return '鍙戞枡鏃ユ湡锛�';
+};
+
+// 鏍规嵁tab绫诲瀷鑾峰彇浜哄憳瀛楁鏍囩
+const getPersonLabel = () => {
+ return '鍙戞枡浜猴細';
+};
+
onMounted(() => {
getList()
})
</script>
<style scoped lang="scss"></style>
+
+
+
diff --git a/src/views/inventoryManagement/receiptManagement/components/formDia.vue b/src/views/inventoryManagement/receiptManagement/components/formDia.vue
new file mode 100644
index 0000000..a736b52
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/components/formDia.vue
@@ -0,0 +1,401 @@
+<template>
+ <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%"
+ @close="closeDia">
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="閲囪喘璁㈠崟鍙�" prop="purchaseContractNumber">
+ <el-select
+ v-model="form.purchaseContractNumber"
+ placeholder="璇烽�夋嫨閲囪喘璁㈠崟鍙�"
+ clearable
+ filterable
+ :loading="loadingPurchaseOptions"
+ @change="handlePurchaseChange"
+ :disabled="operationType === 'edit'"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in purchaseOptions"
+ :key="item.purchaseContractNumber"
+ :label="formatPurchaseOption(item)"
+ :value="item.purchaseContractNumber"
+ />
+ </el-select>
+ </el-form-item>
+ <el-table
+ :data="productList"
+ border
+ v-loading="loadingProducts"
+ @selection-change="handleSelectionChange"
+ >
+ <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="supplierName" width="100" /> -->
+ <el-table-column label="閲囪喘鏁伴噺" prop="quantity" width="100" />
+ <el-table-column label="寰呭叆搴撴暟閲�" prop="quantity0" width="100" />
+ <el-table-column label="鏈鍏ュ簱鏁伴噺" prop="quantityStock" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />
+ </template>
+ </el-table-column>
+ <el-table-column label="绋庣巼(%)" prop="taxRate" width="120" />
+ <el-table-column label="鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" :disabled="operationType === 'edit'"/>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鎬讳环(鍏�)"
+ :formatter="formattedNumber"
+ prop="taxInclusiveTotalPrice"
+ width="150"
+ >
+ </el-table-column>
+ </el-table>
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
+import useUserStore from '@/store/modules/user'
+import {
+ updateStockIn,
+ addSutockIn,
+ selectProductRecordListByPuechaserId
+} from "@/api/inventoryManagement/stockIn.js";
+import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
+import { getCurrentDate } from "@/utils/index.js";
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close', 'success'])
+
+const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
+const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
+const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
+const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
+const selectedRows = ref([]) // 浜у搧琛ㄦ牸閫変腑琛�
+const purchaseOptions = ref([])
+const loadingPurchaseOptions = ref(false)
+const loading = ref(false);
+
+const data = reactive({
+ form: {
+ id: null,
+ purchaseContractNumber: '', // 閲囪喘璁㈠崟鍙�
+ supplierId: null, // 渚涘簲鍟咺D
+ supplierName: '', // 渚涘簲鍟嗗悕绉�
+ inboundTime: '', // 鍏ュ簱鏃堕棿
+ inboundBatch: '', // 鍏ュ簱鎵规
+ recorderId: userStore.userId, // 褰曞叆浜篒D
+ recorderName: userStore.name, // 褰曞叆浜哄鍚�
+ entryDate: getCurrentDate(), // 褰曞叆鏃ユ湡
+ remark: '', // 澶囨敞
+ },
+ rules: {
+ purchaseContractNumber: [{ required: true, message: "璇疯緭鍏ラ噰璐悎鍚屽彿", trigger: "blur" }],
+ supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
+ inboundTime: [{ required: true, message: "璇烽�夋嫨鍏ュ簱鏃堕棿", trigger: "change" }],
+ inboundBatch: [{ required: true, message: "璇疯緭鍏ュ叆搴撴壒娆�", trigger: "blur" }]
+ }
+})
+const { form, rules } = toRefs(data)
+
+// 鍔ㄦ�佽绠楀璇濇鏍囬
+const getDialogTitle = () => {
+ return operationType.value === 'add' ? '鏂板鍏ュ簱' : '缂栬緫鍏ュ簱'
+}
+
+const formatPurchaseOption = (item = {}) => {
+ const contract = item.purchaseContractNumber || '--';
+ const supplier = item.supplierName ? ` 路 ${item.supplierName}` : '';
+ return `${contract}${supplier}`;
+};
+
+const loadPurchaseOptions = async (keyword = '') => {
+ try {
+ loadingPurchaseOptions.value = true;
+ const res = await purchaseListPage({
+ current: -1,
+ size: -1,
+ purchaseContractNumber: keyword,
+ });
+ const records = res.data?.records || [];
+ purchaseOptions.value = records;
+ if (
+ form.value.purchaseContractNumber &&
+ !purchaseOptions.value.find(
+ (item) => item.purchaseContractNumber === form.value.purchaseContractNumber
+ )
+ ) {
+ purchaseOptions.value.push({
+ purchaseContractNumber: form.value.purchaseContractNumber,
+ supplierName: form.value.supplierName,
+ supplierId: form.value.supplierId,
+ });
+ }
+ } finally {
+ loadingPurchaseOptions.value = false;
+ }
+};
+
+const handlePurchaseChange = (value) => {
+ form.value.purchaseContractNumber = value || '';
+ const matched = purchaseOptions.value.find(
+ (item) => item.purchaseContractNumber === value
+ );
+ if (matched) {
+ form.value.supplierName = matched.supplierName || form.value.supplierName;
+ form.value.supplierId = matched.supplierId || form.value.supplierId;
+ }
+ if (!value) {
+ productList.value = [];
+ return;
+ }
+ fetchProductsByContract();
+};
+
+const exceedsAddLimit = (product) => {
+ const stock = Number(product?.quantityStock ?? 0);
+ const waiting = Number(product?.quantity0 ?? 0);
+ if (!Number.isFinite(stock) || !Number.isFinite(waiting)) {
+ return false;
+ }
+ return stock > waiting;
+};
+
+const exceedsEditLimit = (product) => {
+ const stock = Number(product?.quantityStock ?? 0);
+ const waiting = Number(product?.quantity0 ?? 0);
+ const original = Number(product?.originalQuantityStock ?? 0);
+ if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) {
+ return false;
+ }
+ return stock > waiting + original;
+};
+
+const formattedNumber = (row, column, cellValue) => {
+ return parseFloat(cellValue).toFixed(2);
+};
+
+// 璁$畻鎬讳环
+const calculateTotalPrice = (row) => {
+ const quantityStock = Number(row?.quantityStock ?? 0);
+ const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0);
+
+ if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) {
+ row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice;
+ } else {
+ row.taxInclusiveTotalPrice = 0;
+ }
+};
+
+const fetchProductsByContract = async () => {
+ if (!form.value.purchaseContractNumber) {
+ proxy.$modal.msgWarning('璇烽�夋嫨鍚堝悓鍙�')
+ return
+ }
+ try {
+ loadingProducts.value = true
+ const productRes = await selectProductRecordListByPuechaserId({
+ purchaseContractNumber: form.value.purchaseContractNumber
+ });
+ if (!productRes.data || productRes.data.length === 0) {
+ proxy.$modal.msgWarning('璇ュ悎鍚屼笅娌℃湁浜у搧璁板綍')
+ productList.value = [];
+ return
+ }
+ productList.value = productRes.data.map(item => {
+ const quantityStock = Number(item?.quantity0 ?? 0);
+ const taxInclusiveUnitPrice = Number(item?.taxInclusiveUnitPrice ?? 0);
+ return {
+ ...item,
+ quantityStock,
+ taxInclusiveUnitPrice,
+ taxInclusiveTotalPrice: quantityStock * taxInclusiveUnitPrice,
+ originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0),
+ };
+ })
+ } catch (error) {
+ console.error('鏌ヨ浜у搧璁板綍澶辫触:', error)
+ proxy.$modal.msgError('鏌ヨ浜у搧璁板綍澶辫触')
+ productList.value = [];
+ } finally {
+ loadingProducts.value = false
+ }
+}
+
+const updatePro = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning('璇峰厛閫夋嫨浜у搧');
+ return;
+ }
+ const target = selectedRows.value[0];
+ const stock = Number(target?.quantityStock ?? 0);
+ if (!Number.isFinite(stock) || stock <= 0) {
+ proxy.$modal.msgWarning('璇峰~鍐欐湁鏁堢殑鍏ュ簱鏁伴噺');
+ return;
+ }
+ if (exceedsEditLimit(target)) {
+ proxy.$modal.msgError('鏈鍏ュ簱鏁伴噺涓嶈兘瓒呰繃鍘熷叆搴撴暟閲忎笌寰呭叆搴撴暟閲忎箣鍜�');
+ return;
+ }
+ const stockInData = {
+ id: selectedRows.value[0].recordId,
+ quantityStock: Number(selectedRows.value[0].quantityStock),
+ };
+ await updateStockIn(stockInData)
+ proxy.$modal.msgSuccess('淇敼鍏ュ簱鎴愬姛')
+ closeDia()
+ emit('success')
+}
+
+const submitForm = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning('璇峰厛閫夋嫨閲囪喘鍚堝悓骞堕�夋嫨浜у搧')
+ return
+ }
+ if(operationType.value !== 'add'){
+ await updatePro()
+ return
+ }
+ try {
+ await proxy.$refs.formRef.validate()
+ const invalidProducts = selectedRows.value.filter((product) => {
+ const stock = Number(product?.quantityStock ?? 0);
+ if (!Number.isFinite(stock) || stock <= 0) {
+ return true;
+ }
+ return exceedsAddLimit(product);
+ })
+
+ if (invalidProducts.length > 0) {
+ proxy.$modal.msgError('鏈鍏ュ簱鏁伴噺闇�澶т簬0锛屼笖涓嶈兘瓒呰繃寰呭叆搴撴暟閲�')
+ return
+ }
+
+ const stockInData = {
+ ...form.value,
+ inboundTime: formatDateTime(form.value.inboundTime),
+ nickName: userStore.nickName,
+ details: selectedRows.value.map(product => ({
+ id: product.id,
+ inboundQuantity: Number(product.quantityStock),
+ taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice),
+ taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice)
+ })),
+ };
+ loading.value = true
+ await addSutockIn(stockInData)
+
+ proxy.$modal.msgSuccess('鏂板鍏ュ簱鎴愬姛')
+ closeDia()
+ emit('success')
+
+ } catch (error) {
+ console.error('鎻愪氦澶辫触:', error)
+ if (!error.errors) {
+ proxy.$modal.msgError('鎿嶄綔澶辫触锛岃閲嶈瘯')
+ }
+ } finally {
+ loading.value = false
+ }
+}
+
+const closeDia = () => {
+ proxy.$refs.formRef.resetFields()
+ dialogFormVisible.value = false
+ emit('close')
+}
+
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection.filter(item => item.id);
+}
+
+function formatDateTime(date = new Date(), includeTime = true) {
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+
+ if (!includeTime) {
+ return `${year}-${month}-${day}`;
+ }
+
+ const hours = String(d.getHours()).padStart(2, '0');
+ const minutes = String(d.getMinutes()).padStart(2, '0');
+ const seconds = String(d.getSeconds()).padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+
+const openDialog = async (type, row) => {
+ operationType.value = type
+ dialogFormVisible.value = true
+ selectedRows.value = []
+ await loadPurchaseOptions();
+
+ if (type === 'add') {
+ form.value = {
+ id: null,
+ purchaseContractNumber: '',
+ supplierId: null,
+ supplierName: '',
+ inboundTime: '',
+ inboundBatch: '',
+ recorderId: userStore.userId,
+ recorderName: userStore.name,
+ entryDate: getCurrentDate(),
+ remark: ''
+ }
+ productList.value = []
+ } else {
+ form.value = JSON.parse(JSON.stringify(row))
+ try {
+ loadingProducts.value = true
+ const res = await selectProductRecordListByPuechaserId({
+ purchaseContractNumber: form.value.purchaseContractNumber,
+ id: row.id
+ });
+ productList.value = res.data.map(item => ({
+ ...item,
+ quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
+ taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0),
+ taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0),
+ originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
+ }))
+ selectedRows.value = productList.value
+ } catch (error) {
+ console.error('鍔犺浇浜у搧澶辫触:', error)
+ proxy.$modal.msgError('鍔犺浇浜у搧澶辫触')
+ productList.value = []
+ } finally {
+ loadingProducts.value = false
+ }
+ }
+}
+
+defineExpose({
+ openDialog,
+})
+</script>
+
+<style scoped lang="scss"></style>
+
+
+
diff --git a/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue b/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue
new file mode 100644
index 0000000..f0f9d75
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue
@@ -0,0 +1,310 @@
+<template>
+ <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">
+ <div style="margin-bottom: 10px;" v-if="operationType === 'add'">
+ <el-button type="primary" @click="addProductRow">鏂板</el-button>
+ </div>
+ <el-table
+ :data="productList"
+ border
+ v-loading="loadingProducts"
+ >
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" width="200">
+ <template #default="scope">
+ <el-input v-model="scope.row.productCategory" placeholder="璇疯緭鍏ヤ骇鍝佸ぇ绫�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="200">
+ <template #default="scope">
+ <el-input v-model="scope.row.specificationModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍗曚綅" prop="unit" width="100">
+ <template #default="scope">
+ <el-input v-model="scope.row.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="渚涘簲鍟�" prop="supplierName" width="200">
+ <template #default="scope">
+ <el-input v-model="scope.row.supplierName" placeholder="璇疯緭鍏ヤ緵搴斿晢" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鐗╁搧绫诲瀷" prop="itemType" width="150">
+ <template #default="scope">
+ <el-input v-model="scope.row.itemType" placeholder="璇疯緭鍏ョ墿鍝佺被鍨�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ簱鏁伴噺" prop="inboundNum" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ簱鏃ユ湡" prop="inboundDate" width="180">
+ <template #default="scope">
+ <el-date-picker
+ v-model="scope.row.inboundDate"
+ type="date"
+ placeholder="璇烽�夋嫨鍏ュ簱鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ style="width: 100%"
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" />
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ width="150"
+ >
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" v-if="operationType === 'add'">
+ <template #default="scope">
+ <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
+import useUserStore from '@/store/modules/user'
+import {
+ addStockInCustom,
+ updateStockInCustom,
+} from "@/api/inventoryManagement/stockIn.js";
+import { getCurrentDate } from "@/utils/index.js";
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close', 'success'])
+
+const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
+const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
+const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
+const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
+const loading = ref(false);
+
+function formatDateTime(date = new Date(), includeTime = true) {
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+
+ if (!includeTime) {
+ return `${year}-${month}-${day}`;
+ }
+
+ const hours = String(d.getHours()).padStart(2, '0');
+ const minutes = String(d.getMinutes()).padStart(2, '0');
+ const seconds = String(d.getSeconds()).padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+
+const taxRateOptions = [
+ { label: '1', value: 1 },
+ { label: '6', value: 6 },
+ { label: '13', value: 13 },
+]
+
+const data = reactive({
+ form: {
+ id: null,
+ supplierId: null, // 渚涘簲鍟咺D
+ supplierName: '', // 渚涘簲鍟嗗悕绉�
+ recorderId: userStore.userId, // 褰曞叆浜篒D
+ recorderName: userStore.name, // 褰曞叆浜哄鍚�
+ entryDate: getCurrentDate(), // 褰曞叆鏃ユ湡
+ remark: '', // 澶囨敞
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" }]
+ }
+})
+const { form, rules } = toRefs(data)
+
+// 鏂板浜у搧琛�
+const addProductRow = () => {
+ productList.value.push({
+ id: null,
+ productCategory: '',
+ specificationModel: '',
+ unit: '',
+ supplierName: form.value.supplierName || '',
+ itemType: '',
+ inboundNum: 0,
+ inboundDate: getCurrentDate(), // 榛樿褰撳ぉ鏃ユ湡
+ // quantityStock: 0,
+ taxInclusiveUnitPrice: 0,
+ taxInclusiveTotalPrice: 0,
+ taxRate: null,
+ taxExclusiveTotalPrice: 0,
+ });
+};
+
+// 鍒犻櫎浜у搧琛�
+const removeProductRow = (index) => {
+ productList.value.splice(index, 1);
+};
+
+// 璁$畻鎬讳环锛堟牴鎹暟閲忋�佸崟浠峰拰鍚◣鍗曚环锛�
+const calculateTotalPrice = (row) => {
+ // 璁$畻鏅�氭�讳环锛歩nboundNum * taxInclusiveUnitPrice
+ const quantity = Number(row.inboundNum || 0);
+ const taxInclusiveUnitPrice = Number(row.taxInclusiveUnitPrice || 0);
+ row.taxInclusiveTotalPrice = quantity * taxInclusiveUnitPrice;
+ calculateExclusivePrice(row);
+};
+
+// 璁$畻涓嶅惈绋庢�讳环锛堟牴鎹惈绋庢�讳环鍜岀◣鐜囷級
+const calculateExclusivePrice = (row) => {
+ const taxInclusiveTotalPrice = Number(row.taxInclusiveTotalPrice || 0);
+ const taxRate = Number(row.taxRate || 0);
+ row.taxExclusiveTotalPrice = taxInclusiveTotalPrice / (1 + taxRate / 100);
+};
+
+const submitForm = async () => {
+ try {
+ await proxy.$refs.formRef.validate()
+
+ if (!productList.value.length) {
+ proxy.$modal.msgError('璇疯嚦灏戞坊鍔犱竴鏉′骇鍝佹暟鎹�')
+ return
+ }
+
+ // 楠岃瘉鑷畾涔夋坊鍔犵殑鏁版嵁蹇呭~瀛楁
+ for (let i = 0; i < productList.value.length; i++) {
+ const product = productList.value[i];
+ if (!product.productCategory || !product.specificationModel || !product.unit) {
+ proxy.$modal.msgError(`绗�${i + 1}琛屼骇鍝佹暟鎹湭濉啓瀹屾暣锛堜骇鍝佸ぇ绫汇�佽鏍煎瀷鍙枫�佸崟浣嶄负蹇呭~锛塦)
+ return
+ }
+ if (!product.itemType) {
+ proxy.$modal.msgError(`绗�${i + 1}琛岃閫夋嫨鐗╁搧绫诲瀷`)
+ return
+ }
+ if (!product.inboundDate) {
+ proxy.$modal.msgError(`绗�${i + 1}琛岃閫夋嫨鍏ュ簱鏃ユ湡`)
+ return
+ }
+ const stock = Number(product?.inboundNum ?? 0);
+ if (!Number.isFinite(stock) || stock <= 0) {
+ proxy.$modal.msgError(`绗�${i + 1}琛屾湰娆″叆搴撴暟閲忛渶澶т簬0`)
+ return
+ }
+ }
+
+ const payloadList = productList.value.map(product => ({
+ id: product.id ?? null,
+ inboundNum: Number(product.inboundNum),
+ productCategory: product.productCategory,
+ specificationModel: product.specificationModel,
+ unit: product.unit,
+ supplierName: product.supplierName || form.value.supplierName,
+ itemType: product.itemType,
+ inboundDate: formatDateTime(product.inboundDate, false),
+ taxRate: Number(product.taxRate || 0),
+ taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
+ taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0),
+ taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0),
+ }));
+ loading.value = true
+ if (operationType.value === 'edit') {
+ const editPayload = payloadList[0]
+ await updateStockInCustom(editPayload)
+ } else {
+ await addStockInCustom(payloadList)
+ }
+
+ proxy.$modal.msgSuccess(operationType.value === 'edit' ? '缂栬緫鑷畾涔夊叆搴撴垚鍔�' : '鏂板鑷畾涔夊叆搴撴垚鍔�')
+ closeDia()
+ emit('success')
+
+ } catch (error) {
+ console.error('鎻愪氦澶辫触:', error)
+ if (!error.errors) {
+ proxy.$modal.msgError('鎿嶄綔澶辫触锛岃閲嶈瘯')
+ }
+ } finally {
+ loading.value = false
+ }
+}
+
+const closeDia = () => {
+ proxy.$refs.formRef.resetFields()
+ dialogFormVisible.value = false
+ productList.value = []
+ emit('close')
+}
+
+const openDialog = async (type, row) => {
+ operationType.value = type
+ dialogFormVisible.value = true
+
+ if (type === 'add') {
+ form.value = {
+ id: null,
+ supplierId: null,
+ supplierName: '',
+ recorderId: userStore.userId,
+ recorderName: userStore.name,
+ entryDate: getCurrentDate(),
+ remark: ''
+ }
+ productList.value = []
+ } else {
+ // 缂栬緫妯″紡锛氬皢琛屾暟鎹~鍏呭埌琛ㄦ牸涓互鏀寔淇敼
+ form.value = {
+ id: row?.id ?? null,
+ supplierId: row?.supplierId ?? null,
+ supplierName: row?.supplierName ?? '',
+ recorderId: userStore.userId,
+ recorderName: userStore.name,
+ entryDate: getCurrentDate(),
+ remark: row?.remark ?? ''
+ }
+ productList.value = [{
+ id: row?.id ?? null,
+ productCategory: row?.productCategory ?? '',
+ specificationModel: row?.specificationModel ?? '',
+ unit: row?.unit ?? '',
+ supplierName: row?.supplierName ?? '',
+ itemType: row?.itemType ?? '',
+ inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
+ inboundDate: row?.inboundDate ?? row?.createTime ?? '',
+ taxRate: Number(row?.taxRate ?? 0),
+ taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0),
+ taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0),
+ taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
+ }]
+ }
+}
+
+defineExpose({
+ openDialog,
+})
+</script>
+
+<style scoped lang="scss"></style>
+
diff --git a/src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue b/src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue
new file mode 100644
index 0000000..8ac355d
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue
@@ -0,0 +1,300 @@
+<template>
+ <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">
+ <div style="margin-bottom: 10px;" v-if="operationType === 'add'">
+ <el-button type="primary" @click="addProductRow">鏂板</el-button>
+ </div>
+ <el-table
+ :data="productList"
+ border
+ v-loading="loadingProducts"
+ >
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" width="200">
+ <template #default="scope">
+ <el-input v-model="scope.row.productCategory" placeholder="璇疯緭鍏ヤ骇鍝佸ぇ绫�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="200">
+ <template #default="scope">
+ <el-input v-model="scope.row.specificationModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍗曚綅" prop="unit" width="100">
+ <template #default="scope">
+ <el-input v-model="scope.row.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ簱鏁伴噺" prop="inboundNum" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ簱鏃ユ湡" prop="inboundDate" width="180">
+ <template #default="scope">
+ <el-date-picker
+ v-model="scope.row.inboundDate"
+ type="date"
+ placeholder="璇烽�夋嫨鍏ュ簱鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ style="width: 100%"
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍗曚环(鍏�)" prop="unitPrice" width="150">
+ <template #default="scope">
+ <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.unitPrice" @change="() => calculateTotalPrice(scope.row)" />
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鎬讳环(鍏�)"
+ prop="totalPrice"
+ width="150"
+ >
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" v-if="operationType === 'add'">
+ <template #default="scope">
+ <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
+import useUserStore from '@/store/modules/user'
+import {
+ addStockInCustom, updateProduct
+} from "@/api/inventoryManagement/stockIn.js";
+import { getCurrentDate } from "@/utils/index.js";
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close', 'success'])
+
+const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
+const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
+const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
+const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
+const loading = ref(false);
+
+function formatDateTime(date = new Date(), includeTime = true) {
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+
+ if (!includeTime) {
+ return `${year}-${month}-${day}`;
+ }
+
+ const hours = String(d.getHours()).padStart(2, '0');
+ const minutes = String(d.getMinutes()).padStart(2, '0');
+ const seconds = String(d.getSeconds()).padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+
+const itemTypeOptions = [
+ { label: '鐗╂枡', value: '鐗╂枡' },
+ { label: '鍘熸枡', value: '鍘熸枡' },
+ { label: '鎴愬搧', value: '鎴愬搧' },
+ { label: '鍏朵粬', value: '鍏朵粬' },
+]
+
+const taxRateOptions = [
+ { label: '1', value: 1 },
+ { label: '6', value: 6 },
+ { label: '13', value: 13 },
+]
+
+const data = reactive({
+ form: {
+ id: null,
+ supplierId: null, // 渚涘簲鍟咺D
+ supplierName: '', // 渚涘簲鍟嗗悕绉�
+ recorderId: userStore.userId, // 褰曞叆浜篒D
+ recorderName: userStore.name, // 褰曞叆浜哄鍚�
+ entryDate: getCurrentDate(), // 褰曞叆鏃ユ湡
+ remark: '', // 澶囨敞
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" }]
+ }
+})
+const { form, rules } = toRefs(data)
+
+// 鏂板浜у搧琛�
+const addProductRow = () => {
+ productList.value.push({
+ id: null,
+ productCategory: '',
+ specificationModel: '',
+ unit: '',
+ supplierName: form.value.supplierName || '',
+ itemType: '',
+ inboundNum: 0,
+ inboundDate: '',
+ quantityStock: 0,
+ unitPrice: 0,
+ totalPrice: 0,
+ taxRate: null,
+ taxExclusiveTotalPrice: 0,
+ });
+};
+
+// 鍒犻櫎浜у搧琛�
+const removeProductRow = (index) => {
+ productList.value.splice(index, 1);
+};
+
+// 璁$畻鎬讳环锛堟牴鎹暟閲忋�佸崟浠峰拰鍚◣鍗曚环锛�
+const calculateTotalPrice = (row) => {
+ // 璁$畻鏅�氭�讳环锛歩nboundNum * unitPrice
+ const quantity = Number(row.inboundNum || 0);
+ const unitPrice = Number(row.unitPrice || 0);
+ row.totalPrice = quantity * unitPrice;
+ calculateExclusivePrice(row);
+};
+
+// 璁$畻涓嶅惈绋庢�讳环锛堟牴鎹惈绋庢�讳环鍜岀◣鐜囷級
+const calculateExclusivePrice = (row) => {
+ const totalPrice = Number(row.totalPrice || 0);
+ const taxRate = Number(row.taxRate || 0);
+ row.taxExclusiveTotalPrice = totalPrice / (1 + taxRate / 100);
+};
+
+const submitForm = async () => {
+ try {
+ await proxy.$refs.formRef.validate()
+
+ if (!productList.value.length) {
+ proxy.$modal.msgError('璇疯嚦灏戞坊鍔犱竴鏉′骇鍝佹暟鎹�')
+ return
+ }
+
+ // 楠岃瘉鑷畾涔夋坊鍔犵殑鏁版嵁蹇呭~瀛楁
+ for (let i = 0; i < productList.value.length; i++) {
+ const product = productList.value[i];
+ if (!product.productCategory || !product.specificationModel || !product.unit) {
+ proxy.$modal.msgError(`绗�${i + 1}琛屼骇鍝佹暟鎹湭濉啓瀹屾暣锛堜骇鍝佸ぇ绫汇�佽鏍煎瀷鍙枫�佸崟浣嶄负蹇呭~锛塦)
+ return
+ }
+ if (!product.inboundDate) {
+ proxy.$modal.msgError(`绗�${i + 1}琛岃閫夋嫨鍏ュ簱鏃ユ湡`)
+ return
+ }
+ const stock = Number(product?.inboundNum ?? 0);
+ if (!Number.isFinite(stock) || stock <= 0) {
+ proxy.$modal.msgError(`绗�${i + 1}琛屾湰娆″叆搴撴暟閲忛渶澶т簬0`)
+ return
+ }
+ }
+
+ const payloadList = productList.value.map(product => ({
+ id: product.id ?? null,
+ inboundNum: Number(product.inboundNum),
+ productCategory: product.productCategory,
+ specificationModel: product.specificationModel,
+ unit: product.unit,
+ supplierName: product.supplierName || form.value.supplierName,
+ itemType: product.itemType,
+ inboundDate: formatDateTime(product.inboundDate, false),
+ taxRate: Number(product.taxRate || 0),
+ taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
+ unitPrice: Number(product.unitPrice || 0),
+ }));
+ loading.value = true
+ if (operationType.value === 'edit') {
+ const editPayload = payloadList[0]
+ await updateProduct(editPayload)
+ } else {
+ await addStockInCustom(payloadList)
+ }
+
+ proxy.$modal.msgSuccess(operationType.value === 'edit' ? '缂栬緫鑷畾涔夊叆搴撴垚鍔�' : '鏂板鑷畾涔夊叆搴撴垚鍔�')
+ closeDia()
+ emit('success')
+
+ } catch (error) {
+ console.error('鎻愪氦澶辫触:', error)
+ if (!error.errors) {
+ proxy.$modal.msgError('鎿嶄綔澶辫触锛岃閲嶈瘯')
+ }
+ } finally {
+ loading.value = false
+ }
+}
+
+const closeDia = () => {
+ proxy.$refs.formRef.resetFields()
+ dialogFormVisible.value = false
+ productList.value = []
+ emit('close')
+}
+
+const openDialog = async (type, row) => {
+ operationType.value = type
+ dialogFormVisible.value = true
+
+ if (type === 'add') {
+ form.value = {
+ id: null,
+ supplierId: null,
+ supplierName: '',
+ recorderId: userStore.userId,
+ recorderName: userStore.name,
+ entryDate: getCurrentDate(),
+ remark: ''
+ }
+ productList.value = []
+ } else {
+ // 缂栬緫妯″紡锛氬皢琛屾暟鎹~鍏呭埌琛ㄦ牸涓互鏀寔淇敼
+ form.value = {
+ id: row?.id ?? null,
+ supplierId: row?.supplierId ?? null,
+ supplierName: row?.supplierName ?? '',
+ recorderId: userStore.userId,
+ recorderName: userStore.name,
+ entryDate: getCurrentDate(),
+ remark: row?.remark ?? ''
+ }
+ productList.value = [{
+ id: row?.id ?? null,
+ productCategory: row?.productCategory ?? '',
+ specificationModel: row?.specificationModel ?? '',
+ unit: row?.unit ?? '',
+ supplierName: row?.supplierName ?? '',
+ itemType: row?.itemType ?? '',
+ inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
+ inboundDate: row?.inboundDate ?? row?.createTime ?? '',
+ taxRate: Number(row?.taxRate ?? 0),
+ unitPrice: Number(row?.unitPrice ?? 0),
+ taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
+ }]
+ }
+}
+
+defineExpose({
+ openDialog,
+})
+</script>
+
+<style scoped lang="scss"></style>
+
diff --git a/src/views/inventoryManagement/receiptManagement/index.vue b/src/views/inventoryManagement/receiptManagement/index.vue
index 238f3fd..7f1f83c 100644
--- a/src/views/inventoryManagement/receiptManagement/index.vue
+++ b/src/views/inventoryManagement/receiptManagement/index.vue
@@ -2,9 +2,23 @@
<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"
+ />
+ <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>
@@ -14,132 +28,70 @@
</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%"
- :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)" stripe>
+ <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="inboundDate" width="100" show-overflow-tooltip />
+ <el-table-column label="鎵规鍙�" prop="code" width="130" 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="70" show-overflow-tooltip />
- <el-table-column label="鍏ュ簱鏁伴噺" prop="inboundNum" 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="itemType" show-overflow-tooltip />
+ <el-table-column label="鍏ュ簱鏁伴噺" prop="inboundNum" width="100" show-overflow-tooltip />
+ <el-table-column label="鍓╀綑搴撳瓨" prop="inboundNum0" show-overflow-tooltip />
+ <el-table-column label="鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="150" />
+ <el-table-column label="鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" width="150" />
<el-table-column label="鍏ュ簱浜�" prop="createBy" width="80" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
<template #default="scope">
- <el-button link type="primary" size="small" @click="openForm('edit', scope.row);" :disabled="scope.row.createUser !== userStore.id">缂栬緫</el-button>
+ <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" />
+ <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="operationType === 'add' ? '鏂板鍏ュ簱' : '缂栬緫鍏ュ簱'" width="70%"
- @close="closeDia">
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <el-form-item label="閲囪喘璁㈠崟鍙�" prop="salesContractNo">
- <el-input
- v-model="form.purchaseContractNumber"
- placeholder="璇疯緭鍏ュ悎鍚屽彿"
- clearable
- @change="searchByContractNo"
- :disabled="operationType === 'edit'"
- >
- <template #append>
- <el-button
- icon="Search"
- @click="searchByContractNo"
- :loading="loadingProducts"
- />
- </template>
- </el-input>
- </el-form-item>
- <el-table
- :data="productList"
- border
- v-loading="loadingProducts"
- @selection-change="handleSelectionChange"
- stripe
- >
- <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="supplierName" width="100" />
- <el-table-column label="閲囪喘鏁伴噺" prop="quantity" width="100" />
- <el-table-column label="寰呭叆搴撴暟閲�" prop="quantity0" width="100" />
- <el-table-column label="鏈鍏ュ簱鏁伴噺" prop="quantityStock" width="150">
- <template #default="scope">
- <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" :max="scope.row.quantity0" />
- </template>
- </el-table-column>
- <el-table-column label="绋庣巼(%)" prop="taxRate" width="120" />
- <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>
- </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>
+ <form-dia-manual ref="formDiaManual" @close="handleQuery" @success="handleQuery"></form-dia-manual>
</div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
-import { ref } from 'vue'
+import { ref, reactive, toRefs, onMounted, getCurrentInstance, nextTick } from 'vue'
import { ElMessageBox } from "element-plus";
import useUserStore from '@/store/modules/user'
+import dayjs from 'dayjs'
import {
- getStockInPage,
- updateStockIn,
- addSutockIn,
- delStockIn,
- selectProductRecordListByPuechaserId
+ delStockInCustom,
+ getInPageByCustom,
} from "@/api/inventoryManagement/stockIn.js";
+import FormDiaManual from './components/formDiaManual.vue'
+import { getCurrentDate } from "@/utils/index.js";
-const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const tableData = ref([])
const selectedRows = ref([])
-const userList = ref([])
-
-
-const loading = ref(false);
const tableLoading = ref(false)
+const formDiaManual = ref()
const page = reactive({
current: 1,
@@ -147,37 +99,13 @@
})
const total = ref(0)
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
-const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
-const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
-const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
-const productSelectedRows = ref([]) // 浜у搧琛ㄦ牸閫変腑琛�
const data = reactive({
searchForm: {
- supplierName: '',
+ productCategory:'',
+ timeStr: getCurrentDate(),
},
- form: {
- id: null,
- purchaseContractNumber: '', // 閲囪喘璁㈠崟鍙�
- supplierId: null, // 渚涘簲鍟咺D
- supplierName: '', // 渚涘簲鍟嗗悕绉�
- inboundTime: '', // 鍏ュ簱鏃堕棿
- inboundBatch: '', // 鍏ュ簱鎵规
- recorderId: userStore.userId, // 褰曞叆浜篒D
- recorderName: userStore.name, // 褰曞叆浜哄鍚�
- entryDate: getCurrentDate(), // 褰曞叆鏃ユ湡
- remark: '', // 澶囨敞
- },
- rules: {
- purchaseContractNumber: [{ required: true, message: "璇疯緭鍏ラ噰璐悎鍚屽彿", trigger: "blur" }],
- supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
- inboundTime: [{ required: true, message: "璇烽�夋嫨鍏ュ簱鏃堕棿", trigger: "change" }],
- inboundBatch: [{ required: true, message: "璇疯緭鍏ュ叆搴撴壒娆�", trigger: "blur" }]
- }
})
-const { searchForm, form, rules } = toRefs(data)
-
+const { searchForm } = toRefs(data)
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
@@ -191,262 +119,94 @@
}
const getList = () => {
tableLoading.value = true
- getStockInPage({ ...searchForm.value, ...page }).then(res => {
+ const params = { ...page }
+ params.timeStr = searchForm.value.timeStr
+ params.productCategory = searchForm.value.productCategory
+ params.flag = false
+ const apiCall = getInPageByCustom(params)
+
+ apiCall.then(res => {
tableLoading.value = false
tableData.value = res.data.records
+
+ // 鍓嶇璁$畻鍚◣鎬讳环锛氬惈绋庢�讳环 = taxInclusiveUnitPrice * 鍏ュ簱鏁伴噺
+ tableData.value = tableData.value.map(item => {
+ const inboundNum = Number(item.inboundNum) || 0
+ const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0
+ item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * inboundNum).toFixed(2)
+ return item
+ })
+
total.value = res.data.total
- console.log('tableData:', tableData.value)
}).catch(() => {
tableLoading.value = false
})
}
-
-// 璋冪敤selectProductRecordListByPuechaserId杩欎釜鏂规硶鏍规嵁鍚堝悓鏌ヨ鍒癷d锛屽啀璋冪敤getProductRecordByhetong杩欎釜鏂规硶鏍规嵁id鏌ヨ鍒颁骇鍝佽鍗曡褰�
-// 鏂板鏍规嵁鍚堝悓鍙锋煡璇骇鍝佽褰曠殑鏂规硶
-const searchByContractNo = async () =>
-{
- if (!form.value.purchaseContractNumber) {
- proxy.$modal.msgWarning('璇疯緭鍏ュ悎鍚屽彿')
- return
- }
- try {
- loadingProducts.value = true
- // 鏍规嵁鍚堝悓鏌ヨ浜у搧璁板綍
- const productRes = await selectProductRecordListByPuechaserId({
- purchaseContractNumber: form.value.purchaseContractNumber
- });
- console.log('productRes:', productRes)
- if (!productRes.data || productRes.data.length === 0) {
- proxy.$modal.msgWarning('璇ュ悎鍚屼笅娌℃湁浜у搧璁板綍')
- productList.value = [];
- return
- }
- // 澶勭悊浜у搧鏁版嵁锛屾坊鍔犳湰娆″叆搴撴暟閲忓瓧娈�
- productList.value = productRes.data.map(item => ({
- ...item,
- quantityStock: 0 // 鍒濆鍖栨湰娆″叆搴撴暟閲忎负0
- }))
- } catch (error) {
- console.error('鏌ヨ浜у搧璁板綍澶辫触:', error)
- proxy.$modal.msgError('鏌ヨ浜у搧璁板綍澶辫触')
- productList.value = [];
- } finally {
- loadingProducts.value = false
- }
+// 鎵撳紑寮规
+const openForm = async (type, row) => {
+ await nextTick(() => {
+ formDiaManual.value?.openDialog(type, row)
+ })
}
-
-// 鎵撳紑寮规
- const openForm = async (type, row) => {
- operationType.value = type
- dialogFormVisible.value = true
- selectedRows.value = []
-
- if (type === 'add') {
- // 鏂板鏃跺垵濮嬪寲琛ㄥ崟
- form.value = {
- id: null,
- purchaseContractNumber: '',
- supplierId: null,
- supplierName: '',
- inboundTime: '',
- inboundBatch: '',
- recorderId: userStore.userId,
- recorderName: userStore.name,
- entryDate: getCurrentDate(),
- remark: ''
- }
- productList.value = [] // 娓呯┖浜у搧鍒楄〃
- } else {
- form.value = JSON.parse(JSON.stringify(row))
- try {
- loadingProducts.value = true
- // 鏍规嵁鍚堝悓鍙峰姞杞藉搴旂殑浜у搧鍒楄〃锛堝亣璁� getProductByContract 鏄彲鐢ㄦ帴鍙o級
- const res = await selectProductRecordListByPuechaserId({
- purchaseContractNumber: form.value.purchaseContractNumber,
- id: row.id
- });
- productList.value = res.data.map(item => ({
- ...item,
- quantityStock: row.inboundNum // 濡傛灉宸叉湁鍏ュ簱鏁伴噺鍒欎繚鐣�
- }))
- selectedRows.value = productList.value
- } catch (error) {
- console.error('鍔犺浇浜у搧澶辫触:', error)
- proxy.$modal.msgError('鍔犺浇浜у搧澶辫触')
- productList.value = []
- } finally {
- loadingProducts.value = false
- }
- }
- }
-
- const updatePro = async () => {
- // 鍑嗗鎻愪氦鏁版嵁
- // 鍑嗗鎻愪氦鏁版嵁 - 淇敼涓哄悗绔渶瑕佺殑鏍煎紡
- const stockInData = {
- id: selectedRows.value[0].recordId,
- quantityStock: Number(selectedRows.value[0].quantityStock),// 浣跨敤鏂版牸寮忓寲鍑芥暟
- };
- await updateStockIn(stockInData)
- proxy.$modal.msgSuccess('淇敼鍏ュ簱鎴愬姛')
- closeDia()
- getList() // 鍒锋柊鍒楄〃
- }
-
-// 鎻愪氦琛ㄥ崟
- const submitForm = async () => {
- // 楠岃瘉鑷冲皯閫夋嫨浜嗕竴涓骇鍝�
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgError('璇峰厛鏌ヨ骞堕�夋嫨浜у搧')
- return
- }
- if(operationType.value !== 'add'){
- await updatePro()
- return
- }
- try {
- await proxy.$refs.formRef.validate()
- // 楠岃瘉鍏ュ簱鏁伴噺
- const invalidProducts = selectedRows.value.filter(
- product => product.quantityStock <= 0 || product.quantityStock > product.quantity0
- )
-
- if (invalidProducts.length > 0) {
- proxy.$modal.msgError('璇蜂负鎵�鏈変骇鍝佽緭鍏ユ湁鏁堢殑鍏ュ簱鏁伴噺')
- return
- }
-
- // 鍑嗗鎻愪氦鏁版嵁
- // 鍑嗗鎻愪氦鏁版嵁 - 淇敼涓哄悗绔渶瑕佺殑鏍煎紡
- const stockInData = {
- // 鍏ュ簱鍗曞熀鏈俊鎭�
- ...form.value,
- inboundTime: formatDateTime(form.value.inboundTime),
- nickName: userStore.nickName,// 浣跨敤鏂版牸寮忓寲鍑芥暟
- details: selectedRows.value.map(product => ({
- id: product.id,
- inboundQuantity: Number(product.quantityStock)
- })),
- };
- console.log('鍑嗗鎻愪氦鐨勬暟鎹�:', JSON.parse(JSON.stringify(stockInData)));
- // 璋冪敤API
- loading.value = true
- await addSutockIn(stockInData)
-
- proxy.$modal.msgSuccess('鏂板鍏ュ簱鎴愬姛')
- closeDia()
- getList() // 鍒锋柊鍒楄〃
-
- } catch (error) {
- console.error('鎻愪氦澶辫触:', error)
- if (!error.errors) {
- proxy.$modal.msgError('鎿嶄綔澶辫触锛岃閲嶈瘯')
- }
- } finally {
- loading.value = false
- }
- }
-
-// 鍏抽棴寮规
- const closeDia = () => {
- proxy.$refs.formRef.resetFields()
- dialogFormVisible.value = false
-
- }
// 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter(item => item.id);
- console.log('selection', selectedRows.value)
- }
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection.filter(item => item.id)
+}
- const expandedRowKeys = ref([])
+const expandedRowKeys = ref([])
// 涓昏〃鍚堣鏂规硶
- const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']);
- };
+const summarizeMainTable = (param) => {
+ return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice'])
+}
// 瀵煎嚭
- 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) {
- // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
- const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id);
- 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(() => {
- delStockIn({ids:ids}).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
- getList()
- })
- }).catch(() => {
- proxy.$modal.msg("宸插彇娑�")
- })
- }
-
-// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
-// 淇敼涓烘洿閫氱敤鐨勬棩鏈熸椂闂存牸寮忓寲鍑芥暟
-function formatDateTime(date = new Date(), includeTime = true) {
- const d = new Date(date);
- const year = d.getFullYear();
- const month = String(d.getMonth() + 1).padStart(2, '0');
- const day = String(d.getDate()).padStart(2, '0');
-
- if (!includeTime) {
- return `${year}-${month}-${day}`; // 淇濇寔鍘熸湁 getCurrentDate 鍔熻兘
- }
-
- // 鏂板鏃堕棿閮ㄥ垎鏍煎紡鍖�
- const hours = String(d.getHours()).padStart(2, '0');
- const minutes = String(d.getMinutes()).padStart(2, '0');
- const seconds = String(d.getSeconds()).padStart(2, '0');
-
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-}
-
-// 淇濇寔鍘熸湁 getCurrentDate 鐨勫吋瀹规��
-function getCurrentDate() {
- return formatDateTime(new Date(), false);
-}
-
-
-
-
- onMounted(() => {
- getList()
+const handleOut = () => {
+ ElMessageBox.confirm('鏄惁纭瀵煎嚭锛�', '瀵煎嚭', {
+ confirmButtonText: '纭',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning',
+ }).then(() => {
+ const exportUrl = "/stockin/exportTwo"
+ proxy.download(exportUrl, {}, '鍏ュ簱鍙拌处.xlsx')
+ }).catch(() => {
+ proxy.$modal.msg("宸插彇娑�")
})
+}
+
+// 鍒犻櫎
+const handleDelete = () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁')
+ return
+ }
+ const ids = selectedRows.value.map(item => item.id)
+
+ ElMessageBox.confirm('閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�', '鍒犻櫎', {
+ confirmButtonText: '纭',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning',
+ }).then(() => {
+ // 鏉愭枡鍏ュ簱鍒犻櫎
+ delStockInCustom(ids).then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+ getList()
+ }).catch(() => {
+ proxy.$modal.msgError("鍒犻櫎澶辫触")
+ })
+ }).catch(() => {
+ proxy.$modal.msg("宸插彇娑�")
+ })
+}
+
+onMounted(() => {
+ getList()
+})
</script>
<style scoped lang="scss"></style>
+
+
+
diff --git a/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue b/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
new file mode 100644
index 0000000..d66b0e6
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
@@ -0,0 +1,154 @@
+<template>
+ <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '鏂板鏉愭枡搴撳瓨' : '缂栬緫鏉愭枡搴撳瓨'" width="70%"
+ @update:model-value="$emit('update:dialogFormVisible', $event)" @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="productCategory">
+ <el-input disabled v-model="form.productCategory" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="specificationModel">
+ <el-input disabled v-model="form.specificationModel" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input disabled v-model="form.unit" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐗╁搧绫诲瀷锛�" prop="itemType">
+ <el-input disabled v-model="form.itemType" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鏃堕棿锛�" prop="createTime">
+ <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
+ type="date" placeholder="璇烽�夋嫨" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="搴撳瓨鏁伴噺锛�" prop="inboundNum">
+ <el-input v-model="form.inboundNum" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="宸插嚭搴撴暟閲忥細" prop="totalInboundNum">
+ <el-input disabled v-model="form.totalInboundNum" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="寰呭嚭搴撴暟閲忥細" prop="inboundNum0">
+ <el-input disabled v-model="form.inboundNum0" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input v-model="form.taxInclusiveUnitPrice" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="鑷姩璁$畻" clearable />
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, watch } from 'vue'
+
+const props = defineProps({
+ dialogFormVisible: Boolean,
+ operationType: String,
+ formData: Object
+})
+
+const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
+
+const formRef = ref()
+
+const data = reactive({
+ form: {
+ productCategory: '',
+ specificationModel: '',
+ unit: '',
+ itemType: '',
+ createTime: '',
+ inboundNum: '',
+ totalInboundNum: '',
+ inboundNum0: '',
+ taxInclusiveUnitPrice: '',
+ taxInclusiveTotalPrice: ''
+ },
+ rules: {
+ productCategory: [{ required: true, message: '璇疯緭鍏ヤ骇鍝佸ぇ绫�', trigger: 'blur' }],
+ specificationModel: [{ required: true, message: '璇疯緭鍏ヨ鏍煎瀷鍙�', trigger: 'blur' }],
+ unit: [{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: 'blur' }],
+ itemType: [{ required: true, message: '璇疯緭鍏ョ墿鍝佺被鍨�', trigger: 'blur' }],
+ createTime: [{ required: true, message: '璇烽�夋嫨鍏ュ簱鏃堕棿', trigger: 'change' }],
+ inboundNum: [{ required: true, message: '璇疯緭鍏ュ簱瀛樻暟閲�', trigger: 'blur' }],
+ taxInclusiveUnitPrice: [{ required: true, message: '璇疯緭鍏ュ崟浠�', trigger: 'blur' }]
+ }
+})
+
+const { form, rules } = toRefs(data)
+
+// 璁$畻鎬讳环锛氭�讳环 = 鍗曚环 脳 鍓╀綑搴撳瓨
+const calculateTotalPrice = () => {
+ const unitPrice = parseFloat(form.value.taxInclusiveUnitPrice) || 0
+ const stockQuantity = parseFloat(form.value.inboundNum) || 0 // 搴撳瓨鏁伴噺
+ const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // 宸插嚭搴撴暟閲�
+ const remainingStock = stockQuantity - outboundQuantity // 鍓╀綑搴撳瓨
+ form.value.taxInclusiveTotalPrice = (unitPrice * remainingStock).toFixed(2)
+}
+
+// 鐩戝惉formData鍙樺寲
+watch(() => props.formData, (newVal) => {
+ if (newVal) {
+ form.value = { ...newVal }
+ // 鏁版嵁鍙樺寲鍚庨噸鏂拌绠楁�讳环
+ calculateTotalPrice()
+ }
+}, { immediate: true })
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ emit('submit', form.value)
+ }
+ })
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ emit('close')
+ emit('update:dialogFormVisible', false)
+}
+
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: center;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue b/src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue
new file mode 100644
index 0000000..1653307
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue
@@ -0,0 +1,147 @@
+<template>
+ <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '鏂板鎴愬搧搴撳瓨' : '缂栬緫鎴愬搧搴撳瓨'" width="70%"
+ @update:model-value="$emit('update:dialogFormVisible', $event)" @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="productCategory">
+ <el-input disabled v-model="form.productCategory" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="specificationModel">
+ <el-input disabled v-model="form.specificationModel" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input disabled v-model="form.unit" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鏃堕棿锛�" prop="createTime">
+ <el-date-picker style="width: 100%" v-model="form.createTime" 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="inboundNum">
+ <el-input v-model="form.inboundNum" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="宸插嚭搴撴暟閲忥細" prop="totalInboundNum">
+ <el-input disabled v-model="form.totalInboundNum" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="寰呭嚭搴撴暟閲忥細" prop="inboundNum0">
+ <el-input disabled v-model="form.inboundNum0" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍗曚环(鍏�)锛�" prop="unitPrice">
+ <el-input v-model="form.unitPrice" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎬讳环(鍏�)锛�" prop="totalPrice">
+ <el-input disabled v-model="form.totalPrice" placeholder="鑷姩璁$畻" clearable />
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, watch } from 'vue'
+
+const props = defineProps({
+ dialogFormVisible: Boolean,
+ operationType: String,
+ formData: Object
+})
+
+const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
+
+const formRef = ref()
+
+const data = reactive({
+ form: {
+ productCategory: '',
+ specificationModel: '',
+ unit: '',
+ createTime: '',
+ inboundNum: '',
+ totalInboundNum: '',
+ inboundNum0: '',
+ unitPrice: '',
+ totalPrice: ''
+ },
+ rules: {
+ productCategory: [{ required: true, message: '璇疯緭鍏ヤ骇鍝佸ぇ绫�', trigger: 'blur' }],
+ specificationModel: [{ required: true, message: '璇疯緭鍏ヨ鏍煎瀷鍙�', trigger: 'blur' }],
+ unit: [{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: 'blur' }],
+ createTime: [{ required: true, message: '璇烽�夋嫨鍏ュ簱鏃堕棿', trigger: 'change' }],
+ inboundNum: [{ required: true, message: '璇疯緭鍏ュ簱瀛樻暟閲�', trigger: 'blur' }],
+ unitPrice: [{ required: true, message: '璇疯緭鍏ュ崟浠�', trigger: 'blur' }]
+ }
+})
+
+const { form, rules } = toRefs(data)
+
+// 璁$畻鎬讳环锛氭�讳环 = 鍗曚环 脳 鍓╀綑搴撳瓨
+const calculateTotalPrice = () => {
+ const unitPrice = parseFloat(form.value.unitPrice) || 0
+ const stockQuantity = parseFloat(form.value.inboundNum) || 0 // 搴撳瓨鏁伴噺
+ const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // 宸插嚭搴撴暟閲�
+ const remainingStock = stockQuantity - outboundQuantity // 鍓╀綑搴撳瓨
+ form.value.totalPrice = (unitPrice * remainingStock).toFixed(2)
+}
+
+// 鐩戝惉formData鍙樺寲
+watch(() => props.formData, (newVal) => {
+ if (newVal) {
+ form.value = { ...newVal }
+ // 鏁版嵁鍙樺寲鍚庨噸鏂拌绠楁�讳环
+ calculateTotalPrice()
+ }
+}, { immediate: true })
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ emit('submit', form.value)
+ }
+ })
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ emit('close')
+ emit('update:dialogFormVisible', false)
+}
+
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: center;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue b/src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue
new file mode 100644
index 0000000..5da2eee
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue
@@ -0,0 +1,147 @@
+<template>
+ <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '鏂板鍘熸枡搴撳瓨' : '缂栬緫鍘熸枡搴撳瓨'" width="70%"
+ @update:model-value="$emit('update:dialogFormVisible', $event)" @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="productCategory">
+ <el-input disabled v-model="form.productCategory" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="specificationModel">
+ <el-input disabled v-model="form.specificationModel" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input disabled v-model="form.unit" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鏃堕棿锛�" prop="createTime">
+ <el-date-picker style="width: 100%" v-model="form.createTime" 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="inboundNum">
+ <el-input v-model="form.inboundNum" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="宸插嚭搴撴暟閲忥細" prop="totalInboundNum">
+ <el-input disabled v-model="form.totalInboundNum" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="寰呭嚭搴撴暟閲忥細" prop="inboundNum0">
+ <el-input disabled v-model="form.inboundNum0" placeholder="璇疯緭鍏�" clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input v-model="form.taxInclusiveUnitPrice" placeholder="璇疯緭鍏�" clearable @input="calculateTotalPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="鑷姩璁$畻" clearable />
+ </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>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, watch } from 'vue'
+
+const props = defineProps({
+ dialogFormVisible: Boolean,
+ operationType: String,
+ formData: Object
+})
+
+const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
+
+const formRef = ref()
+
+const data = reactive({
+ form: {
+ productCategory: '',
+ specificationModel: '',
+ unit: '',
+ createTime: '',
+ inboundNum: '',
+ totalInboundNum: '',
+ inboundNum0: '',
+ taxInclusiveUnitPrice: '',
+ taxInclusiveTotalPrice: ''
+ },
+ rules: {
+ productCategory: [{ required: true, message: '璇疯緭鍏ヤ骇鍝佸ぇ绫�', trigger: 'blur' }],
+ specificationModel: [{ required: true, message: '璇疯緭鍏ヨ鏍煎瀷鍙�', trigger: 'blur' }],
+ unit: [{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: 'blur' }],
+ createTime: [{ required: true, message: '璇烽�夋嫨鍏ュ簱鏃堕棿', trigger: 'change' }],
+ inboundNum: [{ required: true, message: '璇疯緭鍏ュ簱瀛樻暟閲�', trigger: 'blur' }],
+ taxInclusiveUnitPrice: [{ required: true, message: '璇疯緭鍏ュ惈绋庡崟浠�', trigger: 'blur' }]
+ }
+})
+
+const { form, rules } = toRefs(data)
+
+// 璁$畻鎬讳环锛氬惈绋庢�讳环 = 鍚◣鍗曚环 脳 鍓╀綑搴撳瓨
+const calculateTotalPrice = () => {
+ const unitPrice = parseFloat(form.value.taxInclusiveUnitPrice) || 0
+ const stockQuantity = parseFloat(form.value.inboundNum) || 0 // 搴撳瓨鏁伴噺
+ const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // 宸插嚭搴撴暟閲�
+ const remainingStock = stockQuantity - outboundQuantity // 鍓╀綑搴撳瓨
+ form.value.taxInclusiveTotalPrice = (unitPrice * remainingStock).toFixed(2)
+}
+
+// 鐩戝惉formData鍙樺寲
+watch(() => props.formData, (newVal) => {
+ if (newVal) {
+ form.value = { ...newVal }
+ // 鏁版嵁鍙樺寲鍚庨噸鏂拌绠楁�讳环
+ calculateTotalPrice()
+ }
+}, { immediate: true })
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ emit('submit', form.value)
+ }
+ })
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ emit('close')
+ emit('update:dialogFormVisible', false)
+}
+
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: center;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inventoryManagement/stockManagement/index.vue b/src/views/inventoryManagement/stockManagement/index.vue
index 06fcaf8..508395e 100644
--- a/src/views/inventoryManagement/stockManagement/index.vue
+++ b/src/views/inventoryManagement/stockManagement/index.vue
@@ -2,155 +2,101 @@
<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"
+ />
+ <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 type="primary" @click="openForm('add')">鏂板</el-button> -->
<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%"
- :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)" stripe>
+ <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="createTime" width="100" 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="inboundDate" width="100" show-overflow-tooltip />
+ <el-table-column label="鎵规鍙�" prop="code" width="130" 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="inboundNum0" width="100" 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="100" 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">
+ <el-table-column label="鐗╁搧绫诲瀷" prop="itemType" width="120" show-overflow-tooltip />
+ <el-table-column label="宸插彂鏂欐暟閲�" prop="totalInboundNum" width="100" show-overflow-tooltip />
+ <el-table-column label="鍓╀綑搴撳瓨" prop="inboundNum0" width="100" show-overflow-tooltip />
+ <el-table-column label="鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="150" />
+ <el-table-column label="鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" width="150" />
+ <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
<template #default="scope">
- <el-button link type="primary" size="small" @click="openForm('edit', scope.row);" :disabled="scope.row.createUser !== userStore.id">缂栬緫</el-button>
+ <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" />
+ <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="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 disabled v-model="form.supplierName" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="浜у搧澶х被锛�" prop="productId">
- <el-select disabled v-model="form.productCategory" placeholder="璇烽�夋嫨" clearable filterable @change="handleProductChange">
- <el-option v-for="item in productList" :key="item.id" :label="item.productName"
- :value="item.productName" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productManageId">
- <el-select disabled v-model="form.specificationModel" placeholder="璇峰厛閫夋嫨浜у搧澶х被" clearable filterable :disabled="!form.productCategory"
- @change="handleModelChange">
- <el-option v-for="item in productModelList" :key="item.id" :label="item.model"
- :value="item.id" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍗曚綅锛�" prop="customerId">
- <el-input disabled v-model="form.unit" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="搴撳瓨鏃堕棿锛�" prop="projectName">
- <el-date-picker style="width: 100%" v-model="form.updateTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
- type="date" placeholder="璇烽�夋嫨" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍏ュ簱鏃堕棿锛�" prop="projectName">
- <el-date-picker style="width: 100%" v-model="form.createTime" 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="customerId">
- <el-input disabled v-model="form.taxInclusiveUnitPrice" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚◣鎬讳环锛�" prop="customerContractNo">
- <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
-
- <el-col :span="12">
- <el-form-item label="绋庣巼锛�" prop="customerId">
- <el-input disabled v-model="form.taxRate" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环锛�" prop="entryDate">
- <el-input disabled v-model="form.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
-
- <el-col :span="12">
- <el-form-item label="鍑哄簱浜猴細" prop="entryPerson">
- <el-select v-model="form.createUser" placeholder="璇烽�夋嫨" clearable>
- <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
- </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>
+ <!-- 鏉愭枡搴撳瓨寮规 -->
+ <FormDiaManual
+ v-model:dialogFormVisible="manualDialogVisible"
+ :operationType="operationType"
+ :formData="form"
+ @submit="submitForm"
+ @close="closeDia"
+ />
</div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
-import { ref } from '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 ,
- updateStockManage,
+ getStockManagePageByCustom,
delStockManage,
- exportStockManage
} from "@/api/inventoryManagement/stockManage.js";
import {
- updateManagement
+ updateManagement, updateManagementByCustom, updateStockIn
} from "@/api/inventoryManagement/stockIn.js";
+import { getCurrentDate } from "@/utils/index.js";
+
+// 瀵煎叆鏉愭枡搴撳瓨寮规缁勪欢
+import FormDiaManual from './components/FormDiaManual.vue'
+
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const tableData = ref([])
@@ -167,17 +113,22 @@
})
const total = ref(0)
const fileList = ref([])
-
+const loading = ref(false);
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const operationType = ref('')
-const dialogFormVisible = ref(false)
+
+// 鏉愭枡搴撳瓨寮规鏄剧ず鐘舵��
+const manualDialogVisible = ref(false)
+
const data = reactive({
searchForm: {
- supplierName: '',
+ // supplierName: '',
+ productCategory:'',
+ customerName: '',
+ timeStr: getCurrentDate(),
},
form: {
supplierId: null,
- supplierName: '',
productId: null,
productName: '',
userId: userStore.userId,
@@ -194,20 +145,24 @@
inboundBatch: '',
stockQuantity: '',
boundTime: '',
+ warnNum: '', // 鏂板鏈�浣庡簱瀛樺瓧娈�
+ salesLedgerProductId: null,
},
rules: {
- supplierName: [{ required: true, message: '璇疯緭鍏ヤ緵搴斿晢鍚嶇О', trigger: 'blur' }],
+ // 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' }]
+ inboundPerson: [{ required: true, message: '璇烽�夋嫨鍑哄簱浜�', trigger: 'change' }],
+ warnNum: [{ required: true, message: '璇疯緭鍏ユ渶浣庡簱瀛�', trigger: 'blur' }],
}
})
const { searchForm, form, rules } = toRefs(data)
@@ -223,16 +178,39 @@
page.size = obj.limit;
getList()
}
+const buildQueryParams = () => {
+ const params = {
+ ...page,
+ timeStr: searchForm.value.timeStr,
+ }
+ params.productCategory = searchForm.value.productCategory
+ return params
+}
+
const getList = () => {
tableLoading.value = true
- getStockManagePage({ ...searchForm.value, ...page }).then(res => {
+ const params = buildQueryParams()
+ getStockManagePageByCustom(params).then(res => {
tableLoading.value = false
tableData.value = res.data.records
- console.log('res', res)
- // tableData.value.map(item => {
- // item.children = []
- // })
+
+ // 涓鸿〃鏍兼暟鎹嚜鍔ㄨ绠楁�讳环
+ 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)
+
+ // 鏉愭枡搴撳瓨锛氬惈绋庢�讳环 = 鍚◣鍗曚环 脳 鍓╀綑搴撳瓨
+ const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0
+ item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2)
+
+ return item
+ })
+
total.value = res.data.total
+ // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
+ // checkStockAndCreatePurchase();
}).catch(() => {
tableLoading.value = false
})
@@ -252,6 +230,16 @@
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
@@ -259,11 +247,6 @@
productData.value = []
let userLists = await userListNoPageByTenantId()
userList.value = userLists.data
- // customerList().then(res => {
- // customerOption.value = res
- // })
- // console.log('userStore.id', userStore.id)
- // form.value.entryPerson = userStore.id
if (type === 'edit') {
form.value = { ...row }
productTreeList().then(res =>{
@@ -276,48 +259,65 @@
}
})
})
-
-
- // getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
-
- // form.value.entryPerson = Number(res.entryPerson)
- // productData.value = form.value.productData
- // fileList.value = form.value.salesLedgerFiles
- // })
}
form.value.entryDate = getCurrentDate() // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
- dialogFormVisible.value = true
+
+ // 浠呮潗鏂欏簱瀛樺脊妗�
+ manualDialogVisible.value = true
}
// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- console.log(form.value)
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 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 = 1
- updateManagement(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛")
- closeDia()
- getList()
- })
- }
+const submitForm = (submittedData) => {
+ console.log('瀛愮粍浠舵彁浜ょ殑鏁版嵁:', submittedData)
+
+ // 浣跨敤瀛愮粍浠舵彁浜ょ殑鏁版嵁锛岃�屼笉鏄埗缁勪欢鐨刦orm瀵硅薄
+ const submitData = { ...submittedData }
+
+ // 鏉愭枡搴撳瓨锛氱Щ闄ゅ惈绋庢�讳环瀛楁
+ delete submitData.taxInclusiveTotalPrice
+ // 绉婚櫎鍏朵粬鍙兘鐨勬�讳环瀛楁
+ delete submitData.taxExclusiveTotalPrice
+
+ console.log('鎻愪氦缁欏悗绔殑鏁版嵁锛堝凡绉婚櫎鎬讳环瀛楁锛�:', submitData)
+
+ // 鏉愭枡搴撳瓨浣跨敤 updateManagementByCustom 鎺ュ彛
+ updateManagementByCustom(submitData).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")
- dialogFormVisible.value = false
+ manualDialogVisible.value = false
}
// 瀵煎嚭
@@ -330,7 +330,9 @@
type: 'warning',
}
).then(() => {
- proxy.download("/stockin/exportCopy", {}, '搴撳瓨淇℃伅.xlsx')
+ const exportParams = buildQueryParams()
+ const exportUrl = "/stockin/exportCopyTwo"
+ proxy.download(exportUrl, exportParams, '搴撳瓨淇℃伅.xlsx')
}).catch(() => {
proxy.$modal.msg("宸插彇娑�")
})
@@ -339,12 +341,6 @@
const handleDelete = () => {
let ids = []
if (selectedRows.value.length > 0) {
- // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
- const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id);
- if (unauthorizedData.length > 0) {
- proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
- return;
- }
ids = selectedRows.value.map(item => item.id);
} else {
proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁')
@@ -366,17 +362,26 @@
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()
+ // checkStockAndCreatePurchase();
+ // 姣忓皬鏃舵鏌ヤ竴娆″簱瀛�
+ // const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000);
+
+// onUnmounted(() => {
+// // 缁勪欢鍗歌浇鏃舵竻闄ゅ畾鏃跺櫒
+// clearInterval(intervalId);
+// });
})
</script>
-<style scoped lang="scss"></style>
+<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
diff --git a/src/views/inventoryManagement/stockReport/index.vue b/src/views/inventoryManagement/stockReport/index.vue
new file mode 100644
index 0000000..728c1ab
--- /dev/null
+++ b/src/views/inventoryManagement/stockReport/index.vue
@@ -0,0 +1,713 @@
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储琛ㄥ崟 -->
+ <div class="search_form">
+ <div class="search_left">
+ <span class="search_title">鎶ヨ〃绫诲瀷锛�</span>
+ <el-select
+ v-model="searchForm.reportType"
+ style="width: 150px;"
+ placeholder="璇烽�夋嫨"
+ @change="handleReportTypeChange"
+ >
+ <el-option label="鏃ユ姤" value="daily" />
+ <el-option label="鏈堟姤" value="monthly" />
+ <el-option label="浣滀笟鎶ヨ〃" value="work" />
+ <el-option label="杩涘嚭瀛樻姤琛�" value="inout" />
+ </el-select>
+
+ <span class="search_title ml10">鏃堕棿鑼冨洿锛�</span>
+ <el-date-picker
+ v-if="searchForm.reportType === 'daily'"
+ v-model="searchForm.singleDate"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 200px;"
+ />
+ <el-date-picker
+ v-else-if="searchForm.reportType === 'monthly'"
+ v-model="searchForm.monthRange"
+ type="monthrange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫湀浠�"
+ end-placeholder="缁撴潫鏈堜唤"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;"
+ />
+ <el-date-picker
+ v-else
+ v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;"
+ />
+
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
+ 鏌ヨ
+ </el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </div>
+
+ <div class="search_right">
+ <el-button type="success" @click="handleExport" icon="Download">
+ 瀵煎嚭鎶ヨ〃
+ </el-button>
+ </div>
+ </div>
+
+ <!-- 缁熻鍗$墖 -->
+ <div class="stats_cards" v-if="reportData.summary">
+ <el-row :gutter="20">
+ <el-col :span="6">
+ <el-card class="stats_card">
+ <div class="stats_content">
+ <div class="stats_icon in">
+ <el-icon><TrendCharts /></el-icon>
+ </div>
+ <div class="stats_info">
+ <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>
+ <div class="stats_label">鎬诲叆搴撻噺</div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="stats_card">
+ <div class="stats_content">
+ <div class="stats_icon out">
+ <el-icon><TrendCharts /></el-icon>
+ </div>
+ <div class="stats_info">
+ <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>
+ <div class="stats_label">鎬诲嚭搴撻噺</div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="stats_card">
+ <div class="stats_content">
+ <div class="stats_icon stock">
+ <el-icon><Box /></el-icon>
+ </div>
+ <div class="stats_info">
+ <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>
+ <div class="stats_label">褰撳墠搴撳瓨</div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="stats_card">
+ <div class="stats_content">
+ <div class="stats_icon turnover">
+ <el-icon><Refresh /></el-icon>
+ </div>
+ <div class="stats_info">
+ <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>
+ <div class="stats_label">鍛ㄨ浆鐜�</div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+
+ <!-- 鍥捐〃鍖哄煙 -->
+ <div class="chart_section" v-if="reportData.chartData">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-card>
+ <template #header>
+ <span>搴撳瓨瓒嬪娍鍥�</span>
+ </template>
+ <div ref="trendChart" style="height: 300px;"></div>
+ </el-card>
+ </el-col>
+ <el-col :span="12">
+ <el-card>
+ <template #header>
+ <span>杩涘嚭搴撳姣�</span>
+ </template>
+ <div ref="comparisonChart" style="height: 300px;"></div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+
+ <!-- 璇︾粏鏁版嵁琛ㄦ牸 -->
+ <div class="table_section">
+ <el-card>
+ <template #header>
+ <span>{{ getTableTitle() }}</span>
+ </template>
+ <el-table
+ v-loading="tableLoading"
+ :data="reportData.tableData"
+ border
+ height="400"
+ style="width: 100%"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ >
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column
+ v-if="searchForm.reportType === 'daily'"
+ label="鏃ユ湡"
+ prop="createTime"
+ width="100"
+ align="center"
+ />
+ <el-table-column
+ v-if="searchForm.reportType === 'monthly'"
+ label="鏈堜唤"
+ prop="createTime"
+ width="100"
+ align="center"
+ />
+ <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="productCategory"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="瑙勬牸鍨嬪彿"
+ prop="specificationModel"
+ min-width="200"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍗曚綅"
+ prop="unit"
+ width="70"
+ show-overflow-tooltip
+ />
+ <!-- <el-table-column
+ label="鏈熷垵搴撳瓨"
+ prop="beginStock"
+ width="100"
+ align="center"
+ /> -->
+ <el-table-column
+ label="鍏ュ簱鏁伴噺"
+ prop="inboundNum"
+ width="100"
+ align="center"
+ />
+ <!-- <el-table-column
+ label="鍑哄簱鏁伴噺"
+ prop=""
+ width="100"
+ align="center"
+ /> -->
+ <el-table-column
+ label="鐜板湪搴撳瓨"
+ prop="inboundNum0"
+ width="100"
+ align="center"
+ />
+ <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
+ v-if="searchForm.reportType === 'work'"
+ label="鎿嶄綔浜哄憳"
+ prop="operator"
+ width="80"
+ align="center"
+ />
+ <el-table-column
+ v-if="searchForm.reportType === 'work'"
+ label="鎿嶄綔鏃堕棿"
+ prop="operateTime"
+ width="150"
+ align="center"
+ />
+ </el-table>
+ </el-card>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import { ElMessage } from 'element-plus'
+import * as echarts from 'echarts'
+import {
+ getStockDailyReport,
+ getStockMonthlyReport,
+ getWorkReport,
+ getStockInOutReport,
+ exportStockReport
+} from '@/api/inventoryManagement/stockReport'
+
+
+const { proxy } = getCurrentInstance()
+// 鍝嶅簲寮忔暟鎹�
+const tableLoading = ref(false)
+const trendChart = ref(null)
+const comparisonChart = ref(null)
+
+const searchForm = reactive({
+ reportType: 'daily',
+ singleDate: '',
+ dateRange: [],
+ monthRange: []
+})
+
+const reportData = ref({
+ summary: null,
+ chartData: null,
+ tableData: []
+})
+
+// 鑾峰彇琛ㄦ牸鏍囬
+const getTableTitle = () => {
+ const typeMap = {
+ daily: '鏃ユ姤璇︾粏鏁版嵁',
+ monthly: '鏈堟姤璇︾粏鏁版嵁',
+ work: '浣滀笟鎶ヨ〃璇︾粏鏁版嵁',
+ inout: '杩涘嚭瀛樻姤琛ㄨ缁嗘暟鎹�'
+ }
+ return typeMap[searchForm.reportType] || '鎶ヨ〃璇︾粏鏁版嵁'
+}
+
+// 鎶ヨ〃绫诲瀷鏀瑰彉
+const handleReportTypeChange = () => {
+ reportData.value = {
+ summary: null,
+ chartData: null,
+ tableData: []
+ }
+}
+
+// 鏌ヨ鏁版嵁
+const handleQuery = async () => {
+ if (!validateSearchForm()) {
+ return
+ }
+
+ tableLoading.value = true
+ try {
+ const params = getQueryParams()
+ let response
+
+ switch (searchForm.reportType) {
+ case 'daily':
+ response = await getStockDailyReport(params)
+ break
+ case 'monthly':
+ response = await getStockMonthlyReport(params)
+ break
+ case 'work':
+ response = await getWorkReport(params)
+ break
+ case 'inout':
+ response = await getStockInOutReport(params)
+ break
+ default:
+ throw new Error('鏈煡鐨勬姤琛ㄧ被鍨�')
+ }
+
+ if (response.code === 200) {
+ // generateMockData()
+ reportData.value.tableData = response.data.tableData
+ reportData.value.summary = response.data.summary
+ reportData.value.chartData = response.data.chartData
+ nextTick(() => {
+ initCharts()
+ })
+
+ }
+ } catch (error) {
+ ElMessage.error('鏌ヨ澶辫触锛�' + error.message)
+ } finally {
+ tableLoading.value = false
+ }
+}
+// // 鐢熸垚鍋囨暟鎹�
+// const generateMockData = () => {
+// // 鐢熸垚缁熻鍗$墖鍋囨暟鎹�
+// const summary = {
+// totalIn: 1000,
+// totalOut: 600,
+// currentStock: 400,
+// turnoverRate: 30
+// }
+
+// // 鐢熸垚鍥捐〃鍋囨暟鎹�
+// const trendDates = ['2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19']
+// const trendValues = [300, 350, 400, 380, 420]
+// const comparisonDates = ['2025-09-15', '2025-09-16', '2025-09-17']
+// const inValues = [100, 150, 200]
+// const outValues = [80, 120, 100]
+
+// const chartData = {
+// trendDates,
+// trendValues,
+// comparisonDates,
+// inValues,
+// outValues
+// }
+
+// reportData.value = {
+// summary,
+// chartData,
+// tableData: []
+// }
+// }
+// 楠岃瘉鎼滅储琛ㄥ崟
+const validateSearchForm = () => {
+ if (searchForm.reportType === 'daily') {
+ if (!searchForm.singleDate) {
+ ElMessage.warning('璇烽�夋嫨鏃ユ湡')
+ return false
+ }
+ } else if (searchForm.reportType === 'work' || searchForm.reportType === 'inout') {
+ if (!searchForm.dateRange || searchForm.dateRange.length !== 2) {
+ ElMessage.warning('璇烽�夋嫨鏃ユ湡鑼冨洿')
+ return false
+ }
+ } else if (searchForm.reportType === 'monthly') {
+ if (!searchForm.monthRange || searchForm.monthRange.length !== 2) {
+ ElMessage.warning('璇烽�夋嫨鏈堜唤鑼冨洿')
+ return false
+ }
+ }
+ return true
+}
+
+// 鑾峰彇鏌ヨ鍙傛暟
+const getQueryParams = () => {
+ const params = {
+ reportType: searchForm.reportType,
+ reportDate: "",
+ startMonth: "",
+ endMonth: "",
+ startDate: "",
+ endDate: ""
+ }
+
+ if (searchForm.reportType === 'daily') {
+ params.reportDate = searchForm.singleDate
+ } else if (searchForm.reportType === 'monthly') {
+ params.startMonth = searchForm.monthRange[0]
+ params.endMonth = searchForm.monthRange[1]
+ } else {
+ params.startDate = searchForm.dateRange[0]
+ params.endDate = searchForm.dateRange[1]
+ }
+
+ return params
+}
+
+// 閲嶇疆鎼滅储
+const handleReset = () => {
+ searchForm.reportType = 'daily'
+ searchForm.singleDate = ''
+ searchForm.dateRange = []
+ searchForm.monthRange = []
+ reportData.value = {
+ summary: null,
+ chartData: null,
+ tableData: []
+ }
+}
+
+// 瀵煎嚭鎶ヨ〃
+const handleExport = async () => {
+ if (!validateSearchForm()) {
+ return
+ }
+
+ try {
+ const params = getQueryParams()
+ // const response = await exportStockReport(params)
+ proxy.download("/stockin/exportCopy", params, '搴撳瓨鎶ヨ〃.xlsx')
+ // 鍒涘缓涓嬭浇閾炬帴
+ // const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
+ // const url = window.URL.createObjectURL(blob)
+ // const link = document.createElement('a')
+ // link.href = url
+ // link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx`
+ // document.body.appendChild(link)
+ // link.click()
+ // document.body.removeChild(link)
+ // window.URL.revokeObjectURL(url)
+
+ // ElMessage.success('瀵煎嚭鎴愬姛')
+ } catch (error) {
+ ElMessage.error('瀵煎嚭澶辫触锛�' + error.message)
+ }
+}
+
+// 鍒濆鍖栧浘琛�
+const initCharts = () => {
+ if (!reportData.value.chartData) return
+
+ initTrendChart()
+ initComparisonChart()
+}
+
+// 鍒濆鍖栬秼鍔垮浘
+const initTrendChart = () => {
+ if (!trendChart.value) return
+
+ const chart = echarts.init(trendChart.value)
+ const option = {
+ title: {
+ text: '搴撳瓨鍙樺寲瓒嬪娍',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'axis'
+ },
+ legend: {
+ data: ['搴撳瓨閲�'],
+ top: 30
+ },
+ xAxis: {
+ type: 'category',
+ data: reportData.value.chartData.trendDates || []
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [{
+ name: '搴撳瓨閲�',
+ type: 'line',
+ data: reportData.value.chartData.trendValues || [],
+ smooth: true,
+ itemStyle: {
+ color: '#409EFF'
+ }
+ }]
+ }
+ chart.setOption(option)
+}
+
+// 鍒濆鍖栧姣斿浘
+const initComparisonChart = () => {
+ if (!comparisonChart.value) return
+
+ const chart = echarts.init(comparisonChart.value)
+ const option = {
+ title: {
+ text: '杩涘嚭搴撳姣�',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'axis'
+ },
+ legend: {
+ data: ['鍏ュ簱', '鍑哄簱'],
+ top: 30
+ },
+ xAxis: {
+ type: 'category',
+ data: reportData.value.chartData.comparisonDates || []
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ name: '鍏ュ簱',
+ type: 'bar',
+ data: reportData.value.chartData.inValues || [],
+ itemStyle: {
+ color: '#67C23A'
+ }
+ },
+ {
+ name: '鍑哄簱',
+ type: 'bar',
+ data: reportData.value.chartData.outValues || [],
+ itemStyle: {
+ color: '#F56C6C'
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+}
+
+// 缁勪欢鎸傝浇鏃惰缃粯璁ゆ椂闂�
+onMounted(() => {
+ const today = new Date()
+ searchForm.singleDate = today.toISOString().split('T')[0]
+
+ const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)
+ searchForm.dateRange = [
+ yesterday.toISOString().split('T')[0],
+ today.toISOString().split('T')[0]
+ ]
+})
+</script>
+
+<style scoped>
+.app-container {
+ padding: 20px;
+}
+
+.search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 20px;
+ background: #fff;
+ border-radius: 4px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.search_left {
+ display: flex;
+ align-items: center;
+}
+
+.search_title {
+ font-weight: 500;
+ color: #333;
+ margin-right: 8px;
+}
+
+.ml10 {
+ margin-left: 10px;
+}
+
+.stats_cards {
+ margin-bottom: 20px;
+}
+
+.stats_card {
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.stats_content {
+ display: flex;
+ align-items: center;
+ padding: 10px 0;
+}
+
+.stats_icon {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 15px;
+ font-size: 24px;
+ color: #fff;
+}
+
+.stats_icon.in {
+ background: linear-gradient(135deg, #67C23A, #85CE61);
+}
+
+.stats_icon.out {
+ background: linear-gradient(135deg, #F56C6C, #F78989);
+}
+
+.stats_icon.stock {
+ background: linear-gradient(135deg, #409EFF, #66B1FF);
+}
+
+.stats_icon.turnover {
+ background: linear-gradient(135deg, #E6A23C, #EEBE77);
+}
+
+.stats_info {
+ flex: 1;
+}
+
+.stats_value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #333;
+ line-height: 1;
+ margin-bottom: 5px;
+}
+
+.stats_label {
+ font-size: 14px;
+ color: #666;
+}
+
+.chart_section {
+ margin-bottom: 20px;
+}
+
+.table_section {
+ margin-bottom: 20px;
+}
+
+:deep(.el-card__header) {
+ background: #f8f9fa;
+ border-bottom: 1px solid #e9ecef;
+ font-weight: 500;
+}
+
+:deep(.el-table .el-table__header-wrapper th) {
+ background-color: #F0F1F5 !important;
+ color: #333333;
+ font-weight: 600;
+}
+
+:deep(.el-table .el-table__body-wrapper td) {
+ padding: 8px 0;
+}
+</style>
diff --git a/src/views/inventoryManagement/stockWarning/index.vue b/src/views/inventoryManagement/stockWarning/index.vue
index 4193352..d0d5834 100644
--- a/src/views/inventoryManagement/stockWarning/index.vue
+++ b/src/views/inventoryManagement/stockWarning/index.vue
@@ -41,28 +41,27 @@
<!-- 鎿嶄綔鎸夐挳 -->
<div class="table-operations">
<el-button type="primary" @click="handleAdd">鏂板棰勮瑙勫垯</el-button>
- <el-button type="success" @click="handleBatchProcess">鎵归噺澶勭悊</el-button>
+ <!-- <el-button type="success" @click="handleBatchProcess">鎵归噺澶勭悊@</el-button> -->
<el-button @click="handleExport">瀵煎嚭</el-button>
</div>
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
@selection-change="handleSelectionChange"
style="width: 100%"
height="calc(100vh - 280px)"
- stripe
>
<el-table-column align="center" type="selection" width="55" />
<el-table-column align="center" label="搴忓彿" type="index" width="60" />
-
+
<!-- 鍩虹淇℃伅瀛楁 -->
<el-table-column label="鍌ㄦ皵缃愮紪鐮�" prop="tankCode" width="120" show-overflow-tooltip />
<el-table-column label="鍌ㄦ皵缃愬悕绉�" prop="tankName" width="200" show-overflow-tooltip />
<el-table-column label="鍌ㄦ皵缃愮被鍨�" prop="tankType" width="120" show-overflow-tooltip />
<el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="150" show-overflow-tooltip />
<el-table-column label="瀹圭Н(m鲁)" prop="volume" width="100" show-overflow-tooltip />
-
+
<!-- 搴撳瓨鐩稿叧瀛楁 -->
<el-table-column label="褰撳墠姘斾綋閲�" prop="currentGasLevel" width="120" show-overflow-tooltip>
<template #default="scope">
@@ -73,7 +72,7 @@
<el-table-column label="鏈�浣庢皵浣撻噺" prop="minGasLevel" width="120" show-overflow-tooltip />
<el-table-column label="鏈�楂樻皵浣撻噺" prop="maxGasLevel" width="120" show-overflow-tooltip />
<el-table-column label="褰撳墠鍘嬪姏(MPa)" prop="currentPressure" width="140" show-overflow-tooltip />
-
+
<!-- 棰勮瑙勫垯瀛楁 -->
<el-table-column label="棰勮绫诲瀷" prop="warningType" width="100" show-overflow-tooltip>
<template #default="scope">
@@ -95,7 +94,7 @@
<el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" />
</template>
</el-table-column>
-
+
<!-- 鏃堕棿鐩稿叧瀛楁 -->
<el-table-column label="棰勮鏃堕棿" prop="warningTime" width="150" show-overflow-tooltip />
<el-table-column label="棰勮鎸佺画澶╂暟" prop="warningDuration" width="120" show-overflow-tooltip />
@@ -116,32 +115,32 @@
<span v-else>-</span>
</template>
</el-table-column>
-
+
<!-- 鎿嶄綔鍒� -->
<el-table-column fixed="right" label="鎿嶄綔" width="200" align="center">
<template #default="scope">
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">缂栬緫</el-button>
- <el-button link type="success" size="small" @click="handleProcess(scope.row)">澶勭悊</el-button>
+<!-- <el-button link type="success" size="small" @click="handleProcess(scope.row)">澶勭悊@</el-button>-->
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
-
+
<!-- 鍒嗛〉 -->
- <pagination
- v-show="total > 0"
- :total="total"
+ <pagination
+ v-show="total > 0"
+ :total="total"
layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
/>
</div>
<!-- 鏂板/缂栬緫棰勮瑙勫垯寮圭獥 -->
- <el-dialog
- v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板棰勮瑙勫垯' : '缂栬緫棰勮瑙勫垯'"
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板棰勮瑙勫垯' : '缂栬緫棰勮瑙勫垯'"
width="50%"
@close="closeDialog"
>
@@ -159,7 +158,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鍌ㄦ皵缃愮被鍨嬶細" prop="tankType">
@@ -177,7 +176,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="瀹圭Н(m鲁)锛�" prop="volume">
@@ -190,7 +189,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<!-- 搴撳瓨鐩稿叧 -->
<el-row :gutter="20">
<el-col :span="12">
@@ -204,7 +203,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鏈�楂樻皵浣撻噺(%)锛�" prop="maxGasLevel">
@@ -217,7 +216,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<!-- 棰勮瑙勫垯 -->
<el-row :gutter="20">
<el-col :span="12">
@@ -240,7 +239,7 @@
</el-form-item>
</el-col>
</el-row>
-
+
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="棰勮闃堝�硷細" prop="warningThreshold">
@@ -253,15 +252,15 @@
</el-form-item>
</el-col>
</el-row>
-
+
<!-- 鏃堕棿鐩稿叧 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="棰勮鏃堕棿锛�" prop="warningTime">
- <el-date-picker
- v-model="form.warningTime"
- type="datetime"
- placeholder="璇烽�夋嫨棰勮鏃堕棿"
+ <el-date-picker
+ v-model="form.warningTime"
+ type="datetime"
+ placeholder="璇烽�夋嫨棰勮鏃堕棿"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
@@ -269,24 +268,24 @@
</el-col>
<el-col :span="12">
<el-form-item label="棰勮鍏呰鏃堕棿锛�" prop="expectedRefillTime">
- <el-date-picker
- v-model="form.expectedRefillTime"
- type="datetime"
- placeholder="璇烽�夋嫨棰勮鍏呰鏃堕棿"
+ <el-date-picker
+ v-model="form.expectedRefillTime"
+ type="datetime"
+ placeholder="璇烽�夋嫨棰勮鍏呰鏃堕棿"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
-
+
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="棰勮缂烘皵鏃堕棿锛�" prop="expectedShortageTime">
- <el-date-picker
- v-model="form.expectedShortageTime"
- type="datetime"
- placeholder="璇烽�夋嫨棰勮缂烘皵鏃堕棿"
+ <el-date-picker
+ v-model="form.expectedShortageTime"
+ type="datetime"
+ placeholder="璇烽�夋嫨棰勮缂烘皵鏃堕棿"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
@@ -294,17 +293,17 @@
</el-col>
<el-col :span="12">
<el-form-item label="棰勮瑙勫垯鎻忚堪锛�" prop="warningRule">
- <el-input
- v-model="form.warningRule"
- type="textarea"
- :rows="3"
+ <el-input
+ v-model="form.warningRule"
+ type="textarea"
+ :rows="3"
placeholder="璇疯緭鍏ラ璀﹁鍒欐弿杩�"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
-
+
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">鍙栨秷</el-button>
@@ -383,15 +382,15 @@
import { WarningFilled } from '@element-plus/icons-vue'
import pagination from '@/components/PIMTable/Pagination.vue'
// 娉ㄩ噴鎺堿PI瀵煎叆锛屼娇鐢ㄥ亣鏁版嵁
-// import {
-// getStockWarningPage,
-// addStockWarning,
-// updateStockWarning,
-// deleteStockWarning,
-// batchProcessStockWarning,
-// exportStockWarning,
-// toggleStockWarningStatus
-// } from '@/api/inventoryManagement/stockWarning.js'
+import {
+ getStockWarningPage,
+ addStockWarning,
+ updateStockWarning,
+ deleteStockWarning,
+ batchProcessStockWarning,
+ exportStockWarning,
+ toggleStockWarningStatus
+} from '@/api/inventoryManagement/stockWarning.js'
const { proxy } = getCurrentInstance()
@@ -411,7 +410,8 @@
// 鍒嗛〉鍙傛暟
const page = reactive({
current: 1,
- size: 10
+ size: 10,
+ total: 0
})
// 鎼滅储琛ㄥ崟
@@ -460,19 +460,19 @@
// 鑾峰彇鍊掕鏃朵俊鎭�
const getCountdown = (expectedTime) => {
if (!expectedTime) return { text: '-', isExpired: false }
-
+
const now = new Date().getTime()
const expected = new Date(expectedTime).getTime()
const diff = expected - now
-
+
if (diff <= 0) {
return { text: '宸茬己姘�', isExpired: true }
}
-
+
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
-
+
if (days > 0) {
return { text: `${days}澶�${hours}灏忔椂`, isExpired: false }
} else if (hours > 0) {
@@ -485,11 +485,11 @@
// 鑾峰彇鍊掕鏃舵牱寮忕被
const getCountdownClass = (expectedTime) => {
if (!expectedTime) return ''
-
+
const now = new Date().getTime()
const expected = new Date(expectedTime).getTime()
const diff = expected - now
-
+
if (diff <= 0) {
return 'countdown-expired'
} else if (diff <= 24 * 60 * 60 * 1000) { // 24灏忔椂鍐�
@@ -519,7 +519,7 @@
const showShortageWarning = (tank) => {
currentWarningTank.value = tank
shortageWarningVisible.value = true
-
+
// 鎾斁鎻愮ず闊筹紙鍙�夛級
// const audio = new Audio('/path/to/warning-sound.mp3')
// audio.play()
@@ -538,236 +538,20 @@
// 杩欓噷鍙互璋冪敤澶勭悊API
}
-
-
-// 鐢熸垚鍋囨暟鎹�
-const generateMockData = () => {
- const mockData = [
- {
- id: 1,
- tankCode: 'TANK001',
- tankName: '娑插寲姘斿偍缃怉',
- tankType: '娑插寲姘斿偍缃�',
- specificationModel: 'LPG-5000L',
- volume: 5000,
- currentGasLevel: 15,
- safetyGasLevel: 30,
- minGasLevel: 10,
- maxGasLevel: 95,
- currentPressure: 2.5,
- warningType: '姘斾綋涓嶈冻',
- warningLevel: '绱ф��',
- warningThreshold: 20,
- isEnabled: true,
- warningTime: '2024-01-15 08:30:00',
- warningDuration: 3,
- lastUpdateTime: '2024-01-15 10:00:00',
- expectedRefillTime: '2024-01-16 14:00:00',
- expectedShortageTime: '2024-01-15 18:30:00', // 浠婂ぉ涓嬪崍6:30缂烘皵
- warningRule: '褰撴皵浣撻噺浣庝簬20%鏃惰Е鍙戦璀�'
- },
- {
- id: 2,
- tankCode: 'TANK002',
- tankName: '鍘嬬缉姘斿偍缃怋',
- tankType: '鍘嬬缉姘斿偍缃�',
- specificationModel: 'COMP-3000L',
- volume: 3000,
- currentGasLevel: 45,
- safetyGasLevel: 25,
- minGasLevel: 15,
- maxGasLevel: 90,
- currentPressure: 8.2,
- warningType: '鍘嬪姏寮傚父',
- warningLevel: '閲嶈',
- warningThreshold: 10,
- isEnabled: true,
- warningTime: '2024-01-14 16:20:00',
- warningDuration: 2,
- lastUpdateTime: '2024-01-15 09:15:00',
- expectedRefillTime: '2024-01-17 09:00:00',
- expectedShortageTime: '2024-01-18 12:00:00', // 3澶╁悗缂烘皵
- warningRule: '褰撳帇鍔涜秴杩�8MPa鏃惰Е鍙戦璀�'
- },
- {
- id: 3,
- tankCode: 'TANK003',
- tankName: '澶╃劧姘斿偍缃怌',
- tankType: '澶╃劧姘斿偍缃�',
- specificationModel: 'NG-8000L',
- volume: 8000,
- currentGasLevel: 75,
- safetyGasLevel: 20,
- minGasLevel: 10,
- maxGasLevel: 95,
- currentPressure: 4.8,
- warningType: '娓╁害寮傚父',
- warningLevel: '涓�鑸�',
- warningThreshold: 5,
- isEnabled: true,
- warningTime: '2024-01-13 11:45:00',
- warningDuration: 1,
- lastUpdateTime: '2024-01-15 08:45:00',
- expectedRefillTime: '2024-01-20 10:00:00',
- expectedShortageTime: '2024-01-22 15:30:00', // 7澶╁悗缂烘皵
- warningRule: '褰撴俯搴﹁秴杩�60掳C鏃惰Е鍙戦璀�'
- },
- {
- id: 4,
- tankCode: 'TANK004',
- tankName: '姘ф皵鍌ㄧ綈D',
- tankType: '姘ф皵鍌ㄧ綈',
- specificationModel: 'O2-2000L',
- volume: 2000,
- currentGasLevel: 8,
- safetyGasLevel: 25,
- minGasLevel: 5,
- maxGasLevel: 90,
- currentPressure: 6.5,
- warningType: '娉勬紡棰勮',
- warningLevel: '绱ф��',
- warningThreshold: 15,
- isEnabled: true,
- warningTime: '2024-01-15 07:15:00',
- warningDuration: 4,
- lastUpdateTime: '2024-01-15 11:30:00',
- expectedRefillTime: '2024-01-15 16:00:00',
- expectedShortageTime: '2024-01-15 14:00:00', // 浠婂ぉ涓嬪崍2鐐圭己姘�
- warningRule: '褰撴娴嬪埌姘斾綋娉勬紡鏃惰Е鍙戦璀�'
- },
- {
- id: 5,
- tankCode: 'TANK005',
- tankName: '娑插寲姘斿偍缃怑',
- tankType: '娑插寲姘斿偍缃�',
- specificationModel: 'LPG-6000L',
- volume: 6000,
- currentGasLevel: 35,
- safetyGasLevel: 30,
- minGasLevel: 15,
- maxGasLevel: 95,
- currentPressure: 3.2,
- warningType: '姘斾綋涓嶈冻',
- warningLevel: '閲嶈',
- warningThreshold: 20,
- isEnabled: false,
- warningTime: '2024-01-14 14:30:00',
- warningDuration: 2,
- lastUpdateTime: '2024-01-15 09:00:00',
- expectedRefillTime: '2024-01-19 08:00:00',
- expectedShortageTime: '2024-01-21 10:00:00', // 6澶╁悗缂烘皵
- warningRule: '褰撴皵浣撻噺浣庝簬20%鏃惰Е鍙戦璀�'
- },
- {
- id: 6,
- tankCode: 'TANK006',
- tankName: '鍘嬬缉姘斿偍缃怓',
- tankType: '鍘嬬缉姘斿偍缃�',
- specificationModel: 'COMP-4000L',
- volume: 4000,
- currentGasLevel: 85,
- safetyGasLevel: 20,
- minGasLevel: 10,
- maxGasLevel: 90,
- currentPressure: 7.8,
- warningType: '鍘嬪姏寮傚父',
- warningLevel: '涓�鑸�',
- warningThreshold: 8,
- isEnabled: true,
- warningTime: '2024-01-12 09:20:00',
- warningDuration: 1,
- lastUpdateTime: '2024-01-15 08:30:00',
- expectedRefillTime: '2024-01-25 14:00:00',
- expectedShortageTime: '2024-01-28 16:00:00', // 13澶╁悗缂烘皵
- warningRule: '褰撳帇鍔涜秴杩�8MPa鏃惰Е鍙戦璀�'
- },
- {
- id: 7,
- tankCode: 'TANK007',
- tankName: '澶╃劧姘斿偍缃怗',
- tankType: '澶╃劧姘斿偍缃�',
- specificationModel: 'NG-10000L',
- volume: 10000,
- currentGasLevel: 92,
- safetyGasLevel: 15,
- minGasLevel: 8,
- maxGasLevel: 95,
- currentPressure: 5.2,
- warningType: '娓╁害寮傚父',
- warningLevel: '閲嶈',
- warningThreshold: 6,
- isEnabled: true,
- warningTime: '2024-01-11 16:45:00',
- warningDuration: 1,
- lastUpdateTime: '2024-01-15 07:45:00',
- expectedRefillTime: '2024-01-30 09:00:00',
- expectedShortageTime: '2024-02-05 12:00:00', // 21澶╁悗缂烘皵
- warningRule: '褰撴俯搴﹁秴杩�60掳C鏃惰Е鍙戦璀�'
- },
- {
- id: 8,
- tankCode: 'TANK008',
- tankName: '姘ф皵鍌ㄧ綈H',
- tankType: '姘ф皵鍌ㄧ綈',
- specificationModel: 'O2-1500L',
- volume: 1500,
- currentGasLevel: 12,
- safetyGasLevel: 30,
- minGasLevel: 8,
- maxGasLevel: 90,
- currentPressure: 4.5,
- warningType: '娉勬紡棰勮',
- warningLevel: '绱ф��',
- warningThreshold: 12,
- isEnabled: true,
- warningTime: '2024-01-15 06:30:00',
- warningDuration: 5,
- lastUpdateTime: '2024-01-15 12:15:00',
- expectedRefillTime: '2024-01-15 20:00:00',
- expectedShortageTime: '2024-01-15 17:30:00', // 浠婂ぉ涓嬪崍5:30缂烘皵
- warningRule: '褰撴娴嬪埌姘斾綋娉勬紡鏃惰Е鍙戦璀�'
- }
- ]
-
- // 鏍规嵁鎼滅储鏉′欢杩囨护鏁版嵁
- let filteredData = mockData.filter(item => {
- if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false
- if (searchForm.tankType && item.tankType !== searchForm.tankType) return false
- if (searchForm.warningType && item.warningType !== searchForm.warningType) return false
- if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false
- return true
- })
-
- // 鍒嗛〉澶勭悊
- const start = (page.current - 1) * page.size
- const end = start + page.size
- const paginatedData = filteredData.slice(start, end)
-
- return {
- records: paginatedData,
- total: filteredData.length
- }
-}
-
// 鑾峰彇鍒楄〃鏁版嵁
const getList = async () => {
tableLoading.value = true
- try {
- // 妯℃嫙缃戠粶寤惰繜
- await new Promise(resolve => setTimeout(resolve, 500))
-
- const result = generateMockData()
- tableData.value = result.records
- total.value = result.total
-
- // 妫�鏌ョ己姘旈璀�
+ getStockWarningPage(page, searchForm)
+ .then(res => {
+
+ tableData.value = res.data.records
+ page.value.total = res.data.total;
+ tableLoading.value = false;
+ // 妫�鏌ョ己姘旈璀�
checkShortageWarnings()
- } catch (error) {
- console.error('鑾峰彇鍒楄〃澶辫触:', error)
- ElMessage.error('鑾峰彇鍒楄〃澶辫触')
- } finally {
- tableLoading.value = false
- }
+ }).catch(err => {
+ tableLoading.value = false;
+ })
}
// 鎼滅储
@@ -799,7 +583,7 @@
// 鏂板
const handleAdd = () => {
operationType.value = 'add'
- resetForm()
+ // resetForm()
dialogFormVisible.value = true
}
@@ -816,7 +600,7 @@
// 妯℃嫙API璋冪敤寤惰繜
await new Promise(resolve => setTimeout(resolve, 300))
ElMessage.success(`姝e湪澶勭悊棰勮锛�${row.tankName}`)
- getList()
+ // getList()
} catch (error) {
ElMessage.error('澶勭悊棰勮澶辫触')
}
@@ -830,11 +614,21 @@
cancelButtonText: '鍙栨秷',
type: 'warning'
})
-
- // 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 300))
- ElMessage.success('鍒犻櫎鎴愬姛')
- getList()
+ let ids = [];
+ ids.push(row.id);
+ deleteStockWarning(ids).then(res => {
+ if(res.code == 200){
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ ids.value = [];
+ getList();
+ }
+ }).catch(err => {
+ ElMessage.error(err.msg);
+ })
+ // // 妯℃嫙API璋冪敤寤惰繜
+ // await new Promise(resolve => setTimeout(resolve, 300))
+ // ElMessage.success('鍒犻櫎鎴愬姛')
+ // getList()
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('鍒犻櫎澶辫触')
@@ -848,7 +642,7 @@
ElMessage.warning('璇烽�夋嫨瑕佸鐞嗙殑棰勮')
return
}
-
+
try {
// 妯℃嫙API璋冪敤寤惰繜
await new Promise(resolve => setTimeout(resolve, 500))
@@ -861,75 +655,65 @@
// 瀵煎嚭
const handleExport = async () => {
- try {
- // 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 800))
-
- // 鐢熸垚瀵煎嚭鏁版嵁
- const exportData = generateMockData().records
- const csvContent = generateCSV(exportData)
-
- // 鍒涘缓涓嬭浇閾炬帴
- const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
- const url = window.URL.createObjectURL(blob)
- const link = document.createElement('a')
- link.href = url
- link.download = `鍌ㄦ皵缃愰璀︽暟鎹甠${new Date().getTime()}.csv`
- link.click()
- window.URL.revokeObjectURL(url)
-
- ElMessage.success('瀵煎嚭鎴愬姛')
- } catch (error) {
- ElMessage.error('瀵煎嚭澶辫触')
- }
+ // if (selectedRows.value.length === 0) {
+ // exportStockWarning().then(res => {
+ // // // 鍒涘缓涓嬭浇閾炬帴
+ // // const blob = new Blob([res.data], { type: 'text/csv;charset=utf-8;' })
+ // // const url = window.URL.createObjectURL(blob)
+ // // const link = document.createElement('a')
+ // // link.href = url
+ // // link.download = `鍌ㄦ皵缃愰璀︽暟鎹甠${new Date().getTime()}.csv`
+ // // link.click()
+ // // window.URL.revokeObjectURL(url)
+ // }).catch(err => {
+ // ElMessage.error(err.msg);
+ // })
+ // }else{
+ // let ids = [];
+ // selectedRows.value.forEach(item => {
+ // ids.push(item.id);
+ // })
+ // exportStockWarning(ids).then(res => {
+ // // // 鍒涘缓涓嬭浇閾炬帴
+ // // const blob = new Blob([res.data], { type: 'text/csv;charset=utf-8;' })
+ // // const url = window.URL.createObjectURL(blob)
+ // // const link = document.createElement('a')
+ // // link.href = url
+ // // link.download = `鍌ㄦ皵缃愰璀︽暟鎹甠${new Date().getTime()}.csv`
+ // // link.click()
+ // // window.URL.revokeObjectURL(url)
+ // }).catch(err => {
+ // ElMessage.error(err.msg);
+ // })
+ // }
+
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/gasTankWarning/export", {ids: selectedRows.value.map(item => item.id)}, "鍌ㄦ皵缃愰璀�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
}
-// 鐢熸垚CSV鍐呭
-const generateCSV = (data) => {
- const headers = [
- '鍌ㄦ皵缃愮紪鐮�', '鍌ㄦ皵缃愬悕绉�', '鍌ㄦ皵缃愮被鍨�', '瑙勬牸鍨嬪彿', '瀹圭Н(m鲁)',
- '褰撳墠姘斾綋閲�(%)', '瀹夊叏姘斾綋閲�(%)', '鏈�浣庢皵浣撻噺(%)', '鏈�楂樻皵浣撻噺(%)',
- '褰撳墠鍘嬪姏(MPa)', '棰勮绫诲瀷', '棰勮绾у埆', '棰勮闃堝��', '鏄惁鍚敤',
- '棰勮鏃堕棿', '棰勮鎸佺画澶╂暟', '鏈�鍚庢洿鏂版椂闂�', '棰勮鍏呰鏃堕棿', '棰勮缂烘皵鏃堕棿', '棰勮瑙勫垯鎻忚堪'
- ]
-
- const csvRows = [headers.join(',')]
-
- data.forEach(item => {
- const row = [
- item.tankCode,
- item.tankName,
- item.tankType,
- item.specificationModel,
- item.volume,
- item.currentGasLevel,
- item.safetyGasLevel,
- item.minGasLevel,
- item.maxGasLevel,
- item.currentPressure,
- item.warningType,
- item.warningLevel,
- item.warningThreshold,
- item.isEnabled ? '鏄�' : '鍚�',
- item.warningTime,
- item.warningDuration,
- item.lastUpdateTime,
- item.expectedRefillTime,
- item.expectedShortageTime,
- item.warningRule
- ]
- csvRows.push(row.join(','))
- })
-
- return csvRows.join('\n')
-}
-// 鍚敤鐘舵�佸彉鍖�
+
+// // 鍚敤鐘舵�佸彉鍖�
const handleEnableChange = async (row) => {
+
try {
- // 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 200))
- ElMessage.success(`${row.tankName} 鐨勫惎鐢ㄧ姸鎬佸凡鏇存柊`)
+ updateStockWarning(row).then(res => {
+ if(res.code == 200){
+ ElMessage.success(`${row.tankName} 鐨勫惎鐢ㄧ姸鎬佸凡鏇存柊`);
+ getList();
+ }
+ }).catch(err => {
+ ElMessage.error(err.msg);
+ })
} catch (error) {
ElMessage.error('鐘舵�佹洿鏂板け璐�')
// 鎭㈠鍘熺姸鎬�
@@ -941,18 +725,39 @@
const submitForm = async () => {
try {
await proxy.$refs.formRef.validate()
-
+
// 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 500))
-
+ // await new Promise(resolve => setTimeout(resolve, 500))
+
if (operationType.value === 'add') {
- ElMessage.success('鏂板鎴愬姛')
+ addStockWarning(form).then(res => {
+ if(res.code == 200){
+ ElMessage.success("娣诲姞鎴愬姛");
+ dialogFormVisible.value = false
+ getList()
+ resetForm()
+ }
+ }).catch(err => {
+ ElMessage.error(err.msg);
+ })
+
+ // ElMessage.success('鏂板鎴愬姛')
} else {
- ElMessage.success('缂栬緫鎴愬姛')
+ updateStockWarning(form).then(res => {
+ if(res.code == 200){
+ ElMessage.success("鏇存柊鎴愬姛");
+ dialogFormVisible.value = false
+ getList()
+ resetForm()
+ }
+ }).catch(err => {
+ ElMessage.error(err.msg);
+ })
+ // ElMessage.success('缂栬緫鎴愬姛')
}
-
- closeDialog()
- getList()
+
+ // closeDialog()
+ // getList()
} catch (error) {
if (!error.errors) {
ElMessage.error(operationType.value === 'add' ? '鏂板澶辫触' : '缂栬緫澶辫触')
@@ -963,7 +768,7 @@
// 鍏抽棴寮圭獥
const closeDialog = () => {
dialogFormVisible.value = false
- resetForm()
+ // resetForm()
}
// 閲嶇疆琛ㄥ崟
@@ -1041,89 +846,89 @@
<style scoped lang="scss">
.app-container {
padding: 20px;
-
+
.table-operations {
text-align: right;
margin-bottom: 20px;
-
+
.el-button {
margin-right: 10px;
}
}
-
+
.table_list {
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
-
+
.text-danger {
color: #f56c6c;
font-weight: bold;
}
-
+
.text-warning {
color: #e6a23c;
font-weight: bold;
}
-
+
.text-success {
color: #67c23a;
font-weight: bold;
}
-
+
.dialog-footer {
text-align: right;
}
-
+
// 鍊掕鏃舵牱寮�
.countdown-timer {
font-weight: bold;
}
-
+
.countdown-normal {
color: #67c23a;
}
-
+
.countdown-warning {
color: #e6a23c;
}
-
+
.countdown-urgent {
color: #f56c6c;
animation: blink 1s infinite;
}
-
+
.countdown-expired {
color: #f56c6c;
font-weight: bold;
}
-
+
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0.5; }
}
-
+
// 缂烘皵棰勮寮规鏍峰紡
.shortage-warning-content {
text-align: center;
padding: 20px 0;
-
+
.warning-icon {
margin-bottom: 20px;
}
-
+
.warning-message {
h3 {
color: #f56c6c;
margin-bottom: 10px;
}
-
+
p {
margin-bottom: 10px;
color: #606266;
}
-
+
.warning-details {
background: #f5f7fa;
padding: 15px;
diff --git a/src/views/salesManagement/receiptPaymentHistory/index.vue b/src/views/salesManagement/receiptPaymentHistory/index.vue
index ea373ea..d7ef8b2 100644
--- a/src/views/salesManagement/receiptPaymentHistory/index.vue
+++ b/src/views/salesManagement/receiptPaymentHistory/index.vue
@@ -109,19 +109,6 @@
{
label: "鍥炴鏂瑰紡",
prop: "receiptPaymentType",
- dataType: "tag",
- formatData: (params) => {
- if (params == 0) {
- return "鐢垫眹";
- } else if (params == 1) {
- return "鎵垮厬";
- } else {
- return null;
- }
- },
- formatType: (params) => {
- return "info";
- },
},
{
label: "鐧昏浜�",
--
Gitblit v1.9.3