Merge branch 'dev_pro2.0' of http://114.132.189.42:9002/r/mom-pro2-before into dev_pro2.0
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { PageParam, PageResult } from '@vben/request'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | export namespace MesDvMeteringApi { |
| | | /** MES 计éå¨å
· */ |
| | | export interface Metering { |
| | | id?: number; // 主é®ID |
| | | code?: string; // 计éå¨å
·ç¼ç |
| | | name?: string; // 计éå¨å
·åç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | brand?: string; // åç/ç产åå®¶ |
| | | category?: number; // å¨å
·ç±»å«ï¼åå
¸ï¼ |
| | | precision?: string; // 精度 |
| | | range?: string; // éç¨ |
| | | deptId?: number; // 使ç¨é¨é¨ç¼å· |
| | | deptName?: string; // 使ç¨é¨é¨åç§° |
| | | chargeUserId?: number; // 责任人ç¼å· |
| | | chargeUserNickname?: string; // 责任人æµç§° |
| | | checkCycleCount?: number; // æ ¡åå¨æï¼æï¼ |
| | | useDate?: string; // æå
¥ä½¿ç¨æ¥æ |
| | | lastCheckDate?: string; // 䏿¬¡æ£æµæ¥æ |
| | | nextCheckDate?: string; // 䏿¬¡æ£æµæ¥æï¼å°ææ¥ï¼ |
| | | status?: number; // ç¶æï¼åå
¸ï¼ |
| | | expireStatus?: number; // å°æç¶æï¼1 å·²è¿æ / 2 å³å°å°æ / 3 æ£å¸¸ |
| | | expireDays?: number; // è·å°æå¤©æ° |
| | | remark?: string; // 夿³¨ |
| | | createTime?: Date; // å建æ¶é´ |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢è®¡éå¨å
·å页 */ |
| | | export function getMeteringPage(params: PageParam) { |
| | | return requestClient.get<PageResult<MesDvMeteringApi.Metering>>( |
| | | '/mes/dv/metering/page', |
| | | { params }, |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢è®¡éå¨å
·è¯¦æ
*/ |
| | | export function getMetering(id: number) { |
| | | return requestClient.get<MesDvMeteringApi.Metering>( |
| | | `/mes/dv/metering/get?id=${id}`, |
| | | ); |
| | | } |
| | | |
| | | /** æ°å¢è®¡éå¨å
· */ |
| | | export function createMetering(data: MesDvMeteringApi.Metering) { |
| | | return requestClient.post<number>('/mes/dv/metering/create', data); |
| | | } |
| | | |
| | | /** ä¿®æ¹è®¡éå¨å
· */ |
| | | export function updateMetering(data: MesDvMeteringApi.Metering) { |
| | | return requestClient.put('/mes/dv/metering/update', data); |
| | | } |
| | | |
| | | /** å é¤è®¡éå¨å
· */ |
| | | export function deleteMetering(id: number) { |
| | | return requestClient.delete(`/mes/dv/metering/delete?id=${id}`); |
| | | } |
| | | |
| | | /** 导åºè®¡éå¨å
· */ |
| | | export function exportMetering(params: any) { |
| | | return requestClient.download('/mes/dv/metering/export-excel', { params }); |
| | | } |
| | | |
| | | /** æ¥è¯¢è®¡éå¨å
·ç²¾ç®å表ï¼ä¸æéé¡¹ï¼ */ |
| | | export function getMeteringSimpleList() { |
| | | return requestClient.get<MesDvMeteringApi.Metering[]>( |
| | | '/mes/dv/metering/simple-list', |
| | | ); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { PageParam, PageResult } from '@vben/request'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | export namespace MesDvMeteringCheckApi { |
| | | /** MES è®¡éæ£æµè®°å½ */ |
| | | export interface MeteringCheck { |
| | | id?: number; // 主é®ID |
| | | meteringId?: number; // 计éå¨å
·ID |
| | | meteringCode?: string; // 计éå¨å
·ç¼ç |
| | | meteringName?: string; // 计éå¨å
·åç§° |
| | | checkCode?: string; // æ£æµç¼å· |
| | | checkDate?: string; // æ£æµæ¥æ |
| | | checkOrg?: string; // æ£æµæºæ |
| | | checkResult?: number; // æ£æµç»è®ºï¼åå
¸ï¼ |
| | | certNo?: string; // è¯ä¹¦ç¼å· |
| | | checkUserId?: number; // æ£æµäººç¼å· |
| | | checkUserNickname?: string; // æ£æµäººæµç§° |
| | | nextCheckDate?: string; // 䏿¬¡æ£æµæ¥æ |
| | | remark?: string; // 夿³¨ |
| | | createTime?: Date; // å建æ¶é´ |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢è®¡éæ£æµè®°å½å页 */ |
| | | export function getMeteringCheckPage(params: PageParam) { |
| | | return requestClient.get<PageResult<MesDvMeteringCheckApi.MeteringCheck>>( |
| | | '/mes/dv/metering-check/page', |
| | | { params }, |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢è®¡éæ£æµè®°å½è¯¦æ
*/ |
| | | export function getMeteringCheck(id: number) { |
| | | return requestClient.get<MesDvMeteringCheckApi.MeteringCheck>( |
| | | `/mes/dv/metering-check/get?id=${id}`, |
| | | ); |
| | | } |
| | | |
| | | /** æ°å¢è®¡éæ£æµè®°å½ */ |
| | | export function createMeteringCheck(data: MesDvMeteringCheckApi.MeteringCheck) { |
| | | return requestClient.post<number>('/mes/dv/metering-check/create', data); |
| | | } |
| | | |
| | | /** ä¿®æ¹è®¡éæ£æµè®°å½ */ |
| | | export function updateMeteringCheck(data: MesDvMeteringCheckApi.MeteringCheck) { |
| | | return requestClient.put('/mes/dv/metering-check/update', data); |
| | | } |
| | | |
| | | /** å é¤è®¡éæ£æµè®°å½ */ |
| | | export function deleteMeteringCheck(id: number) { |
| | | return requestClient.delete(`/mes/dv/metering-check/delete?id=${id}`); |
| | | } |
| | | |
| | | /** 导åºè®¡éæ£æµè®°å½ */ |
| | | export function exportMeteringCheck(params: any) { |
| | | return requestClient.download('/mes/dv/metering-check/export-excel', { |
| | | params, |
| | | }); |
| | | } |
| | |
| | | ABNORMAL: 2, |
| | | } as const; |
| | | |
| | | /** MES 计éå¨å
·ç¶ææä¸¾ */ |
| | | export const MesDvMeteringStatusEnum = { |
| | | IN_USE: 1, // å¨ç¨ |
| | | STOPPED: 2, // åç¨ |
| | | SCRAPPED: 3, // æ¥åº |
| | | } as const; |
| | | |
| | | /** MES è®¡éæ£æµç»è®ºæä¸¾ */ |
| | | export const MesDvMeteringCheckResultEnum = { |
| | | QUALIFIED: 1, // åæ ¼ |
| | | UNQUALIFIED: 2, // ä¸åæ ¼ |
| | | } as const; |
| | | |
| | | /** MES 计éå¨å
·å°æç¶ææä¸¾ */ |
| | | export const MesDvMeteringExpireStatusEnum = { |
| | | OVERDUE: 1, // å·²è¿æ |
| | | WITHIN: 2, // å³å°å°æ |
| | | NORMAL: 3, // æ£å¸¸ |
| | | } as const; |
| | | |
| | | /** MES 维修工åç¶ææä¸¾ */ |
| | | export const MesDvRepairStatusEnum = { |
| | | PREPARE: MesOrderStatusConstants.DRAFT, |
| | |
| | | MES_DV_REPAIR_RESULT: 'mes_dv_repair_result', // MES ç»´ä¿®ç»æ |
| | | MES_DV_CHECK_RECORD_STATUS: 'mes_dv_check_record_status', // MES ç¹æ£è®°å½ç¶æ |
| | | MES_DV_CHECK_RESULT: 'mes_dv_check_result', // MES ç¹æ£ç»æ |
| | | MES_DV_METERING_CATEGORY: 'mes_dv_metering_category', // MES 计éå¨å
·ç±»å« |
| | | MES_DV_METERING_STATUS: 'mes_dv_metering_status', // MES 计éå¨å
·ç¶æ |
| | | MES_DV_METERING_CHECK_RESULT: 'mes_dv_metering_check_result', // MES è®¡éæ£æµç»è®º |
| | | MES_PRO_LINK_TYPE: 'mes_pro_link_type', // MES å·¥åºå
³ç³»ç±»å |
| | | MES_PRO_WORK_ORDER_STATUS: 'mes_pro_work_order_status', // MES ç产工åç¶æ |
| | | MES_PRO_WORK_ORDER_TYPE: 'mes_pro_work_order_type', // MES å·¥åç±»å |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export { default as DvMeteringSelectDialog } from './select-dialog.vue'; |
| | | export { default as DvMeteringSelect } from './select.vue'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesDvMeteringApi } from '#/api/mes/dv/metering'; |
| | | |
| | | import { nextTick, ref } from 'vue'; |
| | | |
| | | import { message, Modal } from 'ant-design-vue'; |
| | | |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getMeteringPage } from '#/api/mes/dv/metering'; |
| | | |
| | | import { |
| | | useMeteringSelectGridColumns, |
| | | useMeteringSelectGridFormSchema, |
| | | } from '../data'; |
| | | |
| | | defineOptions({ name: 'DvMeteringSelectDialog' }); |
| | | |
| | | const emit = defineEmits<{ |
| | | selected: [rows: MesDvMeteringApi.Metering[]]; |
| | | }>(); |
| | | |
| | | const open = ref(false); // å¼¹çªæ¯å¦æå¼ |
| | | const multiple = ref(false); // æ¯å¦å¤é |
| | | const selectedRows = ref<MesDvMeteringApi.Metering[]>([]); // å·²éå¨å
·å表 |
| | | const preSelectedIds = ref<number[]>([]); // é¢éå¨å
·ç¼å·å表 |
| | | |
| | | /** è·åå½åè¡¨æ ¼æ°æ® */ |
| | | function getTableRows() { |
| | | return gridApi.grid.getTableData().fullData as MesDvMeteringApi.Metering[]; |
| | | } |
| | | |
| | | /** è·åå¤éè®°å½ï¼å
å« VXE reserve è·¨é¡µè®°å½ */ |
| | | function getMultipleSelectedRows() { |
| | | const selectedMap = new Map<number, MesDvMeteringApi.Metering>(); |
| | | const records = [ |
| | | ...(gridApi.grid.getCheckboxReserveRecords?.() ?? []), |
| | | ...(gridApi.grid.getCheckboxRecords?.() ?? []), |
| | | ] as MesDvMeteringApi.Metering[]; |
| | | records.forEach((row) => { |
| | | const rowId = row.id; |
| | | if (rowId !== undefined && rowId !== null) { |
| | | selectedMap.set(rowId, row); |
| | | } |
| | | }); |
| | | return [...selectedMap.values()]; |
| | | } |
| | | |
| | | /** å¤çå¾éåå */ |
| | | function handleCheckboxSelectChange() { |
| | | selectedRows.value = getMultipleSelectedRows(); |
| | | } |
| | | |
| | | /** å¤çåéåå */ |
| | | function handleRadioChange(row: MesDvMeteringApi.Metering) { |
| | | selectedRows.value = [row]; |
| | | } |
| | | |
| | | /** å¤é模å¼ä¸åæ¢è¡å¾é */ |
| | | async function toggleMultipleRow(row: MesDvMeteringApi.Metering) { |
| | | const selected = gridApi.grid.isCheckedByCheckboxRow(row); |
| | | await gridApi.grid.setCheckboxRow(row, !selected); |
| | | selectedRows.value = getMultipleSelectedRows(); |
| | | } |
| | | |
| | | /** å¤çè¡åå» */ |
| | | async function handleCellDblclick({ |
| | | row, |
| | | }: { |
| | | row: MesDvMeteringApi.Metering; |
| | | }) { |
| | | 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 = getTableRows(); |
| | | for (const row of rows) { |
| | | if ( |
| | | row.id === undefined || |
| | | row.id === null || |
| | | !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(); |
| | | } |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | formOptions: { |
| | | schema: useMeteringSelectGridFormSchema(), |
| | | }, |
| | | gridOptions: { |
| | | columns: useMeteringSelectGridColumns(false), |
| | | height: 480, |
| | | keepSource: true, |
| | | checkboxConfig: { |
| | | highlight: true, |
| | | range: true, |
| | | reserve: true, |
| | | }, |
| | | radioConfig: { |
| | | highlight: true, |
| | | trigger: 'row', |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => { |
| | | return await getMeteringPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | search: true, |
| | | }, |
| | | } as VxeTableGridOptions<MesDvMeteringApi.Metering>, |
| | | gridEvents: { |
| | | cellDblclick: handleCellDblclick, |
| | | checkboxAll: handleCheckboxSelectChange, |
| | | checkboxChange: handleCheckboxSelectChange, |
| | | radioChange: ({ row }: { row: MesDvMeteringApi.Metering }) => { |
| | | 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: useMeteringSelectGridColumns(multiple.value), |
| | | }); |
| | | await resetQueryState(); |
| | | await gridApi.query(); |
| | | await nextTick(); |
| | | await applyPreSelection(); |
| | | } |
| | | |
| | | /** å
³é计éå¨å
·éæ©å¼¹çª */ |
| | | async function closeModal() { |
| | | open.value = false; |
| | | await resetQueryState(); |
| | | } |
| | | |
| | | /** ç¡®è®¤éæ©è®¡éå¨å
· */ |
| | | 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="计éå¨å
·å表" /> |
| | | </Modal> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { MesDvMeteringApi } from '#/api/mes/dv/metering'; |
| | | |
| | | import { computed, ref, useAttrs, watch } from 'vue'; |
| | | |
| | | import { IconifyIcon } from '@vben/icons'; |
| | | |
| | | import { Input, Tooltip } from 'ant-design-vue'; |
| | | |
| | | import { getMetering } from '#/api/mes/dv/metering'; |
| | | |
| | | import DvMeteringSelectDialog from './select-dialog.vue'; |
| | | |
| | | defineOptions({ name: 'DvMeteringSelect', inheritAttrs: false }); |
| | | |
| | | const props = withDefaults( |
| | | defineProps<{ |
| | | allowClear?: boolean; |
| | | disabled?: boolean; |
| | | modelValue?: number; |
| | | placeholder?: string; |
| | | }>(), |
| | | { |
| | | allowClear: true, |
| | | disabled: false, |
| | | modelValue: undefined, |
| | | placeholder: 'è¯·éæ©è®¡éå¨å
·', |
| | | }, |
| | | ); |
| | | const emit = defineEmits<{ |
| | | change: [item: MesDvMeteringApi.Metering | undefined]; |
| | | 'update:modelValue': [value: number | undefined]; |
| | | }>(); |
| | | const attrs = useAttrs(); // éä¼ å±æ§ |
| | | const dialogRef = ref<InstanceType<typeof DvMeteringSelectDialog>>(); // 计éå¨å
·éæ©å¼¹çª |
| | | const hovering = ref(false); // æ¯å¦æ¬å |
| | | const selectedItem = ref<MesDvMeteringApi.Metering>(); // å½åéä¸ç计éå¨å
· |
| | | |
| | | const displayLabel = computed(() => selectedItem.value?.name ?? ''); // éæ©å¨å±ç¤ºåç§° |
| | | const showClear = computed( |
| | | () => |
| | | props.allowClear && |
| | | !props.disabled && |
| | | hovering.value && |
| | | props.modelValue !== null, |
| | | ); |
| | | |
| | | /** æ ¹æ®å¨å
·ç¼å·åæ¾éæ©å¨ */ |
| | | async function resolveItemById(id: number | undefined) { |
| | | if (!id) { |
| | | selectedItem.value = undefined; |
| | | return; |
| | | } |
| | | if (selectedItem.value?.id === id) { |
| | | return; |
| | | } |
| | | selectedItem.value = await getMetering(id); |
| | | } |
| | | |
| | | watch( |
| | | () => props.modelValue, |
| | | (value) => { |
| | | resolveItemById(value); |
| | | }, |
| | | { immediate: true }, |
| | | ); |
| | | |
| | | /** æ¸
空已éå¨å
· */ |
| | | function clearSelected() { |
| | | selectedItem.value = undefined; |
| | | emit('update:modelValue', undefined); |
| | | emit('change', undefined); |
| | | } |
| | | |
| | | /** æå¼è®¡éå¨å
·éæ©å¼¹çª */ |
| | | function handleClick(event: MouseEvent) { |
| | | if (props.disabled) { |
| | | return; |
| | | } |
| | | const target = event.target as HTMLElement; |
| | | if (showClear.value && target.closest('.ant-input-suffix')) { |
| | | event.stopPropagation(); |
| | | clearSelected(); |
| | | return; |
| | | } |
| | | const selectedIds = ( |
| | | props.modelValue === null ? [] : [props.modelValue] |
| | | ) as number[]; |
| | | dialogRef.value?.open(selectedIds, { multiple: false }); |
| | | } |
| | | |
| | | /** åå¡«éä¸ç计éå¨å
· */ |
| | | function handleSelected(rows: MesDvMeteringApi.Metering[]) { |
| | | const item = rows[0]; |
| | | if (!item) { |
| | | return; |
| | | } |
| | | selectedItem.value = item; |
| | | emit('update:modelValue', item.id); |
| | | emit('change', item); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div |
| | | v-bind="attrs" |
| | | class="w-full" |
| | | :class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'" |
| | | @click="handleClick" |
| | | @mouseenter="hovering = true" |
| | | @mouseleave="hovering = false" |
| | | > |
| | | <Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false"> |
| | | <template #title> |
| | | <div v-if="selectedItem" class="leading-6"> |
| | | <div>å¨å
·ç¼ç ï¼{{ selectedItem.code || '-' }}</div> |
| | | <div>å¨å
·åç§°ï¼{{ selectedItem.name || '-' }}</div> |
| | | <div v-if="selectedItem.specification"> |
| | | è§æ ¼åå·ï¼{{ selectedItem.specification }} |
| | | </div> |
| | | <div v-if="selectedItem.deptName"> |
| | | 使ç¨é¨é¨ï¼{{ selectedItem.deptName }} |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <Input |
| | | :disabled="disabled" |
| | | :placeholder="placeholder" |
| | | :value="displayLabel" |
| | | readonly |
| | | > |
| | | <template #suffix> |
| | | <IconifyIcon |
| | | class="size-4" |
| | | :icon="showClear ? 'lucide:circle-x' : 'lucide:search'" |
| | | /> |
| | | </template> |
| | | </Input> |
| | | </Tooltip> |
| | | </div> |
| | | <DvMeteringSelectDialog ref="dialogRef" @selected="handleSelected" /> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesDvMeteringApi } from '#/api/mes/dv/metering'; |
| | | |
| | | import { |
| | | DICT_TYPE, |
| | | MesDvMeteringExpireStatusEnum, |
| | | MesDvMeteringStatusEnum, |
| | | } from '@vben/constants'; |
| | | import { getDictOptions } from '@vben/hooks'; |
| | | import { handleTree } from '@vben/utils'; |
| | | |
| | | import { z } from '#/adapter/form'; |
| | | import { getSimpleDeptList } from '#/api/system/dept'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | | |
| | | /** å°æç¶æå±ç¤ºé
ç½® */ |
| | | export const METERING_EXPIRE_STATUS_OPTIONS: { |
| | | color: string; |
| | | label: string; |
| | | value: number; |
| | | }[] = [ |
| | | { |
| | | label: 'å·²è¿æ', |
| | | value: MesDvMeteringExpireStatusEnum.OVERDUE, |
| | | color: 'red', |
| | | }, |
| | | { |
| | | label: 'å³å°å°æ', |
| | | value: MesDvMeteringExpireStatusEnum.WITHIN, |
| | | color: 'orange', |
| | | }, |
| | | { |
| | | label: 'æ£å¸¸', |
| | | value: MesDvMeteringExpireStatusEnum.NORMAL, |
| | | color: 'green', |
| | | }, |
| | | ]; |
| | | |
| | | /** æ°å¢/ä¿®æ¹è®¡éå¨å
·ç表å */ |
| | | export function useFormSchema(formType: FormType): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'id', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'code', |
| | | label: 'å¨å
·ç¼ç ', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥å¨å
·ç¼ç ', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['id'], |
| | | componentProps: (values) => ({ disabled: !!values.id }), |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'name', |
| | | label: 'å¨å
·åç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥å¨å
·åç§°', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'category', |
| | | label: 'å¨å
·ç±»å«', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_CATEGORY, 'number'), |
| | | placeholder: 'è¯·éæ©å¨å
·ç±»å«', |
| | | }, |
| | | help: 'å¦å¡å°ºãååè¡¨ãæ¸©åº¦è®¡çï¼ä¸åç±»å«æå¸¸è§çæ ¡å卿', |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | fieldName: 'specification', |
| | | label: 'è§æ ¼åå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥è§æ ¼åå·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'brand', |
| | | label: 'åç/ç产åå®¶', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥åç/ç产åå®¶', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'precision', |
| | | label: '精度', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥ç²¾åº¦', |
| | | }, |
| | | help: 'æµé精度ï¼å¦ 0.01mm', |
| | | }, |
| | | { |
| | | fieldName: 'range', |
| | | label: 'éç¨', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥éç¨', |
| | | }, |
| | | help: 'æµéèå´ï¼å¦ 0~150mm', |
| | | }, |
| | | { |
| | | fieldName: 'deptId', |
| | | label: '使ç¨é¨é¨', |
| | | component: 'ApiTreeSelect', |
| | | componentProps: { |
| | | api: async () => handleTree(await getSimpleDeptList()), |
| | | childrenField: 'children', |
| | | labelField: 'name', |
| | | placeholder: 'è¯·éæ©ä½¿ç¨é¨é¨', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'chargeUserId', |
| | | label: '责任人', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | api: getSimpleUserList, |
| | | labelField: 'nickname', |
| | | placeholder: 'è¯·éæ©è´£ä»»äºº', |
| | | valueField: 'id', |
| | | }, |
| | | help: '该å¨å
·çç»´æ¤è´£ä»»äººï¼å°ææéçç«å
ä¿¡ä¼åç»ä»', |
| | | }, |
| | | { |
| | | fieldName: 'checkCycleCount', |
| | | label: 'æ ¡å卿', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 1, |
| | | precision: 0, |
| | | placeholder: '请è¾å
¥æ ¡å卿', |
| | | suffix: 'æ', |
| | | }, |
| | | help: 'å¨å
·æ¯é N 个æé¡»æ ¡å/æ£å®ä¸æ¬¡ï¼æ°å¢æ£æµè®°å½æ¶ä¸å¡«ä¸æ¬¡æ£æµæ¥æï¼å°æãæ£æµæ¥æ + æ ¡å卿ãèªå¨è®¡ç®', |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'useDate', |
| | | label: 'æå
¥ä½¿ç¨æ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | format: 'YYYY-MM-DD', |
| | | placeholder: 'è¯·éæ©æå
¥ä½¿ç¨æ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | help: 'å¨å
·å¼å§æå
¥ä½¿ç¨çæ¥æï¼ä»
ä½è®°å½ï¼', |
| | | }, |
| | | { |
| | | fieldName: 'lastCheckDate', |
| | | label: '䏿¬¡æ£æµæ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | disabled: true, |
| | | format: 'YYYY-MM-DD', |
| | | placeholder: '䏿¬¡æ£æµæ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | help: 'ç±ææ°ä¸æ¡æ£æµè®°å½èªå¨ååï¼ä¸å¯æå¨ä¿®æ¹', |
| | | dependencies: { |
| | | triggerFields: ['id'], |
| | | show: () => formType === 'detail', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'nextCheckDate', |
| | | label: '䏿¬¡æ£æµæ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | disabled: true, |
| | | format: 'YYYY-MM-DD', |
| | | placeholder: '䏿¬¡æ£æµæ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | help: 'å°ææ¥ï¼ç±æ£æµè®°å½èªå¨è®¡ç®ååï¼å°æå N 天ï¼åºç¡è®¾æ½é
ç½®ï¼å°æé责任人', |
| | | dependencies: { |
| | | triggerFields: ['id'], |
| | | show: () => formType === 'detail', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'status', |
| | | label: 'å¨å
·ç¶æ', |
| | | component: 'RadioGroup', |
| | | componentProps: { |
| | | buttonStyle: 'solid', |
| | | optionType: 'button', |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_STATUS, 'number'), |
| | | }, |
| | | help: 'å¨ç¨/åç¨/æ¥åº', |
| | | rules: z.number().default(MesDvMeteringStatusEnum.IN_USE), |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | component: 'Textarea', |
| | | formItemClass: 'col-span-3', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥å¤æ³¨', |
| | | rows: 3, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å表çæç´¢è¡¨å */ |
| | | export function useGridFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'code', |
| | | label: 'å¨å
·ç¼ç ', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥å¨å
·ç¼ç ', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'name', |
| | | label: 'å¨å
·åç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥å¨å
·åç§°', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'category', |
| | | label: 'å¨å
·ç±»å«', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_CATEGORY, 'number'), |
| | | placeholder: 'è¯·éæ©å¨å
·ç±»å«', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'deptId', |
| | | label: '使ç¨é¨é¨', |
| | | component: 'ApiTreeSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | api: async () => handleTree(await getSimpleDeptList()), |
| | | childrenField: 'children', |
| | | labelField: 'name', |
| | | placeholder: 'è¯·éæ©ä½¿ç¨é¨é¨', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'chargeUserId', |
| | | label: '责任人', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | api: getSimpleUserList, |
| | | labelField: 'nickname', |
| | | placeholder: 'è¯·éæ©è´£ä»»äºº', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'status', |
| | | label: 'å¨å
·ç¶æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_STATUS, 'number'), |
| | | placeholder: 'è¯·éæ©å¨å
·ç¶æ', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'expireStatus', |
| | | label: 'å°æç¶æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: METERING_EXPIRE_STATUS_OPTIONS, |
| | | placeholder: 'è¯·éæ©å°æç¶æ', |
| | | }, |
| | | help: '䏿¬¡æ£æµæ¥æè·ä»å¤© ⤠æé天æ°ï¼åºç¡è®¾æ½é
ç½® mes.dv-metering.remind-daysï¼å³è§ä¸ºãå³å°å°æã', |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å表çåæ®µ */ |
| | | export function useGridColumns(): VxeTableGridOptions<MesDvMeteringApi.Metering>['columns'] { |
| | | return [ |
| | | { |
| | | field: 'code', |
| | | title: 'å¨å
·ç¼ç ', |
| | | minWidth: 150, |
| | | slots: { |
| | | default: 'code', |
| | | }, |
| | | }, |
| | | { field: 'name', title: 'å¨å
·åç§°', minWidth: 150 }, |
| | | { |
| | | field: 'category', |
| | | title: 'å¨å
·ç±»å«', |
| | | width: 110, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_DV_METERING_CATEGORY }, |
| | | }, |
| | | }, |
| | | { field: 'specification', title: 'è§æ ¼åå·', minWidth: 130 }, |
| | | { field: 'brand', title: 'åç/ç产åå®¶', minWidth: 130 }, |
| | | { field: 'deptName', title: '使ç¨é¨é¨', minWidth: 130 }, |
| | | { field: 'chargeUserNickname', title: '责任人', minWidth: 100 }, |
| | | { |
| | | field: 'expireStatus', |
| | | title: 'å°æç¶æ', |
| | | width: 110, |
| | | slots: { |
| | | default: 'expireStatus', |
| | | }, |
| | | }, |
| | | { |
| | | field: 'nextCheckDate', |
| | | title: '䏿¬¡æ£æµæ¥æ', |
| | | width: 130, |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'status', |
| | | title: 'å¨å
·ç¶æ', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_DV_METERING_STATUS }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'createTime', |
| | | title: 'å建æ¶é´', |
| | | width: 180, |
| | | formatter: 'formatDateTime', |
| | | }, |
| | | { |
| | | title: 'æä½', |
| | | width: 210, |
| | | fixed: 'right', |
| | | slots: { |
| | | default: 'actions', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** 计éå¨å
·éæ©å¼¹çªçæç´¢è¡¨å */ |
| | | export function useMeteringSelectGridFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'code', |
| | | label: 'å¨å
·ç¼ç ', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥å¨å
·ç¼ç ', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'name', |
| | | label: 'å¨å
·åç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥å¨å
·åç§°', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** 计éå¨å
·éæ©å¼¹çªçåæ®µ */ |
| | | export function useMeteringSelectGridColumns( |
| | | multiple = false, |
| | | ): VxeTableGridOptions<MesDvMeteringApi.Metering>['columns'] { |
| | | return [ |
| | | { type: multiple ? 'checkbox' : 'radio', width: 50 }, |
| | | { field: 'code', title: 'å¨å
·ç¼ç ', width: 140 }, |
| | | { field: 'name', title: 'å¨å
·åç§°', minWidth: 140 }, |
| | | { |
| | | field: 'category', |
| | | title: 'å¨å
·ç±»å«', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_DV_METERING_CATEGORY }, |
| | | }, |
| | | }, |
| | | { field: 'specification', title: 'è§æ ¼åå·', minWidth: 120 }, |
| | | { field: 'deptName', title: '使ç¨é¨é¨', width: 120 }, |
| | | { field: 'chargeUserNickname', title: '责任人', width: 100 }, |
| | | { |
| | | field: 'nextCheckDate', |
| | | title: '䏿¬¡æ£æµæ¥æ', |
| | | width: 120, |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'status', |
| | | title: 'å¨å
·ç¶æ', |
| | | width: 90, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_DV_METERING_STATUS }, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesDvMeteringApi } from '#/api/mes/dv/metering'; |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Tag } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteMetering, |
| | | exportMetering, |
| | | getMeteringPage, |
| | | } from '#/api/mes/dv/metering'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { |
| | | METERING_EXPIRE_STATUS_OPTIONS, |
| | | useGridColumns, |
| | | useGridFormSchema, |
| | | } from './data'; |
| | | import Form from './modules/form.vue'; |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | /** å·æ°è¡¨æ ¼ */ |
| | | function handleRefresh() { |
| | | gridApi.query(); |
| | | } |
| | | |
| | | /** å建计éå¨å
· */ |
| | | function handleCreate() { |
| | | formModalApi.setData({ formType: 'create' }).open(); |
| | | } |
| | | |
| | | /** æ¥ç计éå¨å
· */ |
| | | function handleDetail(row: MesDvMeteringApi.Metering) { |
| | | formModalApi.setData({ id: row.id, formType: 'detail' }).open(); |
| | | } |
| | | |
| | | /** ç¼è¾è®¡éå¨å
· */ |
| | | function handleEdit(row: MesDvMeteringApi.Metering) { |
| | | formModalApi.setData({ id: row.id, formType: 'update' }).open(); |
| | | } |
| | | |
| | | /** å é¤è®¡éå¨å
· */ |
| | | async function handleDelete(row: MesDvMeteringApi.Metering) { |
| | | const hideLoading = message.loading({ |
| | | content: $t('ui.actionMessage.deleting', [row.name]), |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await deleteMetering(row.id!); |
| | | message.success($t('ui.actionMessage.deleteSuccess', [row.name])); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** 导åºè®¡éå¨å
· */ |
| | | async function handleExport() { |
| | | const data = await exportMetering(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: '计éå¨å
·.xls', source: data }); |
| | | } |
| | | |
| | | /** å°æç¶æå±ç¤º */ |
| | | function getExpireStatusConfig(status?: number) { |
| | | return METERING_EXPIRE_STATUS_OPTIONS.find((item) => item.value === status); |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | formOptions: { |
| | | schema: useGridFormSchema(), |
| | | }, |
| | | gridOptions: { |
| | | columns: useGridColumns(), |
| | | height: 'auto', |
| | | keepSource: true, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => |
| | | await getMeteringPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }), |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | search: true, |
| | | }, |
| | | } as VxeTableGridOptions<MesDvMeteringApi.Metering>, |
| | | }); |
| | | </script> |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <Grid table-title="计éå¨å
·å表"> |
| | | <template #toolbar-tools> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: $t('ui.actionTitle.create', ['计éå¨å
·']), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.ADD, |
| | | auth: ['mes:dv-metering:create'], |
| | | onClick: handleCreate, |
| | | }, |
| | | { |
| | | label: $t('ui.actionTitle.export'), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.DOWNLOAD, |
| | | auth: ['mes:dv-metering:export'], |
| | | onClick: handleExport, |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #code="{ row }"> |
| | | <Button type="link" @click="handleDetail(row)"> |
| | | {{ row.code }} |
| | | </Button> |
| | | </template> |
| | | <template #expireStatus="{ row }"> |
| | | <Tag |
| | | v-if="getExpireStatusConfig(row.expireStatus)" |
| | | :color="getExpireStatusConfig(row.expireStatus)!.color" |
| | | > |
| | | {{ getExpireStatusConfig(row.expireStatus)!.label }} |
| | | </Tag> |
| | | <span v-else>-</span> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: $t('common.edit'), |
| | | type: 'link', |
| | | icon: ACTION_ICON.EDIT, |
| | | auth: ['mes:dv-metering:update'], |
| | | onClick: handleEdit.bind(null, row), |
| | | }, |
| | | { |
| | | label: $t('common.delete'), |
| | | type: 'link', |
| | | danger: true, |
| | | icon: ACTION_ICON.DELETE, |
| | | auth: ['mes:dv-metering:delete'], |
| | | popConfirm: { |
| | | title: $t('ui.actionMessage.deleteConfirm', [row.name]), |
| | | confirm: handleDelete.bind(null, row), |
| | | }, |
| | | }, |
| | | { |
| | | label: $t('common.detail'), |
| | | type: 'link', |
| | | icon: ACTION_ICON.VIEW, |
| | | auth: ['mes:dv-metering:query'], |
| | | onClick: handleDetail.bind(null, row), |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | </Grid> |
| | | </Page> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { FormType } from '../data'; |
| | | |
| | | import type { MesDvMeteringApi } from '#/api/mes/dv/metering'; |
| | | |
| | | import { computed, ref } from 'vue'; |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { |
| | | createMetering, |
| | | getMetering, |
| | | updateMetering, |
| | | } from '#/api/mes/dv/metering'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formType = ref<FormType>('create'); |
| | | const formData = ref<MesDvMeteringApi.Metering>(); |
| | | const isDetail = computed(() => formType.value === 'detail'); |
| | | const getTitle = computed(() => { |
| | | if (formType.value === 'detail') { |
| | | return 'æ¥ç计éå¨å
·'; |
| | | } |
| | | return formType.value === 'update' ? 'ä¿®æ¹è®¡éå¨å
·' : 'æ°å¢è®¡éå¨å
·'; |
| | | }); |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | | componentProps: { |
| | | class: 'w-full', |
| | | }, |
| | | formItemClass: 'col-span-1', |
| | | labelWidth: 110, |
| | | }, |
| | | wrapperClass: 'grid-cols-3', |
| | | layout: 'horizontal', |
| | | schema: [], |
| | | showDefaultActions: false, |
| | | }); |
| | | |
| | | const [Modal, modalApi] = useVbenModal({ |
| | | async onConfirm() { |
| | | if (isDetail.value) { |
| | | await modalApi.close(); |
| | | return; |
| | | } |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | const data = (await formApi.getValues()) as MesDvMeteringApi.Metering; |
| | | try { |
| | | if (formType.value === 'create') { |
| | | await createMetering(data); |
| | | } else { |
| | | await updateMetering(data); |
| | | } |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | await modalApi.close(); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | const data = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = data.formType; |
| | | formApi.setState({ schema: useFormSchema(formType.value) }); |
| | | formApi.setDisabled(formType.value === 'detail'); |
| | | modalApi.setState({ showConfirmButton: formType.value !== 'detail' }); |
| | | if (!data?.id) { |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getMetering(data.id); |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | }); |
| | | </script> |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/5"> |
| | | <Form class="mx-4" /> |
| | | </Modal> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesDvMeteringCheckApi } from '#/api/mes/dv/meteringcheck'; |
| | | |
| | | import { markRaw } from 'vue'; |
| | | |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | import { getDictOptions } from '@vben/hooks'; |
| | | |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { DvMeteringSelect } from '#/views/mes/dv/metering/components'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'update'; |
| | | |
| | | /** æ°å¢/ä¿®æ¹è®¡éæ£æµè®°å½ç表å */ |
| | | export function useFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'id', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'meteringId', |
| | | label: '计éå¨å
·', |
| | | component: markRaw(DvMeteringSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©è®¡éå¨å
·', |
| | | }, |
| | | help: 'éæ©å¨å
·åï¼å
¶æ ¡å卿å°ç¨äºèªå¨è®¡ç®ä¸æ¬¡æ£æµæ¥æ', |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | fieldName: 'checkCode', |
| | | label: 'æ£æµç¼å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥æ£æµç¼å·', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'checkDate', |
| | | label: 'æ£æµæ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | format: 'YYYY-MM-DD', |
| | | placeholder: 'è¯·éæ©æ£æµæ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'checkOrg', |
| | | label: 'æ£æµæºæ', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥æ£æµæºæ', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'checkResult', |
| | | label: 'æ£æµç»è®º', |
| | | component: 'RadioGroup', |
| | | componentProps: { |
| | | buttonStyle: 'solid', |
| | | optionType: 'button', |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_CHECK_RESULT, 'number'), |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'certNo', |
| | | label: 'è¯ä¹¦ç¼å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥è¯ä¹¦ç¼å·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'checkUserId', |
| | | label: 'æ£æµäºº', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | api: getSimpleUserList, |
| | | labelField: 'nickname', |
| | | placeholder: 'è¯·éæ©æ£æµäºº', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'nextCheckDate', |
| | | label: '䏿¬¡æ£æµæ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | format: 'YYYY-MM-DD', |
| | | placeholder: 'è¯·éæ©ä¸æ¬¡æ£æµæ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | help: 'å°ææ¥ï¼å»ºè®®ä¸å¡«ï¼å°æãæ£æµæ¥æ + æ ¡å卿ãèªå¨è®¡ç®å¹¶ååå°å¨å
·ï¼ä¹å¯æå¨æå®', |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | component: 'Textarea', |
| | | formItemClass: 'col-span-3', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥å¤æ³¨', |
| | | rows: 3, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å表çæç´¢è¡¨å */ |
| | | export function useGridFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'meteringId', |
| | | label: '计éå¨å
·', |
| | | component: markRaw(DvMeteringSelect), |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: 'è¯·éæ©è®¡éå¨å
·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'checkCode', |
| | | label: 'æ£æµç¼å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请è¾å
¥æ£æµç¼å·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'checkResult', |
| | | label: 'æ£æµç»è®º', |
| | | component: 'Select', |
| | | componentProps: { |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.MES_DV_METERING_CHECK_RESULT, 'number'), |
| | | placeholder: 'è¯·éæ©æ£æµç»è®º', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'checkDate', |
| | | label: 'æ£æµæ¥æ', |
| | | component: 'RangePicker', |
| | | componentProps: { |
| | | allowClear: true, |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** å表çåæ®µ */ |
| | | export function useGridColumns(): VxeTableGridOptions<MesDvMeteringCheckApi.MeteringCheck>['columns'] { |
| | | return [ |
| | | { |
| | | field: 'meteringCode', |
| | | title: 'å¨å
·ç¼ç ', |
| | | minWidth: 140, |
| | | slots: { |
| | | default: 'meteringCode', |
| | | }, |
| | | }, |
| | | { field: 'meteringName', title: 'å¨å
·åç§°', minWidth: 150 }, |
| | | { field: 'checkCode', title: 'æ£æµç¼å·', minWidth: 140 }, |
| | | { |
| | | field: 'checkDate', |
| | | title: 'æ£æµæ¥æ', |
| | | width: 120, |
| | | formatter: 'formatDate', |
| | | }, |
| | | { field: 'checkOrg', title: 'æ£æµæºæ', minWidth: 140 }, |
| | | { |
| | | field: 'checkResult', |
| | | title: 'æ£æµç»è®º', |
| | | width: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_DV_METERING_CHECK_RESULT }, |
| | | }, |
| | | }, |
| | | { field: 'certNo', title: 'è¯ä¹¦ç¼å·', minWidth: 130 }, |
| | | { field: 'checkUserNickname', title: 'æ£æµäºº', minWidth: 100 }, |
| | | { |
| | | field: 'nextCheckDate', |
| | | title: '䏿¬¡æ£æµæ¥æ', |
| | | width: 130, |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'createTime', |
| | | title: 'å建æ¶é´', |
| | | width: 180, |
| | | formatter: 'formatDateTime', |
| | | }, |
| | | { |
| | | title: 'æä½', |
| | | width: 200, |
| | | fixed: 'right', |
| | | slots: { |
| | | default: 'actions', |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesDvMeteringCheckApi } from '#/api/mes/dv/meteringcheck'; |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteMeteringCheck, |
| | | exportMeteringCheck, |
| | | getMeteringCheckPage, |
| | | } from '#/api/mes/dv/meteringcheck'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | | import Form from './modules/form.vue'; |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | /** å·æ°è¡¨æ ¼ */ |
| | | function handleRefresh() { |
| | | gridApi.query(); |
| | | } |
| | | |
| | | /** åå»ºè®¡éæ£æµè®°å½ */ |
| | | function handleCreate() { |
| | | formModalApi.setData({ formType: 'create' }).open(); |
| | | } |
| | | |
| | | /** æ¥çè®¡éæ£æµè®°å½ */ |
| | | function handleDetail(row: MesDvMeteringCheckApi.MeteringCheck) { |
| | | formModalApi.setData({ id: row.id, formType: 'detail' }).open(); |
| | | } |
| | | |
| | | /** ç¼è¾è®¡éæ£æµè®°å½ */ |
| | | function handleEdit(row: MesDvMeteringCheckApi.MeteringCheck) { |
| | | formModalApi.setData({ id: row.id, formType: 'update' }).open(); |
| | | } |
| | | |
| | | /** å é¤è®¡éæ£æµè®°å½ */ |
| | | async function handleDelete(row: MesDvMeteringCheckApi.MeteringCheck) { |
| | | const hideLoading = message.loading({ |
| | | content: $t('ui.actionMessage.deleting', [row.checkCode]), |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await deleteMeteringCheck(row.id!); |
| | | message.success($t('ui.actionMessage.deleteSuccess', [row.checkCode])); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** 导åºè®¡éæ£æµè®°å½ */ |
| | | async function handleExport() { |
| | | const data = await exportMeteringCheck(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'è®¡éæ£æµè®°å½.xls', source: data }); |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | | formOptions: { |
| | | schema: useGridFormSchema(), |
| | | }, |
| | | gridOptions: { |
| | | columns: useGridColumns(), |
| | | height: 'auto', |
| | | keepSource: true, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => |
| | | await getMeteringCheckPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }), |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | | }, |
| | | toolbarConfig: { |
| | | refresh: true, |
| | | search: true, |
| | | }, |
| | | } as VxeTableGridOptions<MesDvMeteringCheckApi.MeteringCheck>, |
| | | }); |
| | | </script> |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <Grid table-title="è®¡éæ£æµè®°å½å表"> |
| | | <template #toolbar-tools> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: $t('ui.actionTitle.create', ['æ£æµè®°å½']), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.ADD, |
| | | auth: ['mes:dv-metering-check:create'], |
| | | onClick: handleCreate, |
| | | }, |
| | | { |
| | | label: $t('ui.actionTitle.export'), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.DOWNLOAD, |
| | | auth: ['mes:dv-metering-check:export'], |
| | | onClick: handleExport, |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #meteringCode="{ row }"> |
| | | <Button type="link" @click="handleDetail(row)"> |
| | | {{ row.meteringCode }} |
| | | </Button> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: $t('common.edit'), |
| | | type: 'link', |
| | | icon: ACTION_ICON.EDIT, |
| | | auth: ['mes:dv-metering-check:update'], |
| | | onClick: handleEdit.bind(null, row), |
| | | }, |
| | | { |
| | | label: $t('common.delete'), |
| | | type: 'link', |
| | | danger: true, |
| | | icon: ACTION_ICON.DELETE, |
| | | auth: ['mes:dv-metering-check:delete'], |
| | | popConfirm: { |
| | | title: $t('ui.actionMessage.deleteConfirm', [row.checkCode]), |
| | | confirm: handleDelete.bind(null, row), |
| | | }, |
| | | }, |
| | | { |
| | | label: $t('common.detail'), |
| | | type: 'link', |
| | | icon: ACTION_ICON.VIEW, |
| | | auth: ['mes:dv-metering-check:query'], |
| | | onClick: handleDetail.bind(null, row), |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | </Grid> |
| | | </Page> |
| | | </template> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { FormType } from '../data'; |
| | | |
| | | import type { MesDvMeteringCheckApi } from '#/api/mes/dv/meteringcheck'; |
| | | |
| | | import { computed, ref } from 'vue'; |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { |
| | | createMeteringCheck, |
| | | getMeteringCheck, |
| | | updateMeteringCheck, |
| | | } from '#/api/mes/dv/meteringcheck'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formType = ref<FormType>('create'); |
| | | const formData = ref<MesDvMeteringCheckApi.MeteringCheck>(); |
| | | const isDetail = computed(() => formType.value === 'detail'); |
| | | const getTitle = computed(() => { |
| | | if (formType.value === 'detail') { |
| | | return 'æ¥çè®¡éæ£æµè®°å½'; |
| | | } |
| | | return formType.value === 'update' ? 'ä¿®æ¹è®¡éæ£æµè®°å½' : 'æ°å¢è®¡éæ£æµè®°å½'; |
| | | }); |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | | componentProps: { |
| | | class: 'w-full', |
| | | }, |
| | | formItemClass: 'col-span-1', |
| | | labelWidth: 110, |
| | | }, |
| | | wrapperClass: 'grid-cols-3', |
| | | layout: 'horizontal', |
| | | schema: [], |
| | | showDefaultActions: false, |
| | | }); |
| | | |
| | | const [Modal, modalApi] = useVbenModal({ |
| | | async onConfirm() { |
| | | if (isDetail.value) { |
| | | await modalApi.close(); |
| | | return; |
| | | } |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | const data = (await formApi.getValues()) as MesDvMeteringCheckApi.MeteringCheck; |
| | | try { |
| | | if (formType.value === 'create') { |
| | | await createMeteringCheck(data); |
| | | } else { |
| | | await updateMeteringCheck(data); |
| | | } |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | await modalApi.close(); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | const data = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = data.formType; |
| | | formApi.setState({ schema: useFormSchema() }); |
| | | formApi.setDisabled(formType.value === 'detail'); |
| | | modalApi.setState({ showConfirmButton: formType.value !== 'detail' }); |
| | | if (!data?.id) { |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getMeteringCheck(data.id); |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | }); |
| | | </script> |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/5"> |
| | | <Form class="mx-4" /> |
| | | </Modal> |
| | | </template> |