From 5b3cbcef771cd23ef8db1bf29dd15e2ddd98744f Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 24 四月 2026 14:58:53 +0800
Subject: [PATCH] fix: 库存管理页面修改,领用、冻结与解冻区分
---
src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue | 262 ++++++++++++++++++----------
src/views/inventoryManagement/stockManagement/Qualified.vue | 8
src/views/inventoryManagement/stockManagement/Subtract.vue | 250 +++++++++++++++++----------
3 files changed, 333 insertions(+), 187 deletions(-)
diff --git a/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
index 463cb83..05c57b4 100644
--- a/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
+++ b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
@@ -1,17 +1,38 @@
<template>
<div>
<el-dialog
- v-model="isShow"
- :title="operationType === 'frozen' ? '鍐荤粨搴撳瓨' : '瑙e喕搴撳瓨'"
- width="800"
- @close="closeModal"
+ v-model="isShow"
+ :title="operationType === 'frozen' ? '鍐荤粨搴撳瓨' : '瑙e喕搴撳瓨'"
+ width="800"
+ @close="closeModal"
>
<el-form label-width="140px" :model="formState" ref="formRef">
<el-form-item
- :label="operationType === 'frozen' ? '鍐荤粨鏁伴噺锛�' : '瑙e喕鏁伴噺锛�'"
- prop="lockedQuantity"
+ label="搴撳瓨绫诲瀷"
+ prop="stockType"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+ trigger: 'change',
+ }
+ ]"
>
- <el-input-number v-model="formState.lockedQuantity" :step="1" :min="1" precision="0" style="width: 100%" :max="maxCount" />
+ <el-select v-model="formState.stockType" placeholder="璇烽�夋嫨搴撳瓨绫诲瀷" style="width: 100%">
+ <el-option label="鍚堟牸搴撳瓨" value="qualified" />
+ <el-option label="涓嶅悎鏍煎簱瀛�" value="unqualified" />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item :label="operationType === 'frozen' ? '鍐荤粨鏁伴噺锛�' : '瑙e喕鏁伴噺锛�'" prop="lockedQuantity">
+ <el-input-number
+ v-model="formState.lockedQuantity"
+ :step="0.01"
+ :min="inputMin"
+ :precision="2"
+ style="width: 100%"
+ :max="maxCount"
+ />
</el-form-item>
</el-form>
@@ -26,39 +47,67 @@
</template>
<script setup>
-import {ref, computed, getCurrentInstance} from "vue";
-import {frozenStockInventory, thawStockInventory} from "@/api/inventoryManagement/stockInventory.js";
-import {frozenStockUninventory, thawStockUninventory} from "@/api/inventoryManagement/stockUninventory.js";
+import { ref, computed, getCurrentInstance, onMounted, watch } from "vue";
+import { frozenStockInventory, thawStockInventory } from "@/api/inventoryManagement/stockInventory.js";
+import { frozenStockUninventory, thawStockUninventory } from "@/api/inventoryManagement/stockUninventory.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
},
-
operationType: {
type: String,
required: true,
- default: 'frozen',
+ default: "frozen",
},
-
type: {
type: String,
required: true,
- default: 'qualified',
+ default: "qualified",
},
-
record: {
type: Object,
- default: () => {},
- }
+ default: () => ({}),
+ },
});
-const emit = defineEmits(['update:visible', 'completed']);
+const emit = defineEmits(["update:visible", "completed"]);
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
+const toNumber = (value) => {
+ const num = Number(value);
+ return Number.isFinite(num) ? num : 0;
+};
+
+const getQualifiedUnLockedStock = (row) => {
+ return toNumber(
+ row?.qualifiedUnLockedQuantity ??
+ row?.unLockedQuantity ??
+ row?.qualifiedQuantity ??
+ row?.qualitity
+ );
+};
+
+const getUnqualifiedUnLockedStock = (row) => {
+ return toNumber(
+ row?.unQualifiedUnLockedQuantity ??
+ row?.unqualifiedUnLockedQuantity ??
+ row?.unQualifiedQuantity ??
+ row?.unqualifiedQuantity
+ );
+};
+
+const getQualifiedLockedStock = (row) => {
+ return toNumber(row?.qualifiedLockedQuantity ?? row?.lockedQuantity);
+};
+
+const getUnqualifiedLockedStock = (row) => {
+ return toNumber(row?.unQualifiedLockedQuantity ?? row?.unqualifiedLockedQuantity);
+};
+
const formState = ref({
- lockedQuantity: 0,
+ stockType: "qualified",
+ lockedQuantity: 0.01,
});
const isShow = computed({
@@ -66,95 +115,122 @@
return props.visible;
},
set(val) {
- emit('update:visible', val);
+ emit("update:visible", val);
},
});
+const maxCount = computed(() => {
+ const isQualified = formState.value.stockType === "qualified";
+ if (props.operationType === "frozen") {
+ return isQualified ? getQualifiedUnLockedStock(props.record) : getUnqualifiedUnLockedStock(props.record);
+ }
+ return isQualified ? getQualifiedLockedStock(props.record) : getUnqualifiedLockedStock(props.record);
+});
-let { proxy } = getCurrentInstance()
+const inputMin = computed(() => (maxCount.value > 0 ? 0.01 : 0));
+
+const targetStockId = computed(() => {
+ if (formState.value.stockType === "unqualified") {
+ return props.record?.unQualifiedId ?? props.record?.unqualifiedId ?? props.record?.id;
+ }
+ return props.record?.qualifiedId ?? props.record?.id;
+});
+
+const initFormData = () => {
+ formState.value.stockType = props.type === "unqualified" ? "unqualified" : "qualified";
+ if (props.operationType === "thaw") {
+ formState.value.lockedQuantity = maxCount.value;
+ } else {
+ formState.value.lockedQuantity = maxCount.value > 0 ? 0.01 : 0;
+ }
+};
+
+watch(
+ () => props.record,
+ () => {
+ initFormData();
+ },
+ { deep: true }
+);
+
+watch(
+ () => props.operationType,
+ () => {
+ initFormData();
+ }
+);
+
+watch(
+ maxCount,
+ (val) => {
+ if (val <= 0) {
+ formState.value.lockedQuantity = 0;
+ return;
+ }
+ if (!formState.value.lockedQuantity || formState.value.lockedQuantity < 0.01) {
+ formState.value.lockedQuantity = 0.01;
+ } else if (formState.value.lockedQuantity > val) {
+ formState.value.lockedQuantity = val;
+ }
+ },
+ { immediate: true }
+);
+
+const { proxy } = getCurrentInstance();
const closeModal = () => {
- // 閲嶇疆琛ㄥ崟鏁版嵁
formState.value = {
- lockedQuantity: undefined
+ stockType: "qualified",
+ lockedQuantity: 0.01,
};
isShow.value = false;
};
-const maxCount = computed(() => {
- // 鍐荤粨搴撳瓨鏈�澶ф暟閲忎负鏈В鍐绘暟閲�
- if (props.operationType === 'frozen') {
- return props.record.unLockedQuantity
- }
- // 瑙e喕搴撳瓨鏈�澶ф暟閲忎负宸插喕缁撴暟閲�
- return props.record.lockedQuantity
-})
-
const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- const data = Object.assign({id: props.record.id}, formState.value);
- if (props.type === 'qualified') {
- // 鍐荤粨
- if (props.operationType === 'frozen') {
- frozenStockInventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- } else {
- thawStockInventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- }
- } else {
- if (props.operationType === 'frozen') {
- frozenStockUninventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- } else {
- thawStockUninventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- }
- }
+ proxy.$refs["formRef"].validate((valid) => {
+ if (!valid) return;
+
+ if (!formState.value.stockType) {
+ proxy.$modal.msgError("璇烽�夋嫨搴撳瓨绫诲瀷");
+ return;
}
- })
+ if (!formState.value.lockedQuantity || formState.value.lockedQuantity <= 0) {
+ proxy.$modal.msgError(props.operationType === "frozen" ? "鍐荤粨鏁伴噺蹇呴』澶т簬0" : "瑙e喕鏁伴噺蹇呴』澶т簬0");
+ return;
+ }
+ if (formState.value.lockedQuantity > maxCount.value) {
+ proxy.$modal.msgError("鎿嶄綔鏁伴噺涓嶈兘瓒呰繃鍙搷浣滃簱瀛�");
+ return;
+ }
+
+ if (!targetStockId.value) {
+ proxy.$modal.msgError("鏈壘鍒板搴斿簱瀛業D锛屾棤娉曟彁浜�");
+ return;
+ }
+
+ const data = Object.assign({ id: targetStockId.value }, formState.value);
+ let submitApi;
+ if (formState.value.stockType === "qualified") {
+ submitApi = props.operationType === "frozen" ? frozenStockInventory : thawStockInventory;
+ } else {
+ submitApi = props.operationType === "frozen" ? frozenStockUninventory : thawStockUninventory;
+ }
+
+ submitApi(data).then((res) => {
+ if (res.code === 200) {
+ isShow.value = false;
+ emit("completed");
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ }
+ });
+ });
};
onMounted(() => {
- formState.value.lockedQuantity = maxCount.value;
-})
+ initFormData();
+});
defineExpose({
closeModal,
diff --git a/src/views/inventoryManagement/stockManagement/Qualified.vue b/src/views/inventoryManagement/stockManagement/Qualified.vue
index fee5e19..34ce8a8 100644
--- a/src/views/inventoryManagement/stockManagement/Qualified.vue
+++ b/src/views/inventoryManagement/stockManagement/Qualified.vue
@@ -66,8 +66,8 @@
<el-table-column fixed="right" label="鎿嶄綔" min-width="90" align="center">
<template #default="scope">
<el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="getQualifiedUnLockedStock(scope.row) <= 0">棰嗙敤</el-button>
- <el-button link type="primary" v-if="getQualifiedUnLockedStock(scope.row) > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
- <el-button link type="primary" v-if="getQualifiedLockedStock(scope.row) > 0" @click="showThawModal(scope.row)">瑙e喕</el-button>
+ <el-button link type="primary" v-if="getQualifiedUnLockedStock(scope.row) > 0 || getUnqualifiedUnLockedStock(scope.row) > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
+ <el-button link type="primary" v-if="getQualifiedLockedStock(scope.row) > 0 || getUnqualifiedLockedStock(scope.row) > 0" @click="showThawModal(scope.row)">瑙e喕</el-button>
</template>
</el-table-column>
</el-table>
@@ -303,6 +303,10 @@
return toNumber(row?.qualifiedUnLockedQuantity ?? row?.unLockedQuantity ?? row?.qualifiedQuantity ?? row?.qualitity)
}
+const getUnqualifiedUnLockedStock = (row) => {
+ return toNumber(row?.unQualifiedUnLockedQuantity ?? row?.unqualifiedUnLockedQuantity ?? row?.unQualifiedQuantity ?? row?.unqualifiedQuantity)
+}
+
// 琛ㄦ牸琛岀被鍚�
const tableRowClassName = ({ row }) => {
const stock = getQualifiedUnLockedStock(row);
diff --git a/src/views/inventoryManagement/stockManagement/Subtract.vue b/src/views/inventoryManagement/stockManagement/Subtract.vue
index a277a00..00e9007 100644
--- a/src/views/inventoryManagement/stockManagement/Subtract.vue
+++ b/src/views/inventoryManagement/stockManagement/Subtract.vue
@@ -1,47 +1,62 @@
<template>
<div>
<el-dialog
- v-model="isShow"
- title="棰嗙敤"
- width="800"
- @close="closeModal"
+ v-model="isShow"
+ title="棰嗙敤"
+ width="800"
+ @close="closeModal"
>
<el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
<el-form-item
- label="浜у搧鍚嶇О"
- prop="productModelId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨浜у搧',
- trigger: 'change',
- }
- ]"
+ label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ }
+ ]"
>
<el-button type="primary" @click="showProductSelectDialog = true" disabled>
{{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
</el-button>
</el-form-item>
- <el-form-item
- label="瑙勬牸"
- prop="productModelName"
- >
- <el-input v-model="formState.model" disabled />
+ <el-form-item label="瑙勬牸" prop="productModelName">
+ <el-input v-model="formState.model" 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="unit"
+ label="搴撳瓨绫诲瀷"
+ prop="stockType"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨搴撳瓨绫诲瀷',
+ trigger: 'change',
+ }
+ ]"
>
- <el-input v-model="formState.unit" disabled />
+ <el-select v-model="formState.stockType" placeholder="璇烽�夋嫨搴撳瓨绫诲瀷" style="width: 100%">
+ <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" :max="maxQuality" style="width: 100%" />
+ <el-form-item label="鏁伴噺" prop="qualitity">
+ <el-input-number
+ v-model="formState.qualitity"
+ :step="0.01"
+ :precision="2"
+ :min="inputMin"
+ :max="maxQuality"
+ style="width: 100%"
+ />
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
@@ -49,11 +64,10 @@
</el-form-item>
</el-form>
- <!-- 浜у搧閫夋嫨寮圭獥 -->
<ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
+ v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single
/>
<template #footer>
<div class="dialog-footer">
@@ -66,10 +80,10 @@
</template>
<script setup>
-import {ref, computed, getCurrentInstance} from "vue";
+import { ref, computed, getCurrentInstance, onMounted, watch } from "vue";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import {subtractStockInventory} from "@/api/inventoryManagement/stockInventory.js";
-import {subtractStockUnInventory} from "@/api/inventoryManagement/stockUninventory.js";
+import { subtractStockInventory } from "@/api/inventoryManagement/stockInventory.js";
+import { subtractStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js";
const props = defineProps({
visible: {
@@ -78,42 +92,72 @@
},
record: {
type: Object,
- default: () => {},
+ default: () => ({}),
},
type: {
type: String,
required: true,
- default: 'qualified',
+ default: "qualified",
},
});
-const emit = defineEmits(['update:visible', 'completed']);
+const emit = defineEmits(["update:visible", "completed"]);
-onMounted(() => {
- initFormData()
-})
+const toNumber = (value) => {
+ const num = Number(value);
+ return Number.isFinite(num) ? num : 0;
+};
-const maxQuality = computed(() => {
- return props.record.unLockedQuantity ? props.record.unLockedQuantity : 0;
-})
+const getQualifiedUnLockedStock = (row) => {
+ return toNumber(
+ row?.qualifiedUnLockedQuantity ??
+ row?.unLockedQuantity ??
+ row?.qualifiedQuantity ??
+ row?.qualitity
+ );
+};
-const initFormData = () => {
- if (props.record) {
- formState.value = {
- ...props.record,
- }
- }
-}
+const getUnqualifiedUnLockedStock = (row) => {
+ return toNumber(
+ row?.unQualifiedUnLockedQuantity ??
+ row?.unqualifiedUnLockedQuantity ??
+ row?.unQualifiedQuantity ??
+ row?.unqualifiedQuantity
+ );
+};
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
const formState = ref({
productId: undefined,
productModelId: undefined,
productName: "",
model: "",
unit: "",
- qualitity: 0,
- remark: '',
+ stockType: "qualified",
+ qualitity: 0.01,
+ remark: "",
+});
+
+const maxQuality = computed(() => {
+ if (formState.value.stockType === "unqualified") {
+ return getUnqualifiedUnLockedStock(props.record);
+ }
+ return getQualifiedUnLockedStock(props.record);
+});
+
+const inputMin = computed(() => (maxQuality.value > 0 ? 0.01 : 0));
+
+const initFormData = () => {
+ if (props.record) {
+ formState.value = {
+ ...props.record,
+ stockType: props.type === "unqualified" ? "unqualified" : "qualified",
+ qualitity: 0.01,
+ };
+ }
+};
+
+onMounted(() => {
+ initFormData();
});
const isShow = computed({
@@ -121,75 +165,97 @@
return props.visible;
},
set(val) {
- emit('update:visible', val);
+ emit("update:visible", val);
},
});
-const showProductSelectDialog = ref(false);
+watch(
+ () => props.record,
+ () => {
+ initFormData();
+ },
+ { deep: true }
+);
-let { proxy } = getCurrentInstance()
+watch(
+ maxQuality,
+ (val) => {
+ if (val <= 0) {
+ formState.value.qualitity = 0;
+ return;
+ }
+ if (!formState.value.qualitity || formState.value.qualitity < 0.01) {
+ formState.value.qualitity = 0.01;
+ } else if (formState.value.qualitity > val) {
+ formState.value.qualitity = val;
+ }
+ },
+ { immediate: true }
+);
+
+const showProductSelectDialog = ref(false);
+const { proxy } = getCurrentInstance();
const closeModal = () => {
- // 閲嶇疆琛ㄥ崟鏁版嵁
formState.value = {
productId: undefined,
productModelId: undefined,
productName: "",
productModelName: "",
- description: '',
+ stockType: "qualified",
+ qualitity: 0.01,
+ description: "",
};
isShow.value = false;
};
-// 浜у搧閫夋嫨澶勭悊
const handleProductSelect = async (products) => {
if (products && products.length > 0) {
const product = products[0];
- console.log(product)
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;
showProductSelectDialog.value = false;
- // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
- proxy.$refs["formRef"]?.validateField('productModelId');
+ proxy.$refs["formRef"]?.validateField("productModelId");
}
};
const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰瑙勬牸
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨浜у搧");
- return;
- }
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨瑙勬牸");
- return;
- }
- if (props.type === 'qualified') {
- subtractStockInventory(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- } else {
- subtractStockUnInventory(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- }
- }
- })
-};
+ proxy.$refs["formRef"].validate((valid) => {
+ if (!valid) return;
+ if (!formState.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
+ }
+ if (!formState.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨瑙勬牸");
+ return;
+ }
+ if (!formState.value.stockType) {
+ proxy.$modal.msgError("璇烽�夋嫨搴撳瓨绫诲瀷");
+ return;
+ }
+ if (!formState.value.qualitity || formState.value.qualitity <= 0) {
+ proxy.$modal.msgError("棰嗙敤鏁伴噺蹇呴』澶т簬0");
+ return;
+ }
+ if (formState.value.qualitity > maxQuality.value) {
+ proxy.$modal.msgError("棰嗙敤鏁伴噺涓嶈兘瓒呰繃鍙敤搴撳瓨");
+ return;
+ }
+
+ const submitApi =
+ formState.value.stockType === "unqualified" ? subtractStockUnInventory : subtractStockInventory;
+ submitApi(formState.value).then(() => {
+ isShow.value = false;
+ emit("completed");
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ });
+ });
+};
defineExpose({
closeModal,
--
Gitblit v1.9.3