Files
klp-oa/klp-ui/src/components/CoilSelector/index.vue
砂糖 40452d513e feat(发货计划): 新增钢卷选择功能并优化界面布局
- 在发货计划页面添加钢卷选择器组件,支持从列表中选择钢卷
- 优化发货计划卡片布局,增加审批状态显示
- 新增钢卷列表查询API接口
- 调整分页大小和查询条件
- 重构CoilSelector组件,增加更多钢卷信息展示
- 添加钢卷转移组件框架
2025-12-08 15:17:56 +08:00

384 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="coil-selector-container">
<div v-if="useTrigger" class="trigger-container">
<!-- 选择按钮 -->
<slot>
<el-button type="primary" size="small" @click="handleOpen" class="select-button">
<i class="el-icon-search"></i>
<span v-if="selectedCoil">
<span>{{ selectedCoil.currentCoilNo }}</span>
<span>({{ selectedCoil.itemName }})</span>
<span>[{{ selectedCoil.netWeight }}t]</span>
</span>
<span v-else>{{ placeholder }}</span>
</el-button>
</slot>
</div>
<el-dialog title="选择钢卷" :visible.sync="dialogVisible" width="900px" :close-on-click-modal="false"
@close="handleClose" append-to-body>
<!-- 搜索区域 -->
<el-form :inline="true" :model="queryParams" class="search-form">
<el-form-item label="卷号">
<el-input v-model="queryParams.currentCoilNo" placeholder="请输入卷号" clearable size="small"
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="钢种">
<el-input v-model="queryParams.grade" placeholder="请输入钢种" clearable size="small"
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table v-loading="loading" :data="coilList" @row-click="handleRowClick" highlight-current-row height="400px"
style="width: 100%">
<el-table-column label="卷号" align="center" prop="currentCoilNo" :show-overflow-tooltip="true" />
<el-table-column label="存储位置" align="center" prop="actualWarehouseName" width="120" :show-overflow-tooltip="true" />
<el-table-column label="物料" align="center" prop="itemName" width="100" />
<el-table-column label="规格" align="center" prop="specification" width="100" />
<el-table-column label="材质" align="center" prop="material" width="100" />
<el-table-column label="厂家" align="center" prop="manufacturer" width="100" />
<el-table-column label="重量(t)" align="center" prop="netWeight" width="100" />
<el-table-column label="库区" align="center" prop="warehouseName" width="120" :show-overflow-tooltip="true" />
</el-table>
<!-- 分页 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listMaterialCoil } from '@/api/wms/coil';
export default {
name: 'CoilSelector',
props: {
// 非触发器模式下,外部控制显隐(触发器模式下无效)
visible: {
type: Boolean,
default: false
},
// 过滤条件(可以预设一些查询条件)
filters: {
type: Object,
default: () => ({})
},
placeholder: {
type: String,
default: '请选择钢卷'
},
value: {
type: [String, Number],
default: ''
},
// 是否使用内部触发器(按钮)
useTrigger: {
type: Boolean,
default: true
},
// 初始选中的钢卷数据(支持外部传入已选数据)
initialCoil: {
type: Object,
default: null
},
},
data() {
return {
loading: false,
coilList: [],
total: 0,
// 内部显隐控制变量(触发器模式下使用)
innerVisible: false,
// 选中的钢卷数据
selectedCoil: null,
queryParams: {
pageNum: 1,
pageSize: 10,
currentCoilNo: null,
grade: null,
dataType: 1 // 只查询当前数据,不查询历史数据
}
};
},
computed: {
// 根据模式决定对话框显隐逻辑
dialogVisible: {
get() {
// 触发器模式:使用内部变量
if (this.useTrigger) {
return this.innerVisible;
}
// 非触发器模式使用外部传入的visible属性
return this.visible;
},
set(val) {
if (this.useTrigger) {
// 触发器模式:更新内部变量
this.innerVisible = val;
} else {
// 非触发器模式:通知父组件更新
this.$emit('update:visible', val);
}
}
}
},
watch: {
// 监听对话框显隐状态变化,触发数据加载
dialogVisible(val) {
if (val) {
this.resetQuery();
this.getList();
}
},
// 非触发器模式下监听外部visible属性变化
visible(val) {
if (!this.useTrigger && val !== this.dialogVisible) {
this.dialogVisible = val;
}
},
// 监听初始钢卷数据变化
initialCoil(val) {
if (val && typeof val === 'object') {
this.selectedCoil = val;
// 同步到v-model
if (this.useTrigger && val.coilId) {
this.$emit('input', val.coilId);
this.$emit('change', val.coilId);
}
}
},
// 监听v-model值变化外部修改时同步
value(val) {
if (!val) {
this.handleClearSelection();
return;
}
if (val && !this.selectedCoil?.coilId) {
// 如果传入了coilId但还没有选中数据尝试通过id匹配可选功能
this.matchCoilById(val);
}
}
},
created() {
// 初始化时如果有初始钢卷数据,设置选中状态
if (this.initialCoil) {
this.selectedCoil = this.initialCoil;
}
},
methods: {
// 获取钢卷列表
async getList() {
try {
this.loading = true;
const params = { ...this.queryParams, ...this.filters };
const response = await listMaterialCoil(params);
if (response.code === 200) {
this.coilList = response.rows || [];
this.total = response.total || 0;
// 如果有初始coilId尝试匹配数据
if (this.value && !this.selectedCoil) {
this.matchCoilById(this.value);
}
} else {
this.$message.warning(`获取钢卷列表失败:${response.msg || '未知错误'}`);
}
} catch (error) {
console.error('获取钢卷列表异常', error);
this.$message.error('获取钢卷列表失败,请重试');
} finally {
this.loading = false;
}
},
// 根据coilId匹配钢卷数据
matchCoilById(coilId) {
const matchedCoil = this.coilList.find(item => item.coilId == coilId);
if (matchedCoil) {
this.selectedCoil = matchedCoil;
}
},
// 触发器模式:打开对话框
handleOpen() {
this.innerVisible = true;
},
// 搜索
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
// 重置搜索条件
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
currentCoilNo: null,
grade: null,
dataType: 1
};
this.getList();
},
// 点击表格行选择
handleRowClick(row) {
this.handleSelect(row);
},
// 选择钢卷(确认选择)
handleSelect(row) {
if (!row) {
this.$message.warning('请选择有效的钢卷数据');
return;
}
// 存储选中的钢卷数据
this.selectedCoil = row;
// 触发自定义事件,通知父组件选中结果(返回完整行数据)
this.$emit('select', row);
// 触发器模式下支持v-model双向绑定
if (this.useTrigger) {
this.$emit('input', row.coilId);
this.$emit('change', row.coilId); // 兼容v-model的change事件
}
// 选择后关闭对话框
this.handleClose();
},
// 清除选中状态
handleClearSelection() {
this.selectedCoil = null;
this.$emit('input', '');
this.$emit('change', '');
this.$emit('clear', true); // 触发清除事件
},
// 关闭对话框
handleClose() {
this.dialogVisible = false;
// 触发关闭事件,通知父组件
this.$emit('close');
}
}
};
</script>
<style scoped lang="scss">
.coil-selector-container {
width: 100%;
}
.trigger-container {
display: flex;
flex-direction: column;
gap: 8px;
}
// 未选择状态样式
.no-selection {
padding: 8px 12px;
border: 1px dashed #dcdcdc;
border-radius: 4px;
color: #999;
background-color: #f9f9f9;
width: fit-content;
}
// 已选择状态样式
.selected-coil-info {
padding: 12px;
border: 1px solid #e6f7ff;
border-radius: 6px;
background-color: #f0f9ff;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px 24px;
width: fit-content;
max-width: 100%;
.info-item {
display: flex;
align-items: center;
gap: 6px;
.label {
color: #666;
font-size: 13px;
}
.value {
color: #333;
font-size: 14px;
font-weight: 500;
white-space: nowrap;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
}
}
.clear-selection {
color: #f56c6c;
margin-left: 12px;
padding: 0 8px;
&:hover {
color: #ff4d4f;
background-color: transparent;
}
}
}
// 选择按钮样式
.select-button {
margin-top: 4px;
}
.search-form {
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 16px;
}
::v-deep .el-dialog__body {
padding: 20px;
max-height: calc(100vh - 200px);
overflow-y: auto;
}
::v-deep .el-table {
--el-table-row-hover-bg-color: var(--el-color-primary-light-9);
}
::v-deep .el-table__row.current-row {
background-color: var(--el-color-primary-light-8) !important;
}
.dialog-footer {
text-align: right;
}
// 响应式调整
@media (max-width: 768px) {
.selected-coil-info {
gap: 12px;
padding: 10px;
}
.info-item {
flex: 1 1 calc(50% - 12px);
}
}
</style>