调整库存按钮

This commit is contained in:
2025-11-27 17:44:16 +08:00
parent 6507b3ee14
commit 9af7e0d005
3 changed files with 195 additions and 1 deletions

View File

@@ -0,0 +1,154 @@
<template>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="400px"
:close-on-click-modal="false"
@close="handleClose"
>
<el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
<el-form-item label="原料名称">
<el-input v-model="rawMaterial.raw_material_name" disabled></el-input>
</el-form-item>
<el-form-item label="操作类型">
<el-radio-group v-model="form.operationType">
<el-radio label="in">存入</el-radio>
<el-radio label="out">取出</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="变动数量" prop="change_amount">
<el-input-number
v-model="form.change_amount"
:min="1"
:precision="0"
:step="1000"
controls-position="right"
style="width: 100%;"
></el-input-number>
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" type="textarea" :rows="2"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleSubmit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { ref, reactive, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { InventoryApi } from '../../api/inventory';
export default {
name: 'StockAdjustmentDialog',
props: {
visible: {
type: Boolean,
default: false,
},
rawMaterial: {
type: Object,
default: () => ({}),
},
operationType: {
type: String,
default: 'in', // 'in' or 'out'
},
},
emits: ['update:visible', 'success'],
setup(props, { emit }) {
const formRef = ref(null);
const dialogVisible = computed({
get: () => props.visible,
set: (val) => emit('update:visible', val),
});
const form = reactive({
operationType: props.operationType,
change_amount: 1000,
remarks: '',
});
const dialogTitle = computed(() => {
return form.operationType === 'in' ? '存入库存' : '取出库存';
});
watch(() => props.operationType, (newType) => {
form.operationType = newType;
});
watch(() => props.visible, (newVal) => {
if (newVal) {
// 弹窗打开时重置表单
form.change_amount = 1000;
form.remarks = '';
form.operationType = props.operationType;
formRef.value?.clearValidate();
}
});
const rules = {
change_amount: [
{ required: true, message: '请输入变动数量', trigger: 'blur' },
{ type: 'number', message: '数量必须为数字', trigger: 'blur' },
{ min: 1, message: '数量必须大于0', trigger: 'blur' },
],
};
const handleSubmit = async () => {
try {
await formRef.value.validate();
let finalChangeAmount = form.change_amount;
if (form.operationType === 'out') {
finalChangeAmount = -finalChangeAmount;
// 检查是否超出库存
if (props.rawMaterial.stock + finalChangeAmount < 0) {
ElMessage.error('取出数量不能大于当前库存!');
return;
}
}
const data = {
raw_material_id: props.rawMaterial.raw_material_id,
change_amount: finalChangeAmount,
remarks: form.remarks,
};
await InventoryApi.adjustStock(data);
ElMessage.success(`${form.operationType === 'in' ? '存入' : '取出'}成功!`);
emit('success');
dialogVisible.value = false;
} catch (error) {
if (error !== false) { // 阻止表单验证失败时的错误提示
ElMessage.error('操作失败: ' + (error.message || '未知错误'));
}
}
};
const handleClose = () => {
dialogVisible.value = false;
formRef.value?.resetFields();
};
return {
formRef,
dialogVisible,
dialogTitle,
form,
rules,
handleSubmit,
handleClose,
};
},
};
</script>
<style scoped>
/* 可以添加一些样式 */
</style>

View File

@@ -8,6 +8,11 @@
{{ formatRFC3339(scope.row.last_updated) }}
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="scope">
<el-button size="small" type="primary" @click="handleAdjust(scope.row)">调整库存</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@@ -39,7 +44,8 @@ export default {
default: '',
},
},
setup(props, { expose }) {
emits: ['adjust-stock'], // 声明组件将发出的事件
setup(props, { expose, emit }) { // 接收 emit 函数
const stockList = ref([]);
const loading = ref(false);
const pagination = ref({
@@ -81,6 +87,11 @@ export default {
fetchStockList();
};
// 处理库存调整操作
const handleAdjust = (row) => {
emit('adjust-stock', row); // 只传递行数据
};
onMounted(() => {
fetchStockList();
});
@@ -107,6 +118,7 @@ export default {
handleSizeChange,
handleCurrentChange,
formatRFC3339,
handleAdjust, // 暴露给模板
};
},
};

View File

@@ -28,8 +28,16 @@
ref="stockListTableRef"
:stockFilter="stockFilter"
:searchRawMaterialName="searchRawMaterialName"
@adjust-stock="handleAdjustStock"
></stock-list-table>
</el-card>
<!-- 库存调整弹窗 -->
<stock-adjustment-dialog
v-model:visible="showAdjustmentDialog"
:rawMaterial="currentRawMaterialForAdjustment"
@success="refreshList"
></stock-adjustment-dialog>
</div>
</template>
@@ -37,29 +45,49 @@
import { ref } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import StockListTable from '../../components/inventory/StockListTable.vue';
import StockAdjustmentDialog from '../../components/inventory/StockAdjustmentDialog.vue'; // 导入库存调整弹窗组件
export default {
name: 'StockManagement',
components: {
StockListTable,
Refresh,
StockAdjustmentDialog, // 注册组件
},
setup() {
const stockListTableRef = ref(null);
const stockFilter = ref('all'); // 默认显示所有原料
const searchRawMaterialName = ref(''); // 搜索原料名称
// 库存调整弹窗相关
const showAdjustmentDialog = ref(false);
const currentRawMaterialForAdjustment = ref(null);
// currentOperationType 不再需要在这里管理,由 StockAdjustmentDialog 内部管理
const refreshList = () => {
if (stockListTableRef.value) {
stockListTableRef.value.fetchStockList(stockFilter.value, searchRawMaterialName.value);
}
};
/**
* 处理库存调整操作
* @param {object} rawMaterial - 当前操作的原料数据
*/
const handleAdjustStock = (rawMaterial) => {
currentRawMaterialForAdjustment.value = { ...rawMaterial };
showAdjustmentDialog.value = true;
};
return {
stockListTableRef,
stockFilter,
searchRawMaterialName,
refreshList,
// 库存调整弹窗相关
showAdjustmentDialog,
currentRawMaterialForAdjustment,
handleAdjustStock,
};
},
};