| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { ImManagerGroupApi } from '#/api/im/manager/group'; |
| | | |
| | | import { nextTick, ref } from 'vue'; |
| | | |
| | | import { DICT_TYPE } from '#/packages/constants/src'; |
| | | import { getDictOptions } from '#/packages/effects/hooks/src'; |
| | | |
| | | import { Button, message, Modal } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | getManagerGroup, |
| | | getManagerGroupPage, |
| | | } from '#/api/im/manager/group'; |
| | | |
| | | const emit = defineEmits<{ |
| | | selected: [rows: ImManagerGroupApi.Group[]]; |
| | | }>(); |
| | | |
| | | const open = ref(false); // å¼¹çªæ¯å¦æå¼ |
| | | const multiple = ref(false); // æ¯å¦å¤é |
| | | const selectedRows = ref<ImManagerGroupApi.Group[]>([]); // å·²é群å表 |
| | | const preSelectedIds = ref<number[]>([]); // é¢é群ç¼å·å表 |
| | | |
| | | /** ç¾¤éæ©å¼¹çªçæç´¢è¡¨å */ |
| | | function useGroupSelectGridFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'name', |
| | | label: '群åç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥ç¾¤åç§°', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'status', |
| | | label: 'ç¾¤ç¶æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.IM_GROUP_STATUS, 'number'), |
| | | placeholder: 'è¯·éæ©ç¾¤ç¶æ', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** ç¾¤éæ©å¼¹çªçåæ®µ */ |
| | | function useGroupSelectGridColumns( |
| | | isMultiple = false, |
| | | ): VxeTableGridOptions<ImManagerGroupApi.Group>['columns'] { |
| | | return [ |
| | | { |
| | | type: isMultiple ? 'checkbox' : 'radio', |
| | | width: 50, |
| | | }, |
| | | { |
| | | field: 'id', |
| | | title: 'ç¼å·', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'name', |
| | | title: '群åç§°', |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | field: 'ownerNickname', |
| | | title: '群主', |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | field: 'memberCount', |
| | | title: 'æåæ°', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'status', |
| | | title: 'ç¾¤ç¶æ', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.IM_GROUP_STATUS }, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** è·åå¤éè®°å½ï¼å
å« VXE reserve è·¨é¡µè®°å½ */ |
| | | function getMultipleSelectedRows() { |
| | | const selectedMap = new Map<number, ImManagerGroupApi.Group>(); |
| | | const records = [ |
| | | ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), |
| | | ...(gridApi.grid.getCheckboxRecords?.() ?? []), |
| | | ] as ImManagerGroupApi.Group[]; |
| | | records.forEach((row) => { |
| | | selectedMap.set(row.id, row); |
| | | }); |
| | | return [...selectedMap.values()]; |
| | | } |
| | | |
| | | /** å¤çå¤éå¾éåå */ |
| | | function handleCheckboxSelectChange() { |
| | | selectedRows.value = getMultipleSelectedRows(); |
| | | } |
| | | |
| | | /** å¤çåé忢 */ |
| | | function handleRadioChange(row: ImManagerGroupApi.Group) { |
| | | selectedRows.value = [row]; |
| | | } |
| | | |
| | | /** å¤é模å¼ä¸åæ¢è¡å¾é */ |
| | | async function toggleMultipleRow(row: ImManagerGroupApi.Group) { |
| | | const selected = gridApi.grid.isCheckedByCheckboxRow(row); |
| | | await gridApi.grid.setCheckboxRow(row, !selected); |
| | | selectedRows.value = getMultipleSelectedRows(); |
| | | } |
| | | |
| | | /** å¤çè¡åå»ï¼åéç´æ¥ç¡®è®¤ï¼å¤é忢å¾é */ |
| | | async function handleCellDblclick({ row }: { row: ImManagerGroupApi.Group }) { |
| | | if (multiple.value) { |
| | | await toggleMultipleRow(row); |
| | | return; |
| | | } |
| | | selectedRows.value = [row]; |
| | | await gridApi.grid.setRadioRow(row); |
| | | handleConfirm(); |
| | | } |
| | | |
| | | /** åæ¾é¢é群 */ |
| | | async function applyPreSelection() { |
| | | if (preSelectedIds.value.length === 0) { |
| | | return; |
| | | } |
| | | const rows = gridApi.grid.getData() as ImManagerGroupApi.Group[]; |
| | | for (const row of rows) { |
| | | if (!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(); |
| | | return; |
| | | } |
| | | const targetId = preSelectedIds.value[0]; |
| | | if (targetId) { |
| | | selectedRows.value = [await getManagerGroup(targetId)]; |
| | | } |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | formOptions: { |
| | | schema: useGroupSelectGridFormSchema(), |
| | | }, |
| | | gridOptions: { |
| | | columns: useGroupSelectGridColumns(false), |
| | | height: 520, |
| | | keepSource: true, |
| | | checkboxConfig: { |
| | | highlight: true, |
| | | range: true, |
| | | reserve: true, |
| | | }, |
| | | radioConfig: { |
| | | highlight: true, |
| | | trigger: 'row', |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => { |
| | | return await getManagerGroupPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | search: true, |
| | | }, |
| | | } as VxeTableGridOptions<ImManagerGroupApi.Group>, |
| | | gridEvents: { |
| | | cellDblclick: handleCellDblclick, |
| | | checkboxAll: handleCheckboxSelectChange, |
| | | checkboxChange: handleCheckboxSelectChange, |
| | | radioChange: ({ row }: { row: ImManagerGroupApi.Group }) => { |
| | | handleRadioChange(row); |
| | | }, |
| | | }, |
| | | }); |
| | | |
| | | /** éç½®æ¥è¯¢åéæ©ç¶æ */ |
| | | async function resetQueryState() { |
| | | selectedRows.value = []; |
| | | await gridApi.grid.clearCheckboxRow(); |
| | | await gridApi.grid.clearCheckboxReserve(); |
| | | await gridApi.grid.clearRadioRow(); |
| | | await gridApi.formApi.resetForm(); |
| | | } |
| | | |
| | | /** æå¼ç¾¤éæ©å¼¹çª */ |
| | | async function openModal( |
| | | selectedIds?: number[], |
| | | options?: { multiple?: boolean }, |
| | | ) { |
| | | open.value = true; |
| | | multiple.value = options?.multiple ?? false; |
| | | preSelectedIds.value = selectedIds || []; |
| | | await nextTick(); |
| | | gridApi.setGridOptions({ |
| | | columns: useGroupSelectGridColumns(multiple.value), |
| | | }); |
| | | await resetQueryState(); |
| | | await gridApi.query(); |
| | | await nextTick(); |
| | | await applyPreSelection(); |
| | | } |
| | | |
| | | /** å
³éç¾¤éæ©å¼¹çª */ |
| | | function closeModal() { |
| | | open.value = false; |
| | | } |
| | | |
| | | /** ç¡®è®¤éæ©ç¾¤ */ |
| | | function handleConfirm() { |
| | | const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value; |
| | | if (rows.length === 0) { |
| | | message.warning(multiple.value ? '请è³å°éæ©ä¸æ¡æ°æ®' : 'è¯·éæ©ä¸æ¡æ°æ®'); |
| | | return; |
| | | } |
| | | emit('selected', multiple.value ? rows : [rows[0]!]); |
| | | open.value = false; |
| | | } |
| | | |
| | | defineExpose({ open: openModal }); |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal |
| | | v-model:open="open" |
| | | title="ç¾¤éæ©" |
| | | width="70%" |
| | | :destroy-on-close="true" |
| | | @ok="handleConfirm" |
| | | @cancel="closeModal" |
| | | > |
| | | <Grid table-title="群å表" /> |
| | | <template #footer> |
| | | <Button @click="closeModal">åæ¶</Button> |
| | | <Button type="primary" @click="handleConfirm">ç¡®å®</Button> |
| | | </template> |
| | | </Modal> |
| | | </template> |