<template>
|
<el-dialog v-model="visible"
|
title="选择产品"
|
width="1000px"
|
destroy-on-close
|
:close-on-click-modal="false">
|
<el-form :inline="true"
|
:model="query"
|
class="mb-2 search-form">
|
<el-form-item label="产品名称">
|
<el-input v-model="query.productName"
|
size="small"
|
placeholder="输入产品名称"
|
clearable
|
@keyup.enter="onSearch" />
|
</el-form-item>
|
<el-form-item label="规格">
|
<el-input v-model="query.model"
|
size="small"
|
placeholder="输入规格"
|
clearable
|
@keyup.enter="onSearch" />
|
</el-form-item>
|
<el-form-item label="物料编码">
|
<el-input v-model="query.materialCode"
|
size="small"
|
placeholder="输入物料编码"
|
clearable
|
@keyup.enter="onSearch" />
|
</el-form-item>
|
<el-form-item style="200px">
|
<el-button type="primary"
|
size="small"
|
@click="onSearch">搜索</el-button>
|
<el-button size="small"
|
@click="onReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
<!-- 列表 -->
|
<el-table ref="tableRef"
|
v-loading="loading"
|
:data="tableData"
|
height="420"
|
highlight-current-row
|
row-key="id"
|
@selection-change="handleSelectionChange"
|
@select="handleSelect">
|
<el-table-column type="selection"
|
width="55" />
|
<el-table-column type="index"
|
label="序号"
|
width="60" />
|
<el-table-column prop="productName"
|
label="产品名称"
|
min-width="160" />
|
<el-table-column prop="materialCode"
|
label="物料编码"
|
min-width="200" />
|
<el-table-column prop="model"
|
label="规格"
|
min-width="200" />
|
<el-table-column prop="unit"
|
label="单位"
|
min-width="160" />
|
</el-table>
|
<div class="mt-3 flex justify-end">
|
<el-pagination background
|
layout="total, sizes, prev, pager, next, jumper"
|
:total="total"
|
v-model:page-size="page.pageSize"
|
v-model:current-page="page.pageNum"
|
:page-sizes="[10, 20, 50, 100]"
|
@size-change="onPageChange"
|
@current-change="onPageChange" />
|
</div>
|
<template #footer>
|
<el-button @click="close()">取消</el-button>
|
<el-button type="primary"
|
:disabled="multipleSelection.length === 0"
|
@click="onConfirm">
|
确定
|
</el-button>
|
</template>
|
</el-dialog>
|
</template>
|
|
<script setup lang="ts">
|
import { computed, onMounted, reactive, ref, watch, nextTick } from "vue";
|
import { ElMessage } from "element-plus";
|
import { modelListPage } from "@/api/basicData/newProduct";
|
|
export type ProductRow = {
|
id: number;
|
model: string;
|
materialCode: string;
|
unit?: string;
|
productName?: string;
|
};
|
|
const props = defineProps<{
|
modelValue: boolean;
|
single?: boolean; // 是否只能选择一个,默认false(可选择多个)
|
}>();
|
|
const emit = defineEmits(["update:modelValue", "confirm"]);
|
|
const visible = computed({
|
get: () => props.modelValue,
|
set: v => emit("update:modelValue", v),
|
});
|
|
const query = reactive({
|
model: "",
|
materialCode: "",
|
productName: "",
|
});
|
|
const page = reactive({
|
pageNum: 1,
|
pageSize: 10,
|
});
|
|
const loading = ref(false);
|
const tableData = ref<ProductRow[]>([]);
|
const total = ref(0);
|
const multipleSelection = ref<ProductRow[]>([]);
|
const tableRef = ref();
|
|
function close() {
|
visible.value = false;
|
}
|
|
const handleSelectionChange = (val: ProductRow[]) => {
|
if (props.single && val.length > 1) {
|
// 如果限制为单个选择,只保留最后一个选中的
|
const lastSelected = val[val.length - 1];
|
multipleSelection.value = [lastSelected];
|
// 清空表格选中状态,然后重新选中最后一个
|
nextTick(() => {
|
if (tableRef.value) {
|
tableRef.value.clearSelection();
|
tableRef.value.toggleRowSelection(lastSelected, true);
|
}
|
});
|
} else {
|
multipleSelection.value = val;
|
}
|
};
|
|
// 处理单个选择
|
const handleSelect = (selection: ProductRow[], row: ProductRow) => {
|
if (props.single) {
|
// 如果限制为单个,清空其他选择,只保留当前行
|
if (selection.includes(row)) {
|
// 选中当前行时,清空其他选中
|
multipleSelection.value = [row];
|
nextTick(() => {
|
if (tableRef.value) {
|
tableData.value.forEach(item => {
|
if (item.id !== row.id) {
|
tableRef.value.toggleRowSelection(item, false);
|
}
|
});
|
}
|
});
|
}
|
}
|
};
|
|
function onSearch() {
|
page.pageNum = 1;
|
loadData();
|
}
|
|
function onReset() {
|
query.model = "";
|
query.materialCode = "";
|
query.productName = "";
|
page.pageNum = 1;
|
loadData();
|
}
|
|
function onPageChange() {
|
loadData();
|
}
|
|
function onConfirm() {
|
if (multipleSelection.value.length === 0) {
|
ElMessage.warning("请选择一条产品");
|
return;
|
}
|
if (props.single && multipleSelection.value.length > 1) {
|
ElMessage.warning("只能选择一个产品");
|
return;
|
}
|
emit(
|
"confirm",
|
props.single ? [multipleSelection.value[0]] : multipleSelection.value
|
);
|
close();
|
}
|
|
async function loadData() {
|
loading.value = true;
|
try {
|
multipleSelection.value = []; // 翻页/搜索后清空选择更符合预期
|
const res: any = await modelListPage({
|
model: query.model.trim(),
|
materialCode: query.materialCode.trim(),
|
productName: query.productName.trim(),
|
type: 1,
|
current: page.pageNum,
|
size: page.pageSize,
|
});
|
tableData.value = res.data.records;
|
total.value = res.data.total;
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
// 监听弹窗打开,重置选择
|
watch(
|
() => props.modelValue,
|
visible => {
|
if (visible) {
|
multipleSelection.value = [];
|
}
|
}
|
);
|
|
onMounted(() => {
|
loadData();
|
});
|
</script>
|
|
<style scoped>
|
.search-form {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
margin-bottom: 10px;
|
}
|
|
.search-form .el-form-item {
|
margin-bottom: 0;
|
}
|
|
.search-form .el-input {
|
width: 180px;
|
}
|
.el-form--inline .el-form-item {
|
margin-right: 5px;
|
}
|
.justify-end {
|
margin-top: 10px;
|
}
|
</style>
|