Files
klp-oa/klp-ui/src/components/CoilSelector/index.vue
砂糖 2d30a2f3fb feat(发货单): 增加发货单钢卷选择范围限制功能
- 在CoilSelector组件中新增rangeMode和rangeData属性,支持传入可选钢卷列表
- 发货单明细表增加对可选钢卷列表的支持,并在增删改时刷新列表
- 发货单打印时自动填充取货地点为实际库位前三位
- 调整操作列固定显示在表格右侧
2025-12-09 14:37:46 +08:00

399 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 v-if="!rangeMode" :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-if="!rangeMode" 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
},
rangeMode: {
type: Boolean,
default: false
},
// 返回选择模式不再通过list借口获取而是传入可以选择的钢卷数据
rangeData: {
type: Array,
default: () => []
}
},
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() {
// 如果是范围模式,直接使用传入数据
if (this.rangeMode) {
this.coilList = this.rangeData || [];
this.total = this.coilList.length;
return;
}
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>