From d3840d5971aa6e1272f17acce28a5f96a8e3ab29 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 13 五月 2026 15:06:23 +0800
Subject: [PATCH] 浪潮 1.添加仓库管理页面 2.入库、出库添加新增编辑功能并联调
---
src/views/inventoryManagement/dispatchLog/Record.vue | 362 +++++++++++++
src/views/procurementManagement/procurementLedger/index.vue | 29 -
src/views/basicData/customerFile/index.vue | 67 +
src/api/inventoryManagement/stockOut.js | 9
src/views/inventoryManagement/warehouseManagement/index.vue | 491 ++++++++++++++++++
src/api/inventoryManagement/warehouse.js | 63 ++
src/views/basicData/customerFileOpenSea/index.vue | 67 +
src/views/salesManagement/salesLedger/index.vue | 25
src/views/inventoryManagement/stockManagement/Record.vue | 17
src/api/inventoryManagement/stockInventory.js | 9
src/views/inventoryManagement/receiptManagement/Record.vue | 451 ++++++++++++++--
11 files changed, 1,419 insertions(+), 171 deletions(-)
diff --git a/src/api/inventoryManagement/stockInventory.js b/src/api/inventoryManagement/stockInventory.js
index 0ba0943..10ac88b 100644
--- a/src/api/inventoryManagement/stockInventory.js
+++ b/src/api/inventoryManagement/stockInventory.js
@@ -95,3 +95,12 @@
});
};
+// 鏇存柊搴撳瓨璁板綍
+export const updateStockInventory = (params) => {
+ return request({
+ url: "/stockInventory/update",
+ method: "post",
+ data: params,
+ });
+};
+
diff --git a/src/api/inventoryManagement/stockOut.js b/src/api/inventoryManagement/stockOut.js
index 004ba99..3a6606d 100644
--- a/src/api/inventoryManagement/stockOut.js
+++ b/src/api/inventoryManagement/stockOut.js
@@ -35,3 +35,12 @@
data,
});
}
+
+// 鏇存柊鍑哄簱璁板綍
+export const updateStockOutRecord = (id, data) => {
+ return request({
+ url: `/stockOutRecord/${id}`,
+ method: "put",
+ data,
+ });
+}
diff --git a/src/api/inventoryManagement/warehouse.js b/src/api/inventoryManagement/warehouse.js
new file mode 100644
index 0000000..2b183a0
--- /dev/null
+++ b/src/api/inventoryManagement/warehouse.js
@@ -0,0 +1,63 @@
+import request from "@/utils/request";
+
+// 鑾峰彇浠撳簱鍒楄〃锛堝垎椤碉級
+export const getWarehousePage = (params) => {
+ return request({
+ url: "/warehouseInfo/listPage",
+ method: "get",
+ params,
+ });
+};
+
+// 鑾峰彇浠撳簱鍒楄〃锛堜笉鍒嗛〉锛�
+export const getWarehouseList = (params) => {
+ return request({
+ url: "/warehouseInfo/list",
+ method: "get",
+ params,
+ });
+};
+
+// 鏍规嵁ID鑾峰彇浠撳簱璇︽儏
+export const getWarehouseById = (id) => {
+ return request({
+ url: `/warehouseInfo/${id}`,
+ method: "get",
+ });
+};
+
+// 鏂板浠撳簱
+export const addWarehouse = (data) => {
+ return request({
+ url: "/warehouseInfo/add",
+ method: "post",
+ data,
+ });
+};
+
+// 鏇存柊浠撳簱
+export const updateWarehouse = (data) => {
+ return request({
+ url: "/warehouseInfo/edit",
+ method: "post",
+ data,
+ });
+};
+
+// 鍒犻櫎浠撳簱
+export const delWarehouse = (ids) => {
+ return request({
+ url: "/warehouseInfo/delete",
+ method: "post",
+ data: ids,
+ });
+};
+
+// 鏇存柊浠撳簱鐘舵��
+export const updateWarehouseStatus = (id, status) => {
+ return request({
+ url: `/warehouseInfo/${id}/status`,
+ method: "put",
+ params: { status },
+ });
+};
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index 7be166d..932464c 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -136,21 +136,23 @@
</el-form-item>
</el-col>
</el-row>
- <!-- 鑱旂郴浜哄姛鑳藉凡杩佺Щ鍒拌仈绯讳汉绠$悊椤甸潰
+ <!-- 鑱旂郴浜哄垪琛� -->
<el-row :gutter="30"
- v-for="(contact, index) in formYYs.contactList"
+ v-for="(contact, index) in form.contactList"
:key="index">
<el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細"
- prop="contactPerson">
+ <el-form-item :label="index === 0 ? '鑱旂郴浜猴細' : ''"
+ :prop="'contactList.' + index + '.contactPerson'"
+ :rules="{ required: true, message: '璇疯緭鍏ヨ仈绯讳汉', trigger: 'blur' }">
<el-input v-model="contact.contactPerson"
placeholder="璇疯緭鍏�"
clearable />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�"
- prop="contactPhone">
+ <el-form-item :label="index === 0 ? '鑱旂郴鐢佃瘽锛�' : ''"
+ :prop="'contactList.' + index + '.contactPhone'"
+ :rules="{ required: true, message: '璇疯緭鍏ヨ仈绯荤數璇�', trigger: 'blur' }">
<div style="display: flex; align-items: center;width: 100%;">
<el-input v-model="contact.contactPhone"
placeholder="璇疯緭鍏�"
@@ -158,7 +160,8 @@
<el-button @click="removeContact(index)"
type="danger"
circle
- style="margin-left: 5px;">
+ style="margin-left: 5px;"
+ :disabled="form.contactList.length <= 1">
<el-icon>
<Close />
</el-icon>
@@ -168,8 +171,9 @@
</el-col>
</el-row>
<el-button @click="addNewContact"
- style="margin-bottom: 10px;">+ 鏂板鑱旂郴浜�</el-button>
- -->
+ style="margin-bottom: 10px;"
+ type="primary"
+ plain>+ 鏂板鑱旂郴浜�</el-button>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="缁存姢浜猴細"
@@ -868,6 +872,12 @@
companyPhone: "",
contactPerson: "",
contactPhone: "",
+ contactList: [
+ {
+ contactPerson: "",
+ contactPhone: "",
+ },
+ ],
maintainer: "",
maintenanceTime: "",
basicBankAccount: "",
@@ -955,15 +965,15 @@
});
const { searchForm, form, rules } = toRefs(data);
const addNewContact = () => {
- formYYs.value.contactList.push({
+ form.value.contactList.push({
contactPerson: "",
contactPhone: "",
});
};
const removeContact = index => {
- if (formYYs.value.contactList.length > 1) {
- formYYs.value.contactList.splice(index, 1);
+ if (form.value.contactList.length > 1) {
+ form.value.contactList.splice(index, 1);
}
};
// 鏌ヨ鍒楄〃
@@ -1008,7 +1018,7 @@
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
- formYYs.value.contactList = [
+ form.value.contactList = [
{
contactPerson: "",
contactPhone: "",
@@ -1022,14 +1032,19 @@
if (type === "edit") {
getCustomer(row.id).then(res => {
form.value = { ...res.data };
- formYYs.value.contactList = res.data.contactPerson
- .split(",")
- .map((item, index) => {
- return {
- contactPerson: item,
- contactPhone: res.data.contactPhone.split(",")[index],
- };
- });
+ // 浼樺厛浣跨敤鍚庣杩斿洖鐨刢ontactList鏁扮粍锛屽鏋滄病鏈夊垯浣跨敤閫楀彿鍒嗛殧鐨勫瓧绗︿覆杞崲
+ if (res.data.contactList && res.data.contactList.length > 0) {
+ form.value.contactList = res.data.contactList;
+ } else if (res.data.contactPerson) {
+ form.value.contactList = res.data.contactPerson
+ .split(",")
+ .map((item, index) => {
+ return {
+ contactPerson: item,
+ contactPhone: res.data.contactPhone ? res.data.contactPhone.split(",")[index] : "",
+ };
+ });
+ }
});
}
dialogFormVisible.value = true;
@@ -1048,13 +1063,13 @@
};
// 鎻愪氦鏂板
const submitAdd = () => {
- if (formYYs.value.contactList.length < 1) {
+ if (form.value.contactList.length < 1) {
return proxy.$modal.msgWarning("璇疯嚦灏戞坊鍔犱竴涓仈绯讳汉");
}
- form.value.contactPerson = formYYs.value.contactList
+ form.value.contactPerson = form.value.contactList
.map(item => item.contactPerson)
.join(",");
- form.value.contactPhone = formYYs.value.contactList
+ form.value.contactPhone = form.value.contactList
.map(item => item.contactPhone)
.join(",");
addCustomer(form.value).then(res => {
@@ -1065,10 +1080,10 @@
};
// 鎻愪氦淇敼
const submitEdit = () => {
- form.value.contactPerson = formYYs.value.contactList
+ form.value.contactPerson = form.value.contactList
.map(item => item.contactPerson)
.join(",");
- form.value.contactPhone = formYYs.value.contactList
+ form.value.contactPhone = form.value.contactList
.map(item => item.contactPhone)
.join(",");
updateCustomer(form.value).then(res => {
diff --git a/src/views/basicData/customerFileOpenSea/index.vue b/src/views/basicData/customerFileOpenSea/index.vue
index 8801b73..8c3abbc 100644
--- a/src/views/basicData/customerFileOpenSea/index.vue
+++ b/src/views/basicData/customerFileOpenSea/index.vue
@@ -133,21 +133,23 @@
</el-form-item>
</el-col>
</el-row>
- <!-- 鑱旂郴浜哄姛鑳藉凡杩佺Щ鍒拌仈绯讳汉绠$悊椤甸潰
+ <!-- 鑱旂郴浜哄垪琛� -->
<el-row :gutter="30"
- v-for="(contact, index) in formYYs.contactList"
+ v-for="(contact, index) in form.contactList"
:key="index">
<el-col :span="12">
- <el-form-item label="鑱旂郴浜猴細"
- prop="contactPerson">
+ <el-form-item :label="index === 0 ? '鑱旂郴浜猴細' : ''"
+ :prop="'contactList.' + index + '.contactPerson'"
+ :rules="{ required: true, message: '璇疯緭鍏ヨ仈绯讳汉', trigger: 'blur' }">
<el-input v-model="contact.contactPerson"
placeholder="璇疯緭鍏�"
clearable />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�"
- prop="contactPhone">
+ <el-form-item :label="index === 0 ? '鑱旂郴鐢佃瘽锛�' : ''"
+ :prop="'contactList.' + index + '.contactPhone'"
+ :rules="{ required: true, message: '璇疯緭鍏ヨ仈绯荤數璇�', trigger: 'blur' }">
<div style="display: flex; align-items: center;width: 100%;">
<el-input v-model="contact.contactPhone"
placeholder="璇疯緭鍏�"
@@ -155,7 +157,8 @@
<el-button @click="removeContact(index)"
type="danger"
circle
- style="margin-left: 5px;">
+ style="margin-left: 5px;"
+ :disabled="form.contactList.length <= 1">
<el-icon>
<Close />
</el-icon>
@@ -165,8 +168,9 @@
</el-col>
</el-row>
<el-button @click="addNewContact"
- style="margin-bottom: 10px;">+ 鏂板鑱旂郴浜�</el-button>
- -->
+ style="margin-bottom: 10px;"
+ type="primary"
+ plain>+ 鏂板鑱旂郴浜�</el-button>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="缁存姢浜猴細"
@@ -987,6 +991,12 @@
companyPhone: "",
contactPerson: "",
contactPhone: "",
+ contactList: [
+ {
+ contactPerson: "",
+ contactPhone: "",
+ },
+ ],
maintainer: "",
maintenanceTime: "",
basicBankAccount: "",
@@ -1074,15 +1084,15 @@
});
const { searchForm, form, rules } = toRefs(data);
const addNewContact = () => {
- formYYs.value.contactList.push({
+ form.value.contactList.push({
contactPerson: "",
contactPhone: "",
});
};
const removeContact = index => {
- if (formYYs.value.contactList.length > 1) {
- formYYs.value.contactList.splice(index, 1);
+ if (form.value.contactList.length > 1) {
+ form.value.contactList.splice(index, 1);
}
};
// 鏌ヨ鍒楄〃
@@ -1128,7 +1138,7 @@
operationType.value = type;
form.value = {};
form.value.maintainer = userStore.nickName;
- formYYs.value.contactList = [
+ form.value.contactList = [
{
contactPerson: "",
contactPhone: "",
@@ -1142,14 +1152,19 @@
if (type === "edit") {
getCustomer(row.id).then(res => {
form.value = { ...res.data };
- formYYs.value.contactList = res.data.contactPerson
- .split(",")
- .map((item, index) => {
- return {
- contactPerson: item,
- contactPhone: res.data.contactPhone.split(",")[index],
- };
- });
+ // 浼樺厛浣跨敤鍚庣杩斿洖鐨刢ontactList鏁扮粍锛屽鏋滄病鏈夊垯浣跨敤閫楀彿鍒嗛殧鐨勫瓧绗︿覆杞崲
+ if (res.data.contactList && res.data.contactList.length > 0) {
+ form.value.contactList = res.data.contactList;
+ } else if (res.data.contactPerson) {
+ form.value.contactList = res.data.contactPerson
+ .split(",")
+ .map((item, index) => {
+ return {
+ contactPerson: item,
+ contactPhone: res.data.contactPhone ? res.data.contactPhone.split(",")[index] : "",
+ };
+ });
+ }
});
}
dialogFormVisible.value = true;
@@ -1168,13 +1183,13 @@
};
// 鎻愪氦鏂板
const submitAdd = () => {
- if (formYYs.value.contactList.length < 1) {
+ if (form.value.contactList.length < 1) {
return proxy.$modal.msgWarning("璇疯嚦灏戞坊鍔犱竴涓仈绯讳汉");
}
- form.value.contactPerson = formYYs.value.contactList
+ form.value.contactPerson = form.value.contactList
.map(item => item.contactPerson)
.join(",");
- form.value.contactPhone = formYYs.value.contactList
+ form.value.contactPhone = form.value.contactList
.map(item => item.contactPhone)
.join(",");
addCustomer(form.value).then(res => {
@@ -1185,10 +1200,10 @@
};
// 鎻愪氦淇敼
const submitEdit = () => {
- form.value.contactPerson = formYYs.value.contactList
+ form.value.contactPerson = form.value.contactList
.map(item => item.contactPerson)
.join(",");
- form.value.contactPhone = formYYs.value.contactList
+ form.value.contactPhone = form.value.contactList
.map(item => item.contactPhone)
.join(",");
updateCustomer(form.value).then(res => {
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index dd47cb4..724f561 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -31,6 +31,7 @@
>
</div>
<div>
+ <el-button type="primary" @click="handleAdd">鏂板</el-button>
<el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
@@ -94,6 +95,17 @@
</el-tag>
</template>
</el-table-column>
+ <el-table-column label="鎿嶄綔" width="120" align="center" fixed="right">
+ <template #default="scope">
+ <el-button
+ v-if="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== '1' && scope.row.approvalStatus !== 'approved' && scope.row.approvalStatus !== 'APPROVED'"
+ link
+ type="primary"
+ size="small"
+ @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <span v-else style="color: #999; font-size: 12px;">宸查�氳繃</span>
+ </template>
+ </el-table-column>
</el-table>
<pagination
v-show="total > 0"
@@ -104,24 +116,160 @@
@pagination="paginationChange"
/>
</div>
+
+ <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="800"
+ @close="closeDialog">
+ <el-form ref="formRef"
+ :model="formState"
+ label-width="140px"
+ label-position="top">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ }
+ ]">
+ <el-button type="primary"
+ @click="showProductSelect = true">
+ {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ <el-form-item label="瑙勬牸"
+ prop="productModelName">
+ <el-input v-model="formState.productModelName" disabled />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formState.unit" disabled />
+ </el-form-item>
+ <el-form-item label="搴撳瓨绫诲瀷"
+ prop="type"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.type"
+ placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+ :disabled="isEdit">
+ <el-option label="鍚堟牸搴撳瓨"
+ value="qualified" />
+ <el-option label="涓嶅悎鏍煎簱瀛�"
+ value="unqualified" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍑哄簱鏁伴噺"
+ prop="qualitity"
+ :rules="[
+ {
+ required: true,
+ message: '璇疯緭鍏ュ嚭搴撴暟閲�',
+ trigger: 'blur',
+ },
+ {
+ validator: (rule, value, callback) => {
+ if (formState.maxStock > 0 && value > formState.maxStock) {
+ callback('鍑哄簱鏁伴噺涓嶈兘瓒呰繃褰撳墠鎵瑰彿搴撳瓨 ' + formState.maxStock);
+ } else {
+ callback();
+ }
+ },
+ trigger: 'blur',
+ }
+ ]">
+ <el-input-number v-model="formState.qualitity"
+ :step="1"
+ :min="1"
+ :max="formState.maxStock > 0 ? formState.maxStock : undefined"
+ style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鎵瑰彿',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.batchNo"
+ placeholder="璇烽�夋嫨鎵瑰彿"
+ clearable
+ :disabled="isEdit"
+ @change="handleBatchNoChange"
+ style="width: 100%">
+ <el-option v-for="batch in batchNoList"
+ :key="batch"
+ :label="batch + ' (搴撳瓨: ' + (batchNoStockMap[batch] || 0) + ')'"
+ :value="batch" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="formState.batchNo && batchNoStockMap[formState.batchNo]"
+ label="褰撳墠鎵瑰彿搴撳瓨"
+ prop="currentStock">
+ <el-input v-model="batchNoStockMap[formState.batchNo]" disabled />
+ </el-form-item>
+ <el-form-item v-if="isEdit"
+ label="鏉ユ簮"
+ prop="recordType">
+ <el-select v-model="formState.recordType"
+ placeholder="璇烽�夋嫨鏉ユ簮"
+ disabled>
+ <el-option v-for="item in stockRecordTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="formState.remark"
+ type="textarea" />
+ </el-form-item>
+ </el-form>
+ <!-- 浜у搧閫夋嫨寮圭獥 -->
+ <ProductSelectDialog v-model="showProductSelect"
+ @confirm="handleProductSelect"
+ :top-product-parent-id="props.topParentProductId"
+ request-url="/basic/product/pageModelAndQua"
+ single />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleSubmit">纭</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref } from "vue";
-import { ElMessageBox } from "element-plus";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import { ref, reactive, toRefs, computed, getCurrentInstance, watch, onMounted } from "vue";
+import { ElMessageBox, ElMessage } from "element-plus";
import useUserStore from "@/store/modules/user";
import { getCurrentDate } from "@/utils/index.js";
import {
getStockOutPage,
delPendingStockOut,
batchApproveStockOutRecords,
+ updateStockOutRecord,
} from "@/api/inventoryManagement/stockOut.js";
import {
findAllQualifiedStockOutRecordTypeOptions,
findAllUnQualifiedStockOutRecordTypeOptions,
} from "@/api/basicData/enum.js";
+import { addStockOutRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
+import { addUnqualifiedStockOutRecordOnly } from "@/api/inventoryManagement/stockUninventory.js";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
@@ -130,6 +278,10 @@
const tableLoading = ref(false);
// 鏉ユ簮绫诲瀷閫夐」
const stockRecordTypeOptions = ref([]);
+// 鎵瑰彿鍒楄〃锛堜粠batchNoMaps鑾峰彇锛�
+const batchNoList = ref([]);
+// 鎵瑰彿搴撳瓨鏄犲皠
+const batchNoStockMap = ref({});
const page = reactive({
current: 1,
size: 100,
@@ -161,6 +313,40 @@
},
});
const { searchForm } = toRefs(data);
+
+// 瀵硅瘽妗嗙浉鍏�
+const dialogVisible = ref(false);
+const dialogType = ref('add'); // 'add' 鎴� 'edit'
+const dialogTitle = computed(() => dialogType.value === 'add' ? '鏂板鍑哄簱璁板綍' : '缂栬緫鍑哄簱璁板綍');
+const isEdit = computed(() => dialogType.value === 'edit');
+const formRef = ref();
+const showProductSelect = ref(false);
+
+// 琛ㄥ崟鏁版嵁
+const formState = ref({
+ id: undefined,
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ productModelName: "",
+ unit: "",
+ type: undefined,
+ qualitity: 0,
+ batchNo: null,
+ recordType: "",
+ remark: "",
+ maxStock: 0, // 褰撳墠閫変腑鎵瑰彿鐨勬渶澶у簱瀛�
+});
+
+// 鎵瑰彿涓虹┖鏃惰浆涓� null
+watch(
+ () => formState.value.batchNo,
+ val => {
+ if (val === "") {
+ formState.value.batchNo = null;
+ }
+ }
+);
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
@@ -239,6 +425,178 @@
return "warning";
};
+// 鏂板
+const handleAdd = () => {
+ dialogType.value = 'add';
+ resetForm();
+ // 鏍规嵁褰撳墠tab璁剧疆榛樿搴撳瓨绫诲瀷
+ formState.value.type = props.type === '0' ? 'qualified' : 'unqualified';
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const handleEdit = (row) => {
+ dialogType.value = 'edit';
+ resetForm();
+ // 濉厖琛ㄥ崟鏁版嵁
+ formState.value = {
+ id: row.id,
+ productId: row.productId,
+ productModelId: row.productModelId,
+ productName: row.productName,
+ productModelName: row.model,
+ unit: row.unit,
+ type: props.type === '0' ? 'qualified' : 'unqualified',
+ qualitity: row.stockOutNum,
+ batchNo: row.batchNo,
+ recordType: row.recordType,
+ remark: row.remark || "",
+ maxStock: row.stockOutNum || 0, // 缂栬緫鏃朵娇鐢ㄥ綋鍓嶅嚭搴撴暟閲忎綔涓烘渶澶у簱瀛橈紙鍥犱负鏄慨鏀瑰凡鏈夎褰曪級
+ };
+ // 缂栬緫鏃朵粠batchNoMaps鑾峰彇鎵瑰彿鍒楄〃
+ if (row.batchNoMaps && Object.keys(row.batchNoMaps).length > 0) {
+ batchNoList.value = Object.keys(row.batchNoMaps);
+ batchNoStockMap.value = row.batchNoMaps;
+ } else if (row.batchNo) {
+ batchNoList.value = [row.batchNo];
+ batchNoStockMap.value = { [row.batchNo]: row.stockOutNum || 0 };
+ } else {
+ batchNoList.value = [];
+ batchNoStockMap.value = {};
+ }
+ dialogVisible.value = true;
+};
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+ formState.value = {
+ id: undefined,
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ productModelName: "",
+ unit: "",
+ type: undefined,
+ qualitity: 0,
+ batchNo: null,
+ recordType: "",
+ remark: "",
+ maxStock: 0,
+ };
+ batchNoList.value = [];
+ batchNoStockMap.value = {};
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const closeDialog = () => {
+ dialogVisible.value = false;
+ resetForm();
+};
+
+// 浜у搧閫夋嫨澶勭悊
+const handleProductSelect = async products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ formState.value.productId = product.productId;
+ formState.value.productName = product.productName;
+ formState.value.productModelName = product.model;
+ formState.value.productModelId = product.id;
+ formState.value.unit = product.unit;
+ // 浠巄atchNoMaps鑾峰彇鎵瑰彿鍒楄〃鍜屽簱瀛�
+ if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) {
+ batchNoList.value = Object.keys(product.batchNoMaps);
+ batchNoStockMap.value = product.batchNoMaps;
+ } else {
+ batchNoList.value = [];
+ batchNoStockMap.value = {};
+ }
+ // 娓呯┖宸查�夋嫨鐨勬壒鍙峰拰鏈�澶у簱瀛�
+ formState.value.batchNo = null;
+ formState.value.maxStock = 0;
+ showProductSelect.value = false;
+ // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+ proxy.$refs["formRef"]?.validateField("productModelId");
+ }
+};
+
+// 鎵瑰彿閫夋嫨鍙樺寲澶勭悊
+const handleBatchNoChange = (batchNo) => {
+ if (batchNo && batchNoStockMap.value[batchNo]) {
+ formState.value.maxStock = batchNoStockMap.value[batchNo];
+ // 濡傛灉褰撳墠鍑哄簱鏁伴噺瓒呰繃鏈�澶у簱瀛橈紝鑷姩璋冩暣涓烘渶澶у簱瀛�
+ if (formState.value.qualitity > formState.value.maxStock) {
+ formState.value.qualitity = formState.value.maxStock;
+ }
+ } else {
+ formState.value.maxStock = 0;
+ }
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝�
+ if (!formState.value.productModelId) {
+ ElMessage.error("璇烽�夋嫨浜у搧");
+ return;
+ }
+
+ if (dialogType.value === 'add') {
+ submitAdd();
+ } else {
+ submitEdit();
+ }
+ }
+ });
+};
+
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ const params = { ...formState.value };
+
+ if (formState.value.type === "qualified") {
+ addStockOutRecordOnly(params).then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ } else {
+ addUnqualifiedStockOutRecordOnly(params).then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ }
+};
+
+// 鎻愪氦缂栬緫
+const submitEdit = () => {
+ const params = {
+ productId: formState.value.productId,
+ productModelId: formState.value.productModelId,
+ productName: formState.value.productName,
+ model: formState.value.productModelName,
+ unit: formState.value.unit,
+ batchNo: formState.value.batchNo,
+ stockOutNum: formState.value.qualitity,
+ recordType: formState.value.recordType,
+ remark: formState.value.remark,
+ };
+
+ updateStockOutRecord(formState.value.id, params).then(() => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+};
+
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
if (props.type === "0") {
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 78ba5bb..8e51b13 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -31,6 +31,7 @@
</el-button>
</div>
<div>
+ <el-button type="primary" @click="handleAdd">鏂板</el-button>
<el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger"
@@ -97,6 +98,17 @@
</el-tag>
</template>
</el-table-column>
+ <el-table-column label="鎿嶄綔" width="120" align="center" fixed="right">
+ <template #default="scope">
+ <el-button
+ v-if="scope.row.approvalStatus !== 1 && scope.row.approvalStatus !== '1' && scope.row.approvalStatus !== 'approved' && scope.row.approvalStatus !== 'APPROVED'"
+ link
+ type="primary"
+ size="small"
+ @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <span v-else style="color: #999; font-size: 12px;">宸查�氳繃</span>
+ </template>
+ </el-table-column>
</el-table>
<pagination v-show="total > 0"
:total="total"
@@ -105,29 +117,157 @@
:limit="page.size"
@pagination="pageProductChange"/>
</div>
+
+ <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="800"
+ @close="closeDialog">
+ <el-form ref="formRef"
+ :model="formState"
+ label-width="140px"
+ label-position="top">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ }
+ ]">
+ <el-button type="primary"
+ @click="showProductSelect = true">
+ {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ <el-form-item label="瑙勬牸"
+ prop="productModelName">
+ <el-input v-model="formState.productModelName" disabled />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formState.unit" disabled />
+ </el-form-item>
+ <el-form-item label="搴撳瓨绫诲瀷"
+ prop="type"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.type"
+ placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+ :disabled="isEdit">
+ <el-option label="鍚堟牸搴撳瓨"
+ value="qualified" />
+ <el-option label="涓嶅悎鏍煎簱瀛�"
+ value="unqualified" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="搴撳瓨鏁伴噺"
+ prop="qualitity">
+ <el-input-number v-model="formState.qualitity"
+ :step="1"
+ :min="1"
+ style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo">
+ <el-input v-model="formState.batchNo"
+ placeholder="璇疯緭鍏ユ壒鍙�"
+ :disabled="isEdit" />
+ </el-form-item>
+ <el-form-item label="搴撲綅"
+ prop="warehouseId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨搴撲綅',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.warehouseId"
+ placeholder="璇烽�夋嫨搴撲綅"
+ clearable
+ style="width: 100%">
+ <el-option v-for="warehouse in warehouseList"
+ :key="warehouse.id"
+ :label="warehouse.warehouseName + ' - ' + warehouse.location"
+ :value="warehouse.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="isEdit"
+ label="鏉ユ簮"
+ prop="recordType">
+ <el-select v-model="formState.recordType"
+ placeholder="璇烽�夋嫨鏉ユ簮"
+ disabled>
+ <el-option v-for="item in stockRecordTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="formState.type === 'qualified'"
+ label="搴撳瓨棰勮鏁伴噺"
+ prop="warnNum">
+ <el-input-number v-model="formState.warnNum"
+ :step="1"
+ :min="0"
+ :max="formState.qualitity"
+ style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="formState.remark"
+ type="textarea" />
+ </el-form-item>
+ </el-form>
+ <!-- 浜у搧閫夋嫨寮圭獥 -->
+ <ProductSelectDialog v-model="showProductSelect"
+ @confirm="handleProductSelect"
+ :top-product-parent-id="topParentProductId"
+ single />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleSubmit">纭</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
import {
ref,
reactive,
toRefs,
onMounted,
getCurrentInstance,
+ computed,
+ watch,
} from "vue";
-import {ElMessageBox} from "element-plus";
+import { ElMessageBox, ElMessage } from "element-plus";
import {
getStockInRecordListPage,
batchDeletePendingStockInRecords,
batchApproveStockInRecords,
+ updateStockInRecord,
} from "@/api/inventoryManagement/stockInRecord.js";
+import { addStockInRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
+import { createStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js";
import {
findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions,
} from "@/api/basicData/enum.js";
+import { getWarehouseList } from "@/api/inventoryManagement/warehouse.js";
-const {proxy} = getCurrentInstance();
+const { proxy } = getCurrentInstance();
const props = defineProps({
type: {
@@ -146,6 +286,8 @@
const tableLoading = ref(false);
// 鏉ユ簮绫诲瀷閫夐」
const stockRecordTypeOptions = ref([]);
+// 浠撳簱鍒楄〃
+const warehouseList = ref([]);
const page = reactive({
current: 1,
size: 10,
@@ -159,7 +301,43 @@
recordType: "",
},
});
-const {searchForm} = toRefs(data);
+const { searchForm } = toRefs(data);
+
+// 瀵硅瘽妗嗙浉鍏�
+const dialogVisible = ref(false);
+const dialogType = ref('add'); // 'add' 鎴� 'edit'
+const dialogTitle = computed(() => dialogType.value === 'add' ? '鏂板鍏ュ簱璁板綍' : '缂栬緫鍏ュ簱璁板綍');
+const isEdit = computed(() => dialogType.value === 'edit');
+const formRef = ref();
+const showProductSelect = ref(false);
+
+// 琛ㄥ崟鏁版嵁锛堜豢鐓ew.vue浣跨敤formState锛�
+const formState = ref({
+ id: undefined,
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ productModelName: "",
+ unit: "",
+ type: undefined,
+ qualitity: 0,
+ batchNo: null,
+ warehouseId: undefined,
+ warnNum: 0,
+ recordType: "",
+ remark: "",
+});
+
+// 鎵瑰彿涓虹┖鏃惰浆涓� null
+watch(
+ () => formState.value.batchNo,
+ val => {
+ if (val === "") {
+ formState.value.batchNo = null;
+ }
+ }
+);
+
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
@@ -214,32 +392,32 @@
const getList = () => {
tableLoading.value = true;
- const params = {...page, topParentProductId: props.topParentProductId};
+ const params = { ...page, topParentProductId: props.topParentProductId };
params.timeStr = searchForm.value.timeStr;
params.productName = searchForm.value.productName;
params.recordType = searchForm.value.recordType;
getStockInRecordListPage(params)
- .then(res => {
- tableData.value = res.data.records;
- total.value = res.data.total || 0;
- }).finally(() => {
- tableLoading.value = false;
- })
+ .then(res => {
+ tableData.value = res.data.records;
+ total.value = res.data.total || 0;
+ }).finally(() => {
+ tableLoading.value = false;
+ })
};
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
if (props.type === '0') {
findAllQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
- return
- }
- findAllUnQualifiedStockInRecordTypeOptions()
.then(res => {
stockRecordTypeOptions.value = res.data;
})
+ return
+ }
+ findAllUnQualifiedStockInRecordTypeOptions()
+ .then(res => {
+ stockRecordTypeOptions.value = res.data;
+ })
}
// 琛ㄦ牸閫夋嫨鏁版嵁
@@ -248,6 +426,155 @@
};
const expandedRowKeys = ref([]);
+
+// 鏂板
+const handleAdd = () => {
+ dialogType.value = 'add';
+ resetForm();
+ // 鏍规嵁褰撳墠tab璁剧疆榛樿搴撳瓨绫诲瀷
+ formState.value.type = props.type === '0' ? 'qualified' : 'unqualified';
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const handleEdit = (row) => {
+ dialogType.value = 'edit';
+ resetForm();
+ // 濉厖琛ㄥ崟鏁版嵁
+ formState.value = {
+ id: row.id,
+ productId: row.productId,
+ productModelId: row.productModelId,
+ productName: row.productName,
+ productModelName: row.model,
+ unit: row.unit,
+ type: props.type === '0' ? 'qualified' : 'unqualified',
+ qualitity: row.stockInNum,
+ batchNo: row.batchNo,
+ warehouseId: row.warehouseId,
+ warnNum: row.warnNum || 0,
+ recordType: row.recordType,
+ remark: row.remark || "",
+ };
+ dialogVisible.value = true;
+};
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+ formState.value = {
+ id: undefined,
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ productModelName: "",
+ unit: "",
+ type: undefined,
+ qualitity: 0,
+ batchNo: null,
+ warehouseId: undefined,
+ warnNum: 0,
+ recordType: "",
+ remark: "",
+ };
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const closeDialog = () => {
+ dialogVisible.value = false;
+ resetForm();
+};
+
+// 浜у搧閫夋嫨澶勭悊锛堜豢鐓ew.vue锛�
+const handleProductSelect = async products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ formState.value.productId = product.productId;
+ formState.value.productName = product.productName;
+ formState.value.productModelName = product.model;
+ formState.value.productModelId = product.id;
+ formState.value.unit = product.unit;
+ showProductSelect.value = false;
+ // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+ proxy.$refs["formRef"]?.validateField("productModelId");
+ }
+};
+
+// 鎻愪氦琛ㄥ崟锛堜豢鐓ew.vue锛�
+const handleSubmit = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰瑙勬牸
+ if (!formState.value.productModelId) {
+ ElMessage.error("璇烽�夋嫨浜у搧");
+ return;
+ }
+
+ if (dialogType.value === 'add') {
+ submitAdd();
+ } else {
+ submitEdit();
+ }
+ }
+ });
+};
+
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ const params = { ...formState.value };
+
+ if (formState.value.type === "qualified") {
+ addStockInRecordOnly(params).then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ } else {
+ params.warnNum = 0;
+ createStockUnInventory(params).then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ }
+};
+
+// 鑾峰彇浠撳簱鍒楄〃
+const fetchWarehouseList = () => {
+ getWarehouseList({ status: true }).then(res => {
+ warehouseList.value = res.data || [];
+ }).catch(() => {
+ ElMessage.error("鑾峰彇浠撳簱鍒楄〃澶辫触");
+ });
+};
+
+// 鎻愪氦缂栬緫
+const submitEdit = () => {
+ const params = {
+ productId: formState.value.productId,
+ productModelId: formState.value.productModelId,
+ productName: formState.value.productName,
+ model: formState.value.productModelName,
+ unit: formState.value.unit,
+ batchNo: formState.value.batchNo,
+ warehouseId: formState.value.warehouseId,
+ stockInNum: formState.value.qualitity,
+ recordType: formState.value.recordType,
+ remark: formState.value.remark,
+ warnNum: formState.value.warnNum,
+ };
+
+ updateStockInRecord(formState.value.id, params).then(() => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ closeDialog();
+ getList();
+ }).catch(() => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+};
const handleBatchApprove = () => {
if (selectedRows.value.length === 0) {
@@ -261,30 +588,30 @@
type: "warning",
distinguishCancelAndClose: true,
})
- .then(() => {
- batchApproveStockInRecords({ids, approvalStatus: 1})
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
- });
- })
- .catch((action) => {
- if (action === "cancel") {
- batchApproveStockInRecords({ids, approvalStatus: 2})
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
- });
- return;
- }
- proxy.$modal.msg("宸插彇娑�");
- });
+ .then(() => {
+ batchApproveStockInRecords({ ids, approvalStatus: 1 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
+ });
+ })
+ .catch((action) => {
+ if (action === "cancel") {
+ batchApproveStockInRecords({ ids, approvalStatus: 2 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ });
+ return;
+ }
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 瀵煎嚭
@@ -294,13 +621,13 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- // 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
- proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ .then(() => {
+ // 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
+ proxy.download("/stockInRecord/exportStockInRecord", { type: props.type }, props.type === '0' ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍒犻櫎
@@ -316,24 +643,25 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- batchDeletePendingStockInRecords(ids)
- .then(() => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ .then(() => {
+ batchDeletePendingStockInRecords(ids)
+ .then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍒犻櫎澶辫触");
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
onMounted(() => {
getList();
fetchStockRecordTypeOptions();
+ fetchWarehouseList();
});
watch(
@@ -346,6 +674,3 @@
</script>
<style scoped lang="scss"></style>
-
-
-
diff --git a/src/views/inventoryManagement/stockManagement/Record.vue b/src/views/inventoryManagement/stockManagement/Record.vue
index 7c0a461..0e16cca 100644
--- a/src/views/inventoryManagement/stockManagement/Record.vue
+++ b/src/views/inventoryManagement/stockManagement/Record.vue
@@ -34,8 +34,9 @@
<el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" show-overflow-tooltip />
<el-table-column label="澶囨敞" prop="remark" show-overflow-tooltip />
<el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" min-width="90" align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" min-width="120" align="center">
<template #default="scope">
+ <el-button link type="primary" @click="showEditModal(scope.row)">缂栬緫</el-button>
<el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="((scope.row.qualifiedUnLockedQuantity || 0) + (scope.row.qualifiedPendingOutQuantity || 0) <= 0) && ((scope.row.unQualifiedUnLockedQuantity || 0) + (scope.row.unQualifiedPendingOutQuantity || 0) <= 0)">棰嗙敤</el-button>
<el-button link type="primary" v-if="scope.row.unQualifiedUnLockedQuantity > 0 || scope.row.qualifiedUnLockedQuantity > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
<el-button link type="primary" v-if="scope.row.qualifiedLockedQuantity > 0 || scope.row.unQualifiedLockedQuantity > 0" @click="showThawModal(scope.row)">瑙e喕</el-button>
@@ -48,6 +49,11 @@
<new-stock-inventory v-if="isShowNewModal"
v-model:visible="isShowNewModal"
:top-product-parent-id="props.productId"
+ @completed="handleQuery" />
+
+ <edit-stock-inventory
+ v-model:visible="isShowEditModal"
+ :record="record"
@completed="handleQuery" />
<subtract-stock-inventory v-if="isShowSubtractModal"
@@ -86,6 +92,7 @@
});
const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
+const EditStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Edit.vue"));
const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue"));
const ImportStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Import.vue"));
const FrozenAndThawStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue"));
@@ -101,6 +108,8 @@
const total = ref(0)
// 鏄惁鏄剧ず鏂板寮规
const isShowNewModal = ref(false)
+// 鏄惁鏄剧ず缂栬緫寮规
+const isShowEditModal = ref(false)
// 鏄惁鏄剧ず棰嗙敤寮规
const isShowSubtractModal = ref(false)
// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
@@ -152,6 +161,12 @@
}
};
+// 鐐瑰嚮缂栬緫
+const showEditModal = (row) => {
+ record.value = row
+ isShowEditModal.value = true
+}
+
// 鐐瑰嚮棰嗙敤
const showSubtractModal = (row) => {
record.value = row
diff --git a/src/views/inventoryManagement/warehouseManagement/index.vue b/src/views/inventoryManagement/warehouseManagement/index.vue
new file mode 100644
index 0000000..d62e4f1
--- /dev/null
+++ b/src/views/inventoryManagement/warehouseManagement/index.vue
@@ -0,0 +1,491 @@
+<template>
+ <div class="app-container">
+ <div class="search_form" style="margin-bottom: 10px">
+ <div>
+ <span class="search_title">浠撳簱鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.warehouseName"
+ placeholder="璇疯緭鍏ヤ粨搴撳悕绉�"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ <span class="search_title ml10">浠撳簱浣嶇疆锛�</span>
+ <el-input
+ v-model="searchForm.location"
+ placeholder="璇疯緭鍏ヤ粨搴撲綅缃�"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ <span class="search_title ml10">璐熻矗浜猴細</span>
+ <el-input
+ v-model="searchForm.managerName"
+ placeholder="璇疯緭鍏ヨ礋璐d汉"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="handleAdd">鏂板</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"
+ style="width: 100%"
+ 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="warehouseName"
+ min-width="150"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="浠撳簱浣嶇疆"
+ prop="location"
+ min-width="200"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="璐熻矗浜�"
+ prop="managerName"
+ min-width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鑱旂郴鐢佃瘽"
+ prop="contactPhone"
+ min-width="150"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鐘舵��" prop="status" width="100" align="center">
+ <template #default="scope">
+ <el-tag :type="scope.row.status ? 'success' : 'info'" size="small">
+ {{ scope.row.status ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="鍒涘缓鏃堕棿"
+ prop="createTime"
+ min-width="180"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鎿嶄綔" width="150" align="center" fixed="right">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <el-button link type="danger" size="small" @click="handleRowDelete(scope.row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ />
+ </div>
+
+ <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ width="600"
+ @close="closeDialog"
+ >
+ <el-form
+ ref="formRef"
+ :model="formState"
+ label-width="100px"
+ :rules="formRules"
+ >
+ <el-form-item label="浠撳簱鍚嶇О" prop="warehouseName">
+ <el-input
+ v-model="formState.warehouseName"
+ placeholder="璇疯緭鍏ヤ粨搴撳悕绉�"
+ maxlength="50"
+ show-word-limit
+ />
+ </el-form-item>
+ <el-form-item label="浠撳簱浣嶇疆" prop="location">
+ <el-input
+ v-model="formState.location"
+ placeholder="璇疯緭鍏ヤ粨搴撲綅缃�"
+ maxlength="200"
+ show-word-limit
+ />
+ </el-form-item>
+ <el-form-item label="璐熻矗浜�" prop="managerId">
+ <el-select
+ v-model="formState.managerId"
+ placeholder="璇烽�夋嫨璐熻矗浜�"
+ clearable
+ filterable
+ style="width: 100%"
+ @change="handleManagerChange"
+ >
+ <el-option
+ v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鑱旂郴鐢佃瘽" prop="contactPhone">
+ <el-input
+ v-model="formState.contactPhone"
+ placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
+ maxlength="20"
+ show-word-limit
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-radio-group v-model="formState.status">
+ <el-radio :value="true">鍚敤</el-radio>
+ <el-radio :value="false">鍋滅敤</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleSubmit">纭</el-button>
+ <el-button @click="closeDialog">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, reactive, computed, getCurrentInstance, onMounted } from "vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import {
+ getWarehousePage,
+ addWarehouse,
+ updateWarehouse,
+ delWarehouse,
+ updateWarehouseStatus,
+} from "@/api/inventoryManagement/warehouse.js";
+import { listUser } from "@/api/system/user.js";
+
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+
+const page = reactive({
+ current: 1,
+ size: 10,
+});
+const total = ref(0);
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+ warehouseName: "",
+ location: "",
+ managerName: "",
+});
+
+// 瀵硅瘽妗嗙浉鍏�
+const dialogVisible = ref(false);
+const dialogType = ref("add"); // 'add' 鎴� 'edit'
+const dialogTitle = computed(() =>
+ dialogType.value === "add" ? "鏂板浠撳簱" : "缂栬緫浠撳簱"
+);
+const isEdit = computed(() => dialogType.value === "edit");
+const formRef = ref();
+
+// 琛ㄥ崟鏁版嵁
+const formState = reactive({
+ id: undefined,
+ warehouseName: "",
+ location: "",
+ managerId: undefined,
+ managerName: "",
+ contactPhone: "",
+ status: true,
+});
+
+// 鐢ㄦ埛鍒楄〃
+const userList = ref([]);
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const formRules = {
+ warehouseName: [
+ { required: true, message: "璇疯緭鍏ヤ粨搴撳悕绉�", trigger: "blur" },
+ { min: 1, max: 50, message: "闀垮害鍦� 1 鍒� 50 涓瓧绗�", trigger: "blur" },
+ ],
+ location: [
+ { required: true, message: "璇疯緭鍏ヤ粨搴撲綅缃�", trigger: "blur" },
+ { min: 1, max: 200, message: "闀垮害鍦� 1 鍒� 200 涓瓧绗�", trigger: "blur" },
+ ],
+ managerId: [
+ { required: true, message: "璇烽�夋嫨璐熻矗浜�", trigger: "change" },
+ ],
+ contactPhone: [
+ { required: true, message: "璇疯緭鍏ヨ仈绯荤數璇�", trigger: "blur" },
+ { pattern: /^1[3-9]\d{9}$|^0\d{2,3}-?\d{7,8}$/, message: "璇疯緭鍏ユ纭殑鐢佃瘽鍙风爜", trigger: "blur" },
+ ],
+ status: [{ required: true, message: "璇烽�夋嫨鐘舵��", trigger: "change" }],
+};
+
+// 鑾峰彇鐢ㄦ埛鍒楄〃
+const getUserList = () => {
+ listUser({ pageNum: 1, pageSize: 1000 }).then((res) => {
+ userList.value = res.rows || [];
+ });
+};
+
+// 璐熻矗浜洪�夋嫨鍙樺寲
+const handleManagerChange = (userId) => {
+ const user = userList.value.find((item) => item.userId === userId);
+ if (user) {
+ formState.managerName = user.nickName;
+ } else {
+ formState.managerName = "";
+ }
+};
+
+// 鏌ヨ鍒楄〃
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+
+// 閲嶇疆鎼滅储
+const handleReset = () => {
+ searchForm.warehouseName = "";
+ searchForm.location = "";
+ searchForm.managerName = "";
+ handleQuery();
+};
+
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+
+const getList = () => {
+ tableLoading.value = true;
+ getWarehousePage({
+ ...searchForm,
+ current: page.current,
+ size: page.size,
+ })
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records || [];
+ total.value = res.data.total || 0;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+};
+
+// 鏂板
+const handleAdd = () => {
+ dialogType.value = "add";
+ resetForm();
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const handleEdit = (row) => {
+ dialogType.value = "edit";
+ resetForm();
+ // 鏍规嵁managerName鏌ユ壘瀵瑰簲鐨刴anagerId
+ const user = userList.value.find((item) => item.nickName === row.managerName);
+ // 濉厖琛ㄥ崟鏁版嵁
+ Object.assign(formState, {
+ id: row.id,
+ warehouseName: row.warehouseName,
+ location: row.location,
+ managerId: user ? user.userId : row.managerId,
+ managerName: row.managerName,
+ contactPhone: row.contactPhone,
+ status: row.status,
+ });
+ dialogVisible.value = true;
+};
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+ formState.id = undefined;
+ formState.warehouseName = "";
+ formState.location = "";
+ formState.managerId = undefined;
+ formState.managerName = "";
+ formState.contactPhone = "";
+ formState.status = true;
+ proxy.$refs["formRef"]?.resetFields();
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const closeDialog = () => {
+ dialogVisible.value = false;
+ resetForm();
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (dialogType.value === "add") {
+ submitAdd();
+ } else {
+ submitEdit();
+ }
+ }
+ });
+};
+
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ const params = { ...formState };
+ delete params.id;
+ addWarehouse(params)
+ .then(() => {
+ ElMessage.success("鏂板鎴愬姛");
+ closeDialog();
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+};
+
+// 鎻愪氦缂栬緫
+const submitEdit = () => {
+ const params = { ...formState };
+ updateWarehouse(params)
+ .then(() => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ closeDialog();
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+};
+
+// 鐘舵�佸彉鏇�
+const handleStatusChange = (row) => {
+ const statusText = row.status ? "鍚敤" : "鍋滅敤";
+ ElMessageBox.confirm(
+ `纭瑕�${statusText}璇ヤ粨搴撳悧锛焋,
+ "鎻愮ず",
+ {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ )
+ .then(() => {
+ updateWarehouseStatus(row.id, row.status)
+ .then(() => {
+ ElMessage.success(`${statusText}鎴愬姛`);
+ getList();
+ })
+ .catch(() => {
+ // 鎭㈠鍘熺姸鎬�
+ row.status = !row.status;
+ ElMessage.error(`${statusText}澶辫触`);
+ });
+ })
+ .catch(() => {
+ // 鎭㈠鍘熺姸鎬�
+ row.status = !row.status;
+ ElMessage.info("宸插彇娑�");
+ });
+};
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+
+// 鎵归噺鍒犻櫎
+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(() => {
+ delWarehouse(ids).then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鍗曡鍒犻櫎
+const handleRowDelete = (row) => {
+ ElMessageBox.confirm("纭鍒犻櫎璇ヤ粨搴撳悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delWarehouse([row.id]).then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鍒濆鍖栧姞杞芥暟鎹�
+onMounted(() => {
+ getList();
+ getUserList();
+});
+</script>
+
+<style scoped>
+.search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.search_title {
+ font-size: 14px;
+ color: #606266;
+}
+.ml10 {
+ margin-left: 10px;
+}
+.table_list {
+ margin-top: 10px;
+}
+</style>
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index cffdcc6..5555f66 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -394,15 +394,6 @@
prop="taxExclusiveTotalPrice"
:formatter="formattedNumber"
width="150" />
- <el-table-column label="鏄惁璐ㄦ"
- prop="isChecked"
- width="150">
- <template #default="scope">
- <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
- {{ scope.row.isChecked ? '鏄�' : '鍚�' }}
- </el-tag>
- </template>
- </el-table-column>
<el-table-column fixed="right"
label="鎿嶄綔"
min-width="60"
@@ -615,19 +606,6 @@
:min="0"
clearable
style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鏄惁璐ㄦ锛�"
- prop="isChecked">
- <el-radio-group v-model="productForm.isChecked">
- <el-radio label="鏄�"
- :value="true" />
- <el-radio label="鍚�"
- :value="false" />
- </el-radio-group>
</el-form-item>
</el-col>
</el-row>
@@ -852,7 +830,6 @@
supplierId: "",
paymentMethod: "",
executionDate: "",
- isChecked: false,
},
rules: {
purchaseContractNumber: [
@@ -897,7 +874,6 @@
taxExclusiveTotalPrice: "",
invoiceType: "",
warnNum: "",
- isChecked: false,
},
productRules: {
productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
@@ -916,7 +892,6 @@
{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
],
invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
const { productForm, productRules } = toRefs(productFormData);
@@ -1386,9 +1361,7 @@
// 绛夊緟 DOM 鏇存柊
await nextTick();
- if (type === "add") {
- productForm.value.isChecked = false;
- }
+
if (type === "edit") {
// 澶嶅埗琛屾暟鎹�
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 4e2d84e..27ab2c3 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -451,15 +451,6 @@
<el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
prop="taxExclusiveTotalPrice"
:formatter="formattedNumber" />
- <el-table-column label="鏄惁鐢熶骇"
- prop="isProduction"
- width="150">
- <template #default="scope">
- <el-tag :type="scope.row.isProduction ? 'success' : 'info'">
- {{ scope.row.isProduction ? '鏄�' : '鍚�' }}
- </el-tag>
- </template>
- </el-table-column>
<el-table-column fixed="right"
label="鎿嶄綔"
min-width="60"
@@ -706,17 +697,6 @@
<el-option label="澧炰笓绁�"
value="澧炰笓绁�" />
</el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏄惁鐢熶骇锛�"
- prop="isProduction">
- <el-radio-group v-model="productForm.isProduction">
- <el-radio label="鏄�"
- :value="true" />
- <el-radio label="鍚�"
- :value="false" />
- </el-radio-group>
</el-form-item>
</el-col>
</el-row>
@@ -1105,7 +1085,6 @@
taxInclusiveTotalPrice: "",
taxExclusiveTotalPrice: "",
invoiceType: "",
- isProduction: false,
},
productRules: {
productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
@@ -1126,7 +1105,6 @@
{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
],
invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
const { productForm, productRules } = toRefs(productFormData);
@@ -1754,9 +1732,6 @@
productOperationType.value = type;
productForm.value = {};
- if (type === "add") {
- productForm.value.isProduction = true;
- }
proxy.resetForm("productFormRef");
if (type === "edit") {
productForm.value = { ...row };
--
Gitblit v1.9.3