diff --git a/apps/web-antd/src/views/mes/md/workstation/components/select-dialog.vue b/apps/web-antd/src/views/mes/md/workstation/components/select-dialog.vue index 82a8c7279..7e95e7660 100644 --- a/apps/web-antd/src/views/mes/md/workstation/components/select-dialog.vue +++ b/apps/web-antd/src/views/mes/md/workstation/components/select-dialog.vue @@ -30,69 +30,80 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(true); // 是否多选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选工作站列表 const preSelectedIds = ref([]); // 预选工作站编号列表 -/** 单选模式下同步 VXE 勾选状态 */ -async function syncSingleSelection(row?: MesMdWorkstationApi.Workstation) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesMdWorkstationApi.Workstation[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesMdWorkstationApi.Workstation) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesMdWorkstationApi.Workstation) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesMdWorkstationApi.Workstation[]; - row?: MesMdWorkstationApi.Workstation; + row: MesMdWorkstationApi.Workstation; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesMdWorkstationApi.Workstation[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选工作站 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesMdWorkstationApi.Workstation[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -101,7 +112,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useWorkstationSelectGridFormSchema(), }, gridOptions: { - columns: useWorkstationSelectGridColumns(), + columns: useWorkstationSelectGridColumns(true), height: 520, keepSource: true, checkboxConfig: { @@ -109,6 +120,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -131,8 +146,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesMdWorkstationApi.Workstation }) => { + handleRadioChange(row); + }, }, }); @@ -140,6 +159,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); if (props.processId) { await gridApi.formApi.setFieldValue('processId', props.processId); @@ -155,10 +176,13 @@ async function openModal( multiple.value = options?.multiple ?? true; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useWorkstationSelectGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭工作站选择弹窗 */ diff --git a/apps/web-antd/src/views/mes/md/workstation/components/select.vue b/apps/web-antd/src/views/mes/md/workstation/components/select.vue index 7d5750665..e9d7eabb4 100644 --- a/apps/web-antd/src/views/mes/md/workstation/components/select.vue +++ b/apps/web-antd/src/views/mes/md/workstation/components/select.vue @@ -44,6 +44,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antd/src/views/mes/md/workstation/data.ts b/apps/web-antd/src/views/mes/md/workstation/data.ts index e6bf40612..ac84864c8 100644 --- a/apps/web-antd/src/views/mes/md/workstation/data.ts +++ b/apps/web-antd/src/views/mes/md/workstation/data.ts @@ -320,9 +320,11 @@ export function useWorkstationSelectGridFormSchema(): VbenFormSchema[] { } /** 工作站选择弹窗的字段 */ -export function useWorkstationSelectGridColumns(): VxeTableGridOptions['columns'] { +export function useWorkstationSelectGridColumns( + multiple = true, +): VxeTableGridOptions['columns'] { return [ - { type: 'checkbox', width: 50 }, + { type: multiple ? 'checkbox' : 'radio', width: 50 }, { field: 'code', title: '工作站编码', diff --git a/apps/web-antd/src/views/mes/pro/workorder/components/select-dialog.vue b/apps/web-antd/src/views/mes/pro/workorder/components/select-dialog.vue index 84fe01464..9a5936e23 100644 --- a/apps/web-antd/src/views/mes/pro/workorder/components/select-dialog.vue +++ b/apps/web-antd/src/views/mes/pro/workorder/components/select-dialog.vue @@ -37,7 +37,7 @@ const selectedRows = ref([]); // 已选工单列 const preSelectedIds = ref([]); // 预选工单编号列表 const typeTip = computed(() => { - if (props.type === null) { + if (props.type === undefined) { return ''; } return `仅展示【${getDictLabel(DICT_TYPE.MES_PRO_WORK_ORDER_TYPE, props.type)}】类型的工单`; @@ -61,6 +61,9 @@ function getMultipleSelectedRows() { /** 处理多选勾选变化 */ function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } selectedRows.value = getMultipleSelectedRows(); } @@ -137,8 +140,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ return await getWorkOrderPage({ pageNo: page.currentPage, pageSize: page.pageSize, - type: props.type, ...formValues, + ...(props.status === undefined ? {} : { status: props.status }), + ...(props.type === undefined ? {} : { type: props.type }), }); }, }, @@ -169,7 +173,7 @@ async function resetQueryState() { await gridApi.grid.clearCheckboxReserve(); await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); - if (props.status !== null) { + if (props.status !== undefined) { await gridApi.formApi.setFieldValue('status', props.status); } } diff --git a/apps/web-antd/src/views/mes/pro/workorder/components/select.vue b/apps/web-antd/src/views/mes/pro/workorder/components/select.vue index 09c9602de..848fc9a51 100644 --- a/apps/web-antd/src/views/mes/pro/workorder/components/select.vue +++ b/apps/web-antd/src/views/mes/pro/workorder/components/select.vue @@ -49,6 +49,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select-dialog.vue b/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select-dialog.vue index 176d9e158..5e1e6ef72 100644 --- a/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select-dialog.vue +++ b/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select-dialog.vue @@ -19,7 +19,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -57,10 +56,12 @@ function useSearchSchema(): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -101,65 +102,77 @@ function useGridColumns(): VxeTableGridOptions(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmArrivalNoticeApi.ArrivalNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmArrivalNoticeApi.ArrivalNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmArrivalNoticeApi.ArrivalNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmArrivalNoticeApi.ArrivalNotice[]; - row?: MesWmArrivalNoticeApi.ArrivalNotice; + row: MesWmArrivalNoticeApi.ArrivalNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmArrivalNoticeApi.ArrivalNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmArrivalNoticeApi.ArrivalNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -168,7 +181,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -176,6 +189,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -198,8 +215,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmArrivalNoticeApi.ArrivalNotice }) => { + handleRadioChange(row); + }, }, }); @@ -207,6 +228,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -220,10 +243,13 @@ async function openModal( fixedStatus.value = options?.status; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select.vue b/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select.vue index 15117cdde..a0afffcc3 100644 --- a/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select.vue +++ b/apps/web-antd/src/views/mes/wm/arrivalnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antd/src/views/mes/wm/salesnotice/components/select-dialog.vue b/apps/web-antd/src/views/mes/wm/salesnotice/components/select-dialog.vue index b97139575..8c5c8ef1b 100644 --- a/apps/web-antd/src/views/mes/wm/salesnotice/components/select-dialog.vue +++ b/apps/web-antd/src/views/mes/wm/salesnotice/components/select-dialog.vue @@ -21,7 +21,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -84,10 +83,12 @@ function useSearchSchema(hasFixedStatus: boolean): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -128,65 +129,77 @@ function useGridColumns(): VxeTableGridOptions[ ]; } -/** 单选模式下同步 VXE 勾选状态,避免跨页残留多选 */ -async function syncSingleSelection(row?: MesWmSalesNoticeApi.SalesNotice) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmSalesNoticeApi.SalesNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmSalesNoticeApi.SalesNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmSalesNoticeApi.SalesNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmSalesNoticeApi.SalesNotice[]; - row?: MesWmSalesNoticeApi.SalesNotice; + row: MesWmSalesNoticeApi.SalesNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmSalesNoticeApi.SalesNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmSalesNoticeApi.SalesNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -195,7 +208,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(false), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -203,6 +216,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -226,8 +243,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmSalesNoticeApi.SalesNotice }) => { + handleRadioChange(row); + }, }, }); @@ -235,6 +256,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -249,13 +272,16 @@ async function openModal( preSelectedIds.value = selectedIds || []; // 固定状态时隐藏状态搜索项,未固定时展示 gridApi.formApi.setState({ - schema: useSearchSchema(fixedStatus.value !== null), + schema: useSearchSchema(fixedStatus.value !== undefined), }); await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-antd/src/views/mes/wm/salesnotice/components/select.vue b/apps/web-antd/src/views/mes/wm/salesnotice/components/select.vue index f67933038..ee19d2c53 100644 --- a/apps/web-antd/src/views/mes/wm/salesnotice/components/select.vue +++ b/apps/web-antd/src/views/mes/wm/salesnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antdv-next/src/views/mes/md/workstation/components/select-dialog.vue b/apps/web-antdv-next/src/views/mes/md/workstation/components/select-dialog.vue index cdde8ec95..e4cc72ca4 100644 --- a/apps/web-antdv-next/src/views/mes/md/workstation/components/select-dialog.vue +++ b/apps/web-antdv-next/src/views/mes/md/workstation/components/select-dialog.vue @@ -30,69 +30,80 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(true); // 是否多选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选工作站列表 const preSelectedIds = ref([]); // 预选工作站编号列表 -/** 单选模式下同步 VXE 勾选状态 */ -async function syncSingleSelection(row?: MesMdWorkstationApi.Workstation) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesMdWorkstationApi.Workstation[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesMdWorkstationApi.Workstation) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesMdWorkstationApi.Workstation) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesMdWorkstationApi.Workstation[]; - row?: MesMdWorkstationApi.Workstation; + row: MesMdWorkstationApi.Workstation; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesMdWorkstationApi.Workstation[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选工作站 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesMdWorkstationApi.Workstation[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -101,7 +112,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useWorkstationSelectGridFormSchema(), }, gridOptions: { - columns: useWorkstationSelectGridColumns(), + columns: useWorkstationSelectGridColumns(true), height: 520, keepSource: true, checkboxConfig: { @@ -109,6 +120,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -131,8 +146,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesMdWorkstationApi.Workstation }) => { + handleRadioChange(row); + }, }, }); @@ -140,6 +159,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); if (props.processId) { await gridApi.formApi.setFieldValue('processId', props.processId); @@ -155,10 +176,13 @@ async function openModal( multiple.value = options?.multiple ?? true; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useWorkstationSelectGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭工作站选择弹窗 */ diff --git a/apps/web-antdv-next/src/views/mes/md/workstation/components/select.vue b/apps/web-antdv-next/src/views/mes/md/workstation/components/select.vue index a4828d8e4..b9e4e2c32 100644 --- a/apps/web-antdv-next/src/views/mes/md/workstation/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/md/workstation/components/select.vue @@ -44,6 +44,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antdv-next/src/views/mes/md/workstation/data.ts b/apps/web-antdv-next/src/views/mes/md/workstation/data.ts index 9a62997b9..c4cef2063 100644 --- a/apps/web-antdv-next/src/views/mes/md/workstation/data.ts +++ b/apps/web-antdv-next/src/views/mes/md/workstation/data.ts @@ -320,9 +320,11 @@ export function useWorkstationSelectGridFormSchema(): VbenFormSchema[] { } /** 工作站选择弹窗的字段 */ -export function useWorkstationSelectGridColumns(): VxeTableGridOptions['columns'] { +export function useWorkstationSelectGridColumns( + multiple = true, +): VxeTableGridOptions['columns'] { return [ - { type: 'checkbox', width: 50 }, + { type: multiple ? 'checkbox' : 'radio', width: 50 }, { field: 'code', title: '工作站编码', diff --git a/apps/web-antdv-next/src/views/mes/pro/workorder/components/select-dialog.vue b/apps/web-antdv-next/src/views/mes/pro/workorder/components/select-dialog.vue index cea37d93e..56a788d36 100644 --- a/apps/web-antdv-next/src/views/mes/pro/workorder/components/select-dialog.vue +++ b/apps/web-antdv-next/src/views/mes/pro/workorder/components/select-dialog.vue @@ -37,7 +37,7 @@ const selectedRows = ref([]); // 已选工单列 const preSelectedIds = ref([]); // 预选工单编号列表 const typeTip = computed(() => { - if (props.type === null) { + if (props.type === undefined) { return ''; } return `仅展示【${getDictLabel(DICT_TYPE.MES_PRO_WORK_ORDER_TYPE, props.type)}】类型的工单`; @@ -61,6 +61,9 @@ function getMultipleSelectedRows() { /** 处理多选勾选变化 */ function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } selectedRows.value = getMultipleSelectedRows(); } @@ -137,8 +140,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ return await getWorkOrderPage({ pageNo: page.currentPage, pageSize: page.pageSize, - type: props.type, ...formValues, + ...(props.status === undefined ? {} : { status: props.status }), + ...(props.type === undefined ? {} : { type: props.type }), }); }, }, @@ -169,7 +173,7 @@ async function resetQueryState() { await gridApi.grid.clearCheckboxReserve(); await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); - if (props.status !== null) { + if (props.status !== undefined) { await gridApi.formApi.setFieldValue('status', props.status); } } diff --git a/apps/web-antdv-next/src/views/mes/pro/workorder/components/select.vue b/apps/web-antdv-next/src/views/mes/pro/workorder/components/select.vue index 63ec8552d..78a7fb496 100644 --- a/apps/web-antdv-next/src/views/mes/pro/workorder/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/pro/workorder/components/select.vue @@ -49,6 +49,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select-dialog.vue b/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select-dialog.vue index 8c10c70ef..1cd3debdf 100644 --- a/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select-dialog.vue +++ b/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select-dialog.vue @@ -19,7 +19,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -57,10 +56,12 @@ function useSearchSchema(): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -101,65 +102,77 @@ function useGridColumns(): VxeTableGridOptions(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmArrivalNoticeApi.ArrivalNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmArrivalNoticeApi.ArrivalNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmArrivalNoticeApi.ArrivalNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmArrivalNoticeApi.ArrivalNotice[]; - row?: MesWmArrivalNoticeApi.ArrivalNotice; + row: MesWmArrivalNoticeApi.ArrivalNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmArrivalNoticeApi.ArrivalNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmArrivalNoticeApi.ArrivalNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -168,7 +181,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -176,6 +189,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -198,8 +215,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmArrivalNoticeApi.ArrivalNotice }) => { + handleRadioChange(row); + }, }, }); @@ -207,6 +228,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -220,10 +243,13 @@ async function openModal( fixedStatus.value = options?.status; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select.vue b/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select.vue index f2f3f2a40..f33d22579 100644 --- a/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/wm/arrivalnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select-dialog.vue b/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select-dialog.vue index a3332fe5f..de5cbdb51 100644 --- a/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select-dialog.vue +++ b/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select-dialog.vue @@ -21,7 +21,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -84,10 +83,12 @@ function useSearchSchema(hasFixedStatus: boolean): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -128,65 +129,77 @@ function useGridColumns(): VxeTableGridOptions[ ]; } -/** 单选模式下同步 VXE 勾选状态,避免跨页残留多选 */ -async function syncSingleSelection(row?: MesWmSalesNoticeApi.SalesNotice) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmSalesNoticeApi.SalesNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmSalesNoticeApi.SalesNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmSalesNoticeApi.SalesNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmSalesNoticeApi.SalesNotice[]; - row?: MesWmSalesNoticeApi.SalesNotice; + row: MesWmSalesNoticeApi.SalesNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmSalesNoticeApi.SalesNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmSalesNoticeApi.SalesNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -195,7 +208,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(false), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -203,6 +216,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -226,8 +243,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmSalesNoticeApi.SalesNotice }) => { + handleRadioChange(row); + }, }, }); @@ -235,6 +256,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -249,13 +272,16 @@ async function openModal( preSelectedIds.value = selectedIds || []; // 固定状态时隐藏状态搜索项,未固定时展示 gridApi.formApi.setState({ - schema: useSearchSchema(fixedStatus.value !== null), + schema: useSearchSchema(fixedStatus.value !== undefined), }); await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select.vue b/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select.vue index cdccd5e76..225158882 100644 --- a/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select.vue +++ b/apps/web-antdv-next/src/views/mes/wm/salesnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.allowClear && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-ele/src/views/mes/md/workstation/components/select-dialog.vue b/apps/web-ele/src/views/mes/md/workstation/components/select-dialog.vue index a1cc63d77..6fdf2c542 100644 --- a/apps/web-ele/src/views/mes/md/workstation/components/select-dialog.vue +++ b/apps/web-ele/src/views/mes/md/workstation/components/select-dialog.vue @@ -30,69 +30,80 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(true); // 是否多选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选工作站列表 const preSelectedIds = ref([]); // 预选工作站编号列表 -/** 单选模式下同步 VXE 勾选状态 */ -async function syncSingleSelection(row?: MesMdWorkstationApi.Workstation) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesMdWorkstationApi.Workstation[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesMdWorkstationApi.Workstation) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesMdWorkstationApi.Workstation) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesMdWorkstationApi.Workstation[]; - row?: MesMdWorkstationApi.Workstation; + row: MesMdWorkstationApi.Workstation; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesMdWorkstationApi.Workstation[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选工作站 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesMdWorkstationApi.Workstation[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -101,7 +112,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useWorkstationSelectGridFormSchema(), }, gridOptions: { - columns: useWorkstationSelectGridColumns(), + columns: useWorkstationSelectGridColumns(true), height: 520, keepSource: true, checkboxConfig: { @@ -109,6 +120,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -131,8 +146,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesMdWorkstationApi.Workstation }) => { + handleRadioChange(row); + }, }, }); @@ -140,6 +159,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); if (props.processId) { await gridApi.formApi.setFieldValue('processId', props.processId); @@ -155,10 +176,13 @@ async function openModal( multiple.value = options?.multiple ?? true; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useWorkstationSelectGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭工作站选择弹窗 */ diff --git a/apps/web-ele/src/views/mes/md/workstation/components/select.vue b/apps/web-ele/src/views/mes/md/workstation/components/select.vue index 98f9603f6..840aa7fa8 100644 --- a/apps/web-ele/src/views/mes/md/workstation/components/select.vue +++ b/apps/web-ele/src/views/mes/md/workstation/components/select.vue @@ -44,6 +44,7 @@ const showClear = computed( props.clearable && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-ele/src/views/mes/md/workstation/data.ts b/apps/web-ele/src/views/mes/md/workstation/data.ts index 1bb8351c4..b3bb43be5 100644 --- a/apps/web-ele/src/views/mes/md/workstation/data.ts +++ b/apps/web-ele/src/views/mes/md/workstation/data.ts @@ -317,9 +317,11 @@ export function useWorkstationSelectGridFormSchema(): VbenFormSchema[] { } /** 工作站选择弹窗的字段 */ -export function useWorkstationSelectGridColumns(): VxeTableGridOptions['columns'] { +export function useWorkstationSelectGridColumns( + multiple = true, +): VxeTableGridOptions['columns'] { return [ - { type: 'checkbox', width: 50 }, + { type: multiple ? 'checkbox' : 'radio', width: 50 }, { field: 'code', title: '工作站编码', diff --git a/apps/web-ele/src/views/mes/pro/workorder/components/select-dialog.vue b/apps/web-ele/src/views/mes/pro/workorder/components/select-dialog.vue index 2fa661d30..54cd39606 100644 --- a/apps/web-ele/src/views/mes/pro/workorder/components/select-dialog.vue +++ b/apps/web-ele/src/views/mes/pro/workorder/components/select-dialog.vue @@ -37,7 +37,7 @@ const selectedRows = ref([]); // 已选工单列 const preSelectedIds = ref([]); // 预选工单编号列表 const typeTip = computed(() => { - if (props.type === null) { + if (props.type === undefined) { return ''; } return `仅展示【${getDictLabel(DICT_TYPE.MES_PRO_WORK_ORDER_TYPE, props.type)}】类型的工单`; @@ -61,6 +61,9 @@ function getMultipleSelectedRows() { /** 处理多选勾选变化 */ function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } selectedRows.value = getMultipleSelectedRows(); } @@ -137,8 +140,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ return await getWorkOrderPage({ pageNo: page.currentPage, pageSize: page.pageSize, - type: props.type, ...formValues, + ...(props.status === undefined ? {} : { status: props.status }), + ...(props.type === undefined ? {} : { type: props.type }), }); }, }, @@ -169,7 +173,7 @@ async function resetQueryState() { await gridApi.grid.clearCheckboxReserve(); await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); - if (props.status !== null) { + if (props.status !== undefined) { await gridApi.formApi.setFieldValue('status', props.status); } } diff --git a/apps/web-ele/src/views/mes/pro/workorder/components/select.vue b/apps/web-ele/src/views/mes/pro/workorder/components/select.vue index 36adf2a43..935cf1742 100644 --- a/apps/web-ele/src/views/mes/pro/workorder/components/select.vue +++ b/apps/web-ele/src/views/mes/pro/workorder/components/select.vue @@ -49,6 +49,7 @@ const showClear = computed( props.clearable && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select-dialog.vue b/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select-dialog.vue index 836078b64..31a70b63f 100644 --- a/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select-dialog.vue +++ b/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select-dialog.vue @@ -19,7 +19,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -57,10 +56,12 @@ function useSearchSchema(): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -101,65 +102,77 @@ function useGridColumns(): VxeTableGridOptions(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmArrivalNoticeApi.ArrivalNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmArrivalNoticeApi.ArrivalNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmArrivalNoticeApi.ArrivalNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmArrivalNoticeApi.ArrivalNotice[]; - row?: MesWmArrivalNoticeApi.ArrivalNotice; + row: MesWmArrivalNoticeApi.ArrivalNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmArrivalNoticeApi.ArrivalNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmArrivalNoticeApi.ArrivalNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -168,7 +181,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -176,6 +189,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -198,8 +215,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmArrivalNoticeApi.ArrivalNotice }) => { + handleRadioChange(row); + }, }, }); @@ -207,6 +228,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -220,10 +243,13 @@ async function openModal( fixedStatus.value = options?.status; preSelectedIds.value = selectedIds || []; await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select.vue b/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select.vue index 2b1103b1e..4a47bd3b7 100644 --- a/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select.vue +++ b/apps/web-ele/src/views/mes/wm/arrivalnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.clearable && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, ); diff --git a/apps/web-ele/src/views/mes/wm/salesnotice/components/select-dialog.vue b/apps/web-ele/src/views/mes/wm/salesnotice/components/select-dialog.vue index bd59e342b..8e7e43e6a 100644 --- a/apps/web-ele/src/views/mes/wm/salesnotice/components/select-dialog.vue +++ b/apps/web-ele/src/views/mes/wm/salesnotice/components/select-dialog.vue @@ -21,7 +21,6 @@ const emit = defineEmits<{ const open = ref(false); // 弹窗是否打开 const multiple = ref(false); // 是否多选 const fixedStatus = ref(); // 固定状态筛选 -const syncingSingleSelection = ref(false); // 是否同步单选勾选状态 const selectedRows = ref([]); // 已选通知单列表 const preSelectedIds = ref([]); // 预选通知单编号列表 @@ -84,10 +83,12 @@ function useSearchSchema(hasFixedStatus: boolean): VbenFormSchema[] { } /** 表格字段 */ -function useGridColumns(): VxeTableGridOptions['columns'] { +function useGridColumns( + multipleSelect = false, +): VxeTableGridOptions['columns'] { return [ { - type: 'checkbox', + type: multipleSelect ? 'checkbox' : 'radio', width: 50, }, { @@ -128,65 +129,77 @@ function useGridColumns(): VxeTableGridOptions[ ]; } -/** 单选模式下同步 VXE 勾选状态,避免跨页残留多选 */ -async function syncSingleSelection(row?: MesWmSalesNoticeApi.SalesNotice) { - syncingSingleSelection.value = true; - await nextTick(); - await gridApi.grid.clearCheckboxRow(); - if (row) { - await gridApi.grid.setCheckboxRow(row, true); - } - await nextTick(); - syncingSingleSelection.value = false; +/** 获取多选记录,包含 VXE reserve 跨页记录 */ +function getMultipleSelectedRows() { + const selectedMap = new Map(); + const records = [ + ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), + ...(gridApi.grid.getCheckboxRecords?.() ?? []), + ] as MesWmSalesNoticeApi.SalesNotice[]; + records.forEach((row) => { + const rowId = row.id; + if (rowId !== undefined) { + selectedMap.set(rowId, row); + } + }); + return [...selectedMap.values()]; } -/** 处理勾选变化,单选模式只保留最后一条 */ -async function handleCheckboxChange({ - checked, - records, +/** 处理多选勾选变化 */ +function handleCheckboxSelectChange() { + if (!multiple.value) { + return; + } + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理单选切换 */ +function handleRadioChange(row: MesWmSalesNoticeApi.SalesNotice) { + selectedRows.value = [row]; +} + +/** 多选模式下切换行勾选 */ +async function toggleMultipleRow(row: MesWmSalesNoticeApi.SalesNotice) { + const selected = gridApi.grid.isCheckedByCheckboxRow(row); + await gridApi.grid.setCheckboxRow(row, !selected); + selectedRows.value = getMultipleSelectedRows(); +} + +/** 处理行双击:单选直接确认,多选切换勾选 */ +async function handleCellDblclick({ row, }: { - checked: boolean; - records: MesWmSalesNoticeApi.SalesNotice[]; - row?: MesWmSalesNoticeApi.SalesNotice; + row: MesWmSalesNoticeApi.SalesNotice; }) { - if (syncingSingleSelection.value) { + if (multiple.value) { + await toggleMultipleRow(row); return; } - if (!multiple.value) { - const selected = checked && row ? [row] : []; - selectedRows.value = selected; - await syncSingleSelection(selected[0]); - return; - } - selectedRows.value = records; -} - -/** 处理全选变化 */ -function handleCheckboxAll({ - records, -}: { - records: MesWmSalesNoticeApi.SalesNotice[]; -}) { - if (syncingSingleSelection.value) { - return; - } - selectedRows.value = records; + selectedRows.value = [row]; + await gridApi.grid.setRadioRow(row); + handleConfirm(); } /** 回显预选通知单 */ -function applyPreSelection() { +async function applyPreSelection() { if (preSelectedIds.value.length === 0) { return; } const rows = gridApi.grid.getData() as MesWmSalesNoticeApi.SalesNotice[]; for (const row of rows) { - if (row.id && preSelectedIds.value.includes(row.id)) { - gridApi.grid.setCheckboxRow(row, true); - if (!multiple.value) { - selectedRows.value = [row]; - } + if (row.id === undefined || !preSelectedIds.value.includes(row.id)) { + continue; } + if (multiple.value) { + await gridApi.grid.setCheckboxRow(row, true); + } else { + await gridApi.grid.setRadioRow(row); + selectedRows.value = [row]; + return; + } + } + if (multiple.value) { + selectedRows.value = getMultipleSelectedRows(); } } @@ -195,7 +208,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ schema: useSearchSchema(false), }, gridOptions: { - columns: useGridColumns(), + columns: useGridColumns(false), height: 520, keepSource: true, checkboxConfig: { @@ -203,6 +216,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ range: true, reserve: true, }, + radioConfig: { + highlight: true, + trigger: 'row', + }, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -226,8 +243,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: handleCheckboxAll, - checkboxChange: handleCheckboxChange, + cellDblclick: handleCellDblclick, + checkboxAll: handleCheckboxSelectChange, + checkboxChange: handleCheckboxSelectChange, + radioChange: ({ row }: { row: MesWmSalesNoticeApi.SalesNotice }) => { + handleRadioChange(row); + }, }, }); @@ -235,6 +256,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function resetQueryState() { selectedRows.value = []; await gridApi.grid.clearCheckboxRow(); + await gridApi.grid.clearCheckboxReserve(); + await gridApi.grid.clearRadioRow(); await gridApi.formApi.resetForm(); } @@ -249,13 +272,16 @@ async function openModal( preSelectedIds.value = selectedIds || []; // 固定状态时隐藏状态搜索项,未固定时展示 gridApi.formApi.setState({ - schema: useSearchSchema(fixedStatus.value !== null), + schema: useSearchSchema(fixedStatus.value !== undefined), }); await nextTick(); + gridApi.setGridOptions({ + columns: useGridColumns(multiple.value), + }); await resetQueryState(); await gridApi.query(); await nextTick(); - applyPreSelection(); + await applyPreSelection(); } /** 关闭通知单选择弹窗 */ diff --git a/apps/web-ele/src/views/mes/wm/salesnotice/components/select.vue b/apps/web-ele/src/views/mes/wm/salesnotice/components/select.vue index d452270d5..71ea309cc 100644 --- a/apps/web-ele/src/views/mes/wm/salesnotice/components/select.vue +++ b/apps/web-ele/src/views/mes/wm/salesnotice/components/select.vue @@ -47,6 +47,7 @@ const showClear = computed( props.clearable && !props.disabled && hovering.value && + props.modelValue !== undefined && props.modelValue !== null, );