feat: 新增物料管理看板功能及多项优化

新增物料管理看板功能,包含统计卡片和图表展示
优化物料选择器组件,支持分页和搜索功能
重构物料详情展示组件,支持动态加载数据
添加多个ECharts图表组件用于数据可视化
完善出入库和采购单相关功能,增加在途数量显示
修复若干界面显示问题和交互逻辑
This commit is contained in:
砂糖
2026-01-31 14:21:49 +08:00
parent 48e75676c5
commit 42f6f83c3a
17 changed files with 1278 additions and 115 deletions

View File

@@ -0,0 +1,107 @@
<template>
<div @click="open = true" style="cursor: pointer;">
<!-- 触发区插槽默认展示选择按钮/已选物料信息 -->
<slot name="trigger">
<el-button v-if="!materialId" type="primary" size="small">选择配料</el-button>
<el-tag v-else type="info" closable @close="handleClear">
{{ currentMaterial.materialName }}({{ currentMaterial.spec }})[{{ currentMaterial.model }}] - {{
currentMaterial.factory }}库存{{ currentMaterial.currentStock }}{{ currentMaterial.unit }}
</el-tag>
</slot>
</div>
<!-- 选择弹窗表格+分页+底部按钮 -->
<el-dialog title="选择配料" v-model="open" width="800px" destroy-on-close>
<el-table :data="list" style="width: 100%" border stripe @row-click="handleRowSelect" highlight-current-row
row-key="materialId" :current-row-key="materialId">
<el-table-column prop="materialName" label="配料名称" min-width="120" align="center" />
<el-table-column prop="spec" label="配料规格" min-width="100" align="center" />
<el-table-column prop="model" label="配料型号" min-width="100" align="center" />
<el-table-column prop="factory" label="生产厂家" min-width="120" align="center" />
<el-table-column prop="currentStock" label="现存库存" min-width="80" align="center" />
<el-table-column prop="unit" label="计量单位" width="80" align="center" />
</el-table>
<!-- 分页组件 -->
<div style="margin: 15px 0; text-align: right; width: 100%">
<el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :total="total"
:page-sizes="[5, 10, 20, 50]" layout="prev, pager, next, jumper, ->, total, sizes"
@size-change="fetchMaterialList" @current-change="fetchMaterialList" small />
</div>
<template #footer>
<el-button @click="open = false">取消</el-button>
</template>
</el-dialog>
</template>
<script setup name="RawSelector">
import { ref, computed, watch, onMounted } from 'vue';
import { listMaterial, getMaterial } from '@/api/mat/material';
import { ElMessage } from 'element-plus';
// 双向绑定物料ID
const materialId = defineModel({
type: String,
default: ""
})
// 计算当前选中的物料信息
const currentMaterial = computed(() => {
if (!materialId.value) return {};
return list.value.find(item => item.materialId === materialId.value) || {};
});
// 定义事件
const emit = defineEmits(['change']);
// 基础响应式数据
const list = ref([]); // 物料列表
const open = ref(false); // 弹窗显隐
// 分页响应式数据(核心新增)
const pageNum = ref(1); // 当前页码
const pageSize = ref(10); // 每页条数
const total = ref(0); // 总数据条数
// 组件挂载加载列表
onMounted(async () => {
await fetchMaterialList();
});
// 加载物料列表(适配分页参数)
async function fetchMaterialList() {
try {
const res = await listMaterial({ pageNum: pageNum.value, pageSize: pageSize.value });
list.value = res.rows;
total.value = res.total; // 赋值总条数供分页使用
// 分页查询后检查是否存在当前选中的物料ID
const isExist = res.rows.some(item => item.materialId === materialId.value);
if (!isExist) {
console.log('获取物料详情:', materialId.value);
if (!materialId.value) return;
const res = await getMaterial(materialId.value);
list.value.push(res.data);
}
} catch (err) {
console.error('加载物料列表失败:', err);
ElMessage.error('配料列表加载失败,请刷新重试');
}
}
// 表格行选择物料
function handleRowSelect(row) {
if (row.materialId === materialId.value) return;
materialId.value = row.materialId;
emit('change', row);
open.value = false;
}
// 清空已选物料
function handleClear() {
materialId.value = '';
emit('change', {});
ElMessage.info('已清空配料选择');
}
</script>