admin-vue3/src/views/mes/md/workstation/components/MdWorkstationSelectDialog.vue

281 lines
8.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
MES 工作站弹窗选择器支持单选/多选
搜索字段工作站编码所属工序所在车间对齐 KTG simpletableSingle.vue
表格列工作站编码工作站名称工作站地点所在车间所属工序备注
Props:
multiple true 多选checkboxfalse 单选radio默认 true
Events:
selected(rows: MdWorkstationVO[]) 确认选择后触发单选时数组长度为 1
Expose:
open(selectedIds?: number[]) 打开弹窗可传入已选 ID 用于预选高亮
-->
<template>
<Dialog title="工作站选择" v-model="dialogVisible" width="80%">
<!-- 搜索 -->
<ContentWrap>
<el-form :inline="true" :model="queryParams" label-width="85px">
<el-form-item label="工作站编码">
<el-input
v-model="queryParams.code"
placeholder="请输入工作站编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="所属工序">
<ProProcessSelect
v-model="queryParams.processId"
placeholder="请选择工序"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="所在车间">
<MdWorkshopSelect
v-model="queryParams.workshopId"
placeholder="请选择车间"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
ref="tableRef"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:highlight-current-row="!multiple"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
@row-dblclick="handleRowDblClick"
>
<!-- 多选checkboxreserve-selection 保证跨页勾选不丢失) -->
<el-table-column
v-if="multiple"
type="selection"
:reserve-selection="true"
width="50"
align="center"
/>
<!-- 单选radio -->
<el-table-column v-else width="50" align="center">
<template #default="{ row }">
<el-radio
v-model="selectedRadioId"
:value="row.id"
class="radio-no-label"
@change="handleRadioChange(row)"
/>
</template>
</el-table-column>
<el-table-column label="工作站编码" align="center" prop="code" width="140" />
<el-table-column label="工作站名称" align="center" prop="name" min-width="160" />
<el-table-column label="工作站地点" align="center" prop="address" min-width="140" />
<el-table-column label="所在车间" align="center" prop="workshopName" width="120" />
<el-table-column label="所属工序" align="center" prop="processName" width="120" />
<el-table-column label="备注" align="center" prop="remark" min-width="120" />
</el-table>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<template #footer>
<el-button type="primary" @click="confirmSelect">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { MdWorkstationApi, MdWorkstationVO } from '@/api/mes/md/workstation'
import { CommonStatusEnum } from '@/utils/constants'
import ProProcessSelect from '@/views/mes/pro/process/components/ProProcessSelect.vue'
import MdWorkshopSelect from '@/views/mes/md/workstation/components/MdWorkshopSelect.vue'
defineOptions({ name: 'MdWorkstationSelectDialog' })
const props = withDefaults(
defineProps<{
multiple?: boolean // true checkboxfalse radio
}>(),
{
multiple: true
}
)
const message = useMessage()
const emit = defineEmits<{
selected: [rows: MdWorkstationVO[]]
}>()
const dialogVisible = ref(false) // 弹窗是否展示
const loading = ref(false) // 列表加载中
const list = ref<MdWorkstationVO[]>([]) // 工作站列表
const total = ref(0) // 总条数
// ==================== 选中状态 ====================
const tableRef = ref() // 表格 Ref
const selectedRows = ref<MdWorkstationVO[]>([]) // 多选模式:选中行
const selectedRadioId = ref<number>() // 单选模式:选中 ID
const currentRadioRow = ref<MdWorkstationVO>() // 单选模式:选中行对象
const preSelectedIds = ref<number[]>([]) // 打开弹窗时传入的已选 ID
/** 多选checkbox 变化 */
const handleSelectionChange = (rows: MdWorkstationVO[]) => {
if (props.multiple) {
selectedRows.value = rows
}
}
/** 单选radio 变化 */
const handleRadioChange = (row: MdWorkstationVO) => {
currentRadioRow.value = row
}
/** 单击行:单选模式下点击整行即选中(降低操作成本),多选不处理(避免和 dblclick 冲突) */
const handleRowClick = (row: MdWorkstationVO) => {
if (props.multiple) {
return
}
selectedRadioId.value = row.id
currentRadioRow.value = row
}
/** 双击行:多选模式切换勾选,单选模式直接确认 */
const handleRowDblClick = (row: MdWorkstationVO) => {
if (props.multiple) {
tableRef.value?.toggleRowSelection(row)
return
}
selectedRadioId.value = row.id
currentRadioRow.value = row
confirmSelect()
}
// ==================== 工作站查询 ====================
const queryParams = reactive({
pageNo: 1, // 页码
pageSize: 10, // 每页条数
code: undefined as string | undefined, // 工作站编码
processId: undefined as number | undefined, // 工序编号
workshopId: undefined as number | undefined, // 车间编号
status: CommonStatusEnum.ENABLE as number | undefined // 状态:默认只查启用
})
/** 查询工作站列表 */
const getList = async () => {
loading.value = true
try {
const data = await MdWorkstationApi.getWorkstationPage(queryParams)
list.value = data.list
total.value = data.total
await nextTick()
applyPreSelection()
} finally {
loading.value = false
}
}
/** 恢复预选状态(当前页可见范围内) */
const applyPreSelection = () => {
if (preSelectedIds.value.length === 0) {
return
}
if (props.multiple) {
const table = tableRef.value
if (!table) {
return
}
list.value.forEach((row) => {
if (preSelectedIds.value.includes(row.id)) {
table.toggleRowSelection(row, true)
}
})
} else {
const match = list.value.find((row) => preSelectedIds.value.includes(row.id))
if (match) {
selectedRadioId.value = match.id
currentRadioRow.value = match
}
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置查询条件 */
const resetQuery = () => {
queryParams.code = undefined
queryParams.processId = undefined
queryParams.workshopId = undefined
queryParams.status = CommonStatusEnum.ENABLE
handleQuery()
}
/** 确认选择 */
const confirmSelect = () => {
if (props.multiple) {
if (selectedRows.value.length === 0) {
message.warning('请至少选择一条数据')
return
}
emit('selected', selectedRows.value)
} else {
if (!currentRadioRow.value) {
message.warning('请选择一条数据')
return
}
emit('selected', [currentRadioRow.value])
}
dialogVisible.value = false
}
// ==================== 打开弹窗 ====================
/** 打开弹窗,可传入已选 ID 用于预选高亮 */
const open = async (selectedIds?: number[]) => {
dialogVisible.value = true
// 重置查询条件 + 页码,避免二次打开继承上次过滤上下文
queryParams.code = undefined
queryParams.processId = undefined
queryParams.workshopId = undefined
queryParams.status = CommonStatusEnum.ENABLE
queryParams.pageNo = 1
// 清空上一次的选中状态
selectedRows.value = []
selectedRadioId.value = undefined
currentRadioRow.value = undefined
preSelectedIds.value = selectedIds ?? []
// 多选模式清空跨页缓存的勾选
await nextTick()
tableRef.value?.clearSelection()
await getList()
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
/* 隐藏 radio 的 label 文字,只保留圆圈 */
.radio-no-label {
:deep(.el-radio__label) {
display: none;
}
}
</style>