diff --git a/.changeset/.prettierrc.json b/.changeset/.prettierrc.json new file mode 100644 index 000000000..544138be4 --- /dev/null +++ b/.changeset/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/.changeset/fancy-ears-walk.md b/.changeset/fancy-ears-walk.md new file mode 100644 index 000000000..f73cb596b --- /dev/null +++ b/.changeset/fancy-ears-walk.md @@ -0,0 +1,7 @@ +--- +'@vben/styles': patch +'@vben-core/form-ui': patch +'@vben/web-naive': patch +--- + +feat(@core/form-ui): 新增 useVbenForm 数组编辑器 VbenFormFieldArray diff --git a/apps/web-antd/src/api/bpm/oa/leave/index.ts b/apps/web-antd/src/api/bpm/oa/leave/index.ts index b1afbd255..440674bdd 100644 --- a/apps/web-antd/src/api/bpm/oa/leave/index.ts +++ b/apps/web-antd/src/api/bpm/oa/leave/index.ts @@ -21,11 +21,6 @@ export async function createLeave(data: BpmOALeaveApi.Leave) { return requestClient.post('/bpm/oa/leave/create', data); } -/** 更新请假申请 */ -export async function updateLeave(data: BpmOALeaveApi.Leave) { - return requestClient.post('/bpm/oa/leave/update', data); -} - /** 获得请假申请 */ export async function getLeave(id: number) { return requestClient.get(`/bpm/oa/leave/get?id=${id}`); diff --git a/apps/web-antd/src/api/crm/receivable/plan/index.ts b/apps/web-antd/src/api/crm/receivable/plan/index.ts index c4279d8ca..e192b9808 100644 --- a/apps/web-antd/src/api/crm/receivable/plan/index.ts +++ b/apps/web-antd/src/api/crm/receivable/plan/index.ts @@ -29,6 +29,10 @@ export namespace CrmReceivablePlanApi { returnTime: Date; }; } + export interface PlanPageParam extends PageParam { + customerId?: number; + contractId?: number; + } } /** 查询回款计划列表 */ diff --git a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue index 1ac758a6d..b288676f7 100644 --- a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue +++ b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/child-process-node-config.vue @@ -293,7 +293,7 @@ const showChildProcessNodeConfig = (node: SimpleFlowNode) => { if (configForm.value.timeoutType === DelayTypeEnum.FIXED_TIME_DURATION) { const strTimeDuration = node.childProcessSetting.timeoutSetting.timeExpression ?? ''; - const parseTime = strTimeDuration.slice(2, -1); + const parseTime = strTimeDuration.match(/\d+/)?.[0] ?? ''; const parseTimeUnit = strTimeDuration.slice(-1); configForm.value.timeDuration = Number.parseInt(parseTime); configForm.value.timeUnit = convertTimeUnit(parseTimeUnit); @@ -359,12 +359,12 @@ const loadFormInfo = async () => { }; const getIsoTimeDuration = () => { - let strTimeDuration = 'PT'; + let strTimeDuration = 'P'; if (configForm.value.timeUnit === TimeUnitType.MINUTE) { - strTimeDuration += `${configForm.value.timeDuration}M`; + strTimeDuration += `T${configForm.value.timeDuration}M`; } if (configForm.value.timeUnit === TimeUnitType.HOUR) { - strTimeDuration += `${configForm.value.timeDuration}H`; + strTimeDuration += `T${configForm.value.timeDuration}H`; } if (configForm.value.timeUnit === TimeUnitType.DAY) { strTimeDuration += `${configForm.value.timeDuration}D`; diff --git a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue index 0e0ac4cc3..6f578229d 100644 --- a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue +++ b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue @@ -84,12 +84,12 @@ function getShowText(): string { // 获取ISO时间格式 function getIsoTimeDuration() { - let strTimeDuration = 'PT'; + let strTimeDuration = 'P'; if (configForm.value.timeUnit === TimeUnitType.MINUTE) { - strTimeDuration += `${configForm.value.timeDuration}M`; + strTimeDuration += `T${configForm.value.timeDuration}M`; } if (configForm.value.timeUnit === TimeUnitType.HOUR) { - strTimeDuration += `${configForm.value.timeDuration}H`; + strTimeDuration += `T${configForm.value.timeDuration}H`; } if (configForm.value.timeUnit === TimeUnitType.DAY) { strTimeDuration += `${configForm.value.timeDuration}D`; @@ -135,7 +135,7 @@ function openDrawer(node: SimpleFlowNode) { // 固定时长 if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) { const strTimeDuration = node.delaySetting.delayTime; - const parseTime = strTimeDuration.slice(2, -1); + const parseTime = strTimeDuration.match(/\d+/)?.[0] ?? ''; const parseTimeUnit = strTimeDuration.slice(-1); configForm.value.timeDuration = Number.parseInt(parseTime); configForm.value.timeUnit = convertTimeUnit(parseTimeUnit); diff --git a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue index 2afdd6f97..98373821a 100644 --- a/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue +++ b/apps/web-antd/src/views/bpm/components/simple-process-design/components/nodes-config/user-task-node-config.vue @@ -417,7 +417,7 @@ function showUserTaskNodeConfig(node: SimpleFlowNode) { configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable; if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) { const strTimeDuration = node.timeoutHandler.timeDuration; - const parseTime = strTimeDuration.slice(2, -1); + const parseTime = strTimeDuration.match(/\d+/)?.[0] ?? ''; const parseTimeUnit = strTimeDuration.slice(-1); configForm.value.timeDuration = Number.parseInt(parseTime); timeUnit.value = convertTimeUnit(parseTimeUnit); @@ -563,12 +563,12 @@ function useTimeoutHandler() { if (!configForm.value.timeoutHandlerEnable) { return undefined; } - let strTimeDuration = 'PT'; + let strTimeDuration = 'P'; if (timeUnit.value === TimeUnitType.MINUTE) { - strTimeDuration += `${configForm.value.timeDuration}M`; + strTimeDuration += `T${configForm.value.timeDuration}M`; } if (timeUnit.value === TimeUnitType.HOUR) { - strTimeDuration += `${configForm.value.timeDuration}H`; + strTimeDuration += `T${configForm.value.timeDuration}H`; } if (timeUnit.value === TimeUnitType.DAY) { strTimeDuration += `${configForm.value.timeDuration}D`; diff --git a/apps/web-antd/src/views/bpm/oa/leave/create.vue b/apps/web-antd/src/views/bpm/oa/leave/create.vue index 9363959f3..cbe2086b4 100644 --- a/apps/web-antd/src/views/bpm/oa/leave/create.vue +++ b/apps/web-antd/src/views/bpm/oa/leave/create.vue @@ -14,7 +14,7 @@ import { Button, Card, Col, message, Row, Space } from 'ant-design-vue'; import dayjs from 'dayjs'; import { getProcessDefinition } from '#/api/bpm/definition'; -import { createLeave, getLeave, updateLeave } from '#/api/bpm/oa/leave'; +import { createLeave, getLeave } from '#/api/bpm/oa/leave'; import { getApprovalDetail as getApprovalDetailApi } from '#/api/bpm/processInstance'; import { $t } from '#/locales'; import { router } from '#/router'; @@ -88,9 +88,7 @@ async function onSubmit() { }; try { formLoading.value = true; - await (formData.value?.id - ? updateLeave(submitData) - : createLeave(submitData)); + await createLeave(submitData); // 关闭并提示 message.success($t('ui.actionMessage.operationSuccess')); await closeCurrentTab(); diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/modules/time-line.vue b/apps/web-antd/src/views/bpm/processInstance/detail/modules/time-line.vue index 68fde46df..69d13ddf9 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/modules/time-line.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/modules/time-line.vue @@ -198,7 +198,7 @@ function shouldShowCustomUserSelect( function shouldShowApprovalReason(task: any, nodeType: BpmNodeTypeEnum) { return ( task.reason && - [BpmNodeTypeEnum.END_EVENT_NODE, BpmNodeTypeEnum.USER_TASK_NODE].includes( + [BpmNodeTypeEnum.START_USER_NODE, BpmNodeTypeEnum.USER_TASK_NODE].includes( nodeType, ) ); diff --git a/apps/web-antd/src/views/dashboard/workspace/index.vue b/apps/web-antd/src/views/dashboard/workspace/index.vue index 8f6620310..1cfbef1bc 100644 --- a/apps/web-antd/src/views/dashboard/workspace/index.vue +++ b/apps/web-antd/src/views/dashboard/workspace/index.vue @@ -238,7 +238,7 @@ function navTo(nav: WorkbenchProjectItem | WorkbenchQuickNavItem) { -
+
@@ -246,7 +246,7 @@ function navTo(nav: WorkbenchProjectItem | WorkbenchQuickNavItem) {
diff --git a/apps/web-antd/src/views/mes/pro/route/components/color-picker.vue b/apps/web-antd/src/views/mes/pro/route/components/color-picker.vue index 76623fcb0..f3edab9f5 100644 --- a/apps/web-antd/src/views/mes/pro/route/components/color-picker.vue +++ b/apps/web-antd/src/views/mes/pro/route/components/color-picker.vue @@ -51,12 +51,12 @@ function handleColorChange(event: Event) { diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue index 4ffbb62c0..3f86e68f3 100644 --- a/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/bpm-viewer.vue @@ -33,6 +33,7 @@ watch( view.value = newModelView; } }, + { immediate: true }, ); /** 监听 bpmnXml */ diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue index 907b73677..20d6dc7c2 100644 --- a/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/operation-button.vue @@ -278,7 +278,7 @@ async function openPopover(type: string) { } } Object.keys(popOverVisible.value).forEach((item) => { - if (popOverVisible.value[item]) popOverVisible.value[item] = item === type; + popOverVisible.value[item] = item === type; }); if (type === 'approve') { // 当前任务有节点表单时,等 form-create 的 fApi 就绪后再计算下一个节点; diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue index 751f390ca..6e4c65982 100644 --- a/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue @@ -56,6 +56,7 @@ watch( simpleModel.value = newModelView.simpleModel || {}; } }, + { immediate: true }, ); /** 监控模型结构数据 */ diff --git a/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue index f085a6385..02e4c6382 100644 --- a/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue +++ b/apps/web-ele/src/views/bpm/processInstance/detail/modules/time-line.vue @@ -205,7 +205,7 @@ function shouldShowCustomUserSelect( function shouldShowApprovalReason(task: any, nodeType: BpmNodeTypeEnum) { return ( task.reason && - [BpmNodeTypeEnum.END_EVENT_NODE, BpmNodeTypeEnum.USER_TASK_NODE].includes( + [BpmNodeTypeEnum.START_USER_NODE, BpmNodeTypeEnum.USER_TASK_NODE].includes( nodeType, ) ); diff --git a/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue index c4f704cf5..552f8ef13 100644 --- a/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue +++ b/apps/web-ele/src/views/mall/trade/delivery/pickUpOrder/index.vue @@ -21,7 +21,7 @@ import { import { useGridColumns, useGridFormSchema } from './data'; // TODO @芋艿:风格和 antd 不一致; -const summary = ref(); +const summary = ref(); /** 刷新表格 */ function handleRefresh() { diff --git a/apps/web-ele/src/views/mes/pro/task/components/gantt-chart.vue b/apps/web-ele/src/views/mes/pro/task/components/gantt-chart.vue index dca1347c9..497cbff51 100644 --- a/apps/web-ele/src/views/mes/pro/task/components/gantt-chart.vue +++ b/apps/web-ele/src/views/mes/pro/task/components/gantt-chart.vue @@ -89,8 +89,20 @@ function initGantt() { gantt.config.columns = [ { name: 'text', label: '任务名称', tree: true, width: 180, resize: true }, - { name: 'workstation', label: '工作站', align: 'center', width: 100, resize: true }, - { name: 'process', label: '工序', align: 'center', width: 100, resize: true }, + { + name: 'workstation', + label: '工作站', + align: 'center', + width: 100, + resize: true, + }, + { + name: 'process', + label: '工序', + align: 'center', + width: 100, + resize: true, + }, { name: 'start_date', label: '开始时间', align: 'center', width: 130 }, { name: 'end_date', label: '结束时间', align: 'center', width: 130 }, ]; @@ -194,7 +206,10 @@ defineExpose({ loadData }); `; + + // 使用自定义选择器(如 TDesign 的 theme-mode 选择器)更新 CSS 变量 + updateCSSVariables( + { '--td-brand-color': 'rgb(0, 82, 217)' }, + 'tdesign-styles', + ":root[theme-mode='dark']", + ); + + const styleElement = document.querySelector('#tdesign-styles'); + const content = styleElement?.textContent ?? ''; + + // 选择器与变量都应正确写入 + expect(content.startsWith(":root[theme-mode='dark'] {")).toBe(true); + expect(content.includes('--td-brand-color: rgb(0, 82, 217);')).toBe(true); +}); diff --git a/packages/@core/base/shared/src/utils/update-css-variables.ts b/packages/@core/base/shared/src/utils/update-css-variables.ts index 657deaa7d..296e2e57c 100644 --- a/packages/@core/base/shared/src/utils/update-css-variables.ts +++ b/packages/@core/base/shared/src/utils/update-css-variables.ts @@ -1,10 +1,15 @@ /** * 更新 CSS 变量的函数 * @param variables 要更新的 CSS 变量与其新值的映射 + * @param id 内联样式表的 id,便于复用与覆盖 + * @param selector CSS 变量挂载的选择器,默认 `:root`。 + * 对于像 TDesign 这种将变量定义在 `:root[theme-mode='dark']` 等更高优先级选择器下的组件库, + * 需要传入相同(或更高)优先级的选择器才能正确覆盖。 */ function updateCSSVariables( variables: { [key: string]: string }, id = '__vben-styles__', + selector = ':root', ): void { // 获取或创建内联样式表元素 const styleElement = @@ -13,7 +18,7 @@ function updateCSSVariables( styleElement.id = id; // 构建要更新的 CSS 变量的样式文本 - let cssText = ':root {'; + let cssText = `${selector} {`; for (const key in variables) { if (Object.prototype.hasOwnProperty.call(variables, key)) { cssText += `${key}: ${variables[key]};`; diff --git a/packages/@core/composables/src/use-simple-locale/messages.ts b/packages/@core/composables/src/use-simple-locale/messages.ts index efc5c3cc7..671ae33c2 100644 --- a/packages/@core/composables/src/use-simple-locale/messages.ts +++ b/packages/@core/composables/src/use-simple-locale/messages.ts @@ -9,6 +9,7 @@ export const messages: Record> = { prompt: 'Prompt', reset: 'Reset', submit: 'Submit', + confirmTitle: 'Please Confirm', }, 'zh-CN': { cancel: '取消', @@ -18,6 +19,7 @@ export const messages: Record> = { prompt: '提示', reset: '重置', submit: '提交', + confirmTitle: '请确认', }, }; diff --git a/packages/@core/ui-kit/form-ui/src/components/form-field-array.vue b/packages/@core/ui-kit/form-ui/src/components/form-field-array.vue new file mode 100644 index 000000000..1d7a0730a --- /dev/null +++ b/packages/@core/ui-kit/form-ui/src/components/form-field-array.vue @@ -0,0 +1,177 @@ + + + diff --git a/packages/@core/ui-kit/form-ui/src/config.ts b/packages/@core/ui-kit/form-ui/src/config.ts index 645f51f3b..9448d2ac1 100644 --- a/packages/@core/ui-kit/form-ui/src/config.ts +++ b/packages/@core/ui-kit/form-ui/src/config.ts @@ -20,6 +20,8 @@ import { globalShareState } from '@vben-core/shared/global-state'; import { defineRule } from 'vee-validate'; +import VbenFormFieldArray from './components/form-field-array.vue'; + const DEFAULT_MODEL_PROP_NAME = 'modelValue'; export const DEFAULT_FORM_COMMON_CONFIG: FormCommonConfig = {}; @@ -28,6 +30,7 @@ export const COMPONENT_MAP: Record = { DefaultButton: h(VbenButton, { size: 'sm', variant: 'outline' }), PrimaryButton: h(VbenButton, { size: 'sm', variant: 'default' }), VbenCheckbox, + VbenFormFieldArray, VbenInput, VbenInputPassword, VbenPinInput, diff --git a/packages/@core/ui-kit/form-ui/src/index.ts b/packages/@core/ui-kit/form-ui/src/index.ts index 9bb3fd33c..90006842f 100644 --- a/packages/@core/ui-kit/form-ui/src/index.ts +++ b/packages/@core/ui-kit/form-ui/src/index.ts @@ -4,6 +4,7 @@ export type { BaseFormComponentType, ExtendedFormApi, FormLayout, + VbenFormFieldArrayProps, VbenFormProps, FormSchema as VbenFormSchema, } from './types'; diff --git a/packages/@core/ui-kit/form-ui/src/types.ts b/packages/@core/ui-kit/form-ui/src/types.ts index 7b6f53d64..8aea697f6 100644 --- a/packages/@core/ui-kit/form-ui/src/types.ts +++ b/packages/@core/ui-kit/form-ui/src/types.ts @@ -14,6 +14,7 @@ export type BaseFormComponentType = | 'DefaultButton' | 'PrimaryButton' | 'VbenCheckbox' + | 'VbenFormFieldArray' | 'VbenInput' | 'VbenInputPassword' | 'VbenPinInput' @@ -309,6 +310,32 @@ export type FormSchema< P extends Record = Record, > = FormSchemaDiscriminated | FormSchemaFallback; +/** + * 数组编辑器(VbenFormFieldArray)的组件参数 + */ +export interface VbenFormFieldArrayProps< + T extends BaseFormComponentType = BaseFormComponentType, + P extends Record = Record, +> { + /** 操作列表头文案 */ + actionText?: string; + /** 「添加」按钮文案 */ + addButtonText?: string; + /** 新增一行时生成的默认数据;缺省时按列定义的 fieldName 生成空对象 */ + createRow?: () => Record; + disabled?: boolean; + /** 空数据文案 */ + emptyText?: string; + /** 最多行数 */ + max?: number; + /** 最少行数 */ + min?: number; + /** 列定义,每一列是一个子字段(复用 FormSchema) */ + schema: FormSchema[]; + /** 是否显示序号列 */ + showIndex?: boolean; +} + export type HandleSubmitFn = ( values: Record, ) => Promise | void; diff --git a/packages/@core/ui-kit/form-ui/src/use-vben-form.ts b/packages/@core/ui-kit/form-ui/src/use-vben-form.ts index 00c60d05b..da3c57d90 100644 --- a/packages/@core/ui-kit/form-ui/src/use-vben-form.ts +++ b/packages/@core/ui-kit/form-ui/src/use-vben-form.ts @@ -6,7 +6,7 @@ import type { import { defineComponent, h, isReactive, onBeforeUnmount, watch } from 'vue'; -import { useStore } from '@vben-core/shared/store'; +import { useSelector } from '@vben-core/shared/store'; import { FormApi } from './form-api'; import VbenUseForm from './vben-use-form.vue'; @@ -19,7 +19,7 @@ export function useVbenForm< const api = new FormApi(options as unknown as VbenFormProps); const extendedApi: ExtendedFormApi = api as never; extendedApi.useStore = (selector) => { - return useStore(api.store, selector); + return useSelector(api.store, selector); }; const Form = defineComponent( diff --git a/packages/@core/ui-kit/menu-ui/src/components/menu-item.vue b/packages/@core/ui-kit/menu-ui/src/components/menu-item.vue index e9236aaf4..017026423 100644 --- a/packages/@core/ui-kit/menu-ui/src/components/menu-item.vue +++ b/packages/@core/ui-kit/menu-ui/src/components/menu-item.vue @@ -37,7 +37,7 @@ const menuIcon = computed(() => const isHttp = computed(() => isHttpUrl(item.parentPaths.at(-1))); const isTopLevelMenuItem = computed( - () => parentMenu.value?.type.name === 'Menu', + () => parentMenu.value?.type.name === 'MenuUI', ); const collapseShowTitle = computed( diff --git a/packages/@core/ui-kit/menu-ui/src/components/menu.vue b/packages/@core/ui-kit/menu-ui/src/components/menu.vue index acb243fc8..5d9f5780a 100644 --- a/packages/@core/ui-kit/menu-ui/src/components/menu.vue +++ b/packages/@core/ui-kit/menu-ui/src/components/menu.vue @@ -37,7 +37,7 @@ import SubMenu from './sub-menu.vue'; interface Props extends MenuProps {} -defineOptions({ name: 'Menu' }); +defineOptions({ name: 'MenuUI' }); const props = withDefaults(defineProps(), { accordion: true, diff --git a/packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue b/packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue index 5c8c8a860..afc0afa16 100644 --- a/packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue +++ b/packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue @@ -54,7 +54,7 @@ const opened = computed(() => { return rootMenu?.openedMenus.includes(props.path); }); const isTopLevelMenuSubmenu = computed( - () => parentMenu.value?.type.name === 'Menu', + () => parentMenu.value?.type.name === 'MenuUI', ); const mode = computed(() => rootMenu?.props.mode ?? 'vertical'); const rounded = computed(() => rootMenu?.props.rounded); diff --git a/packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts b/packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts index 357b296b9..1e3955dcd 100644 --- a/packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts +++ b/packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts @@ -42,7 +42,7 @@ function useSubMenuContext() { if (!instance) { throw new Error('instance is required'); } - const parentMenu = findComponentUpward(instance, ['Menu', 'SubMenu']); + const parentMenu = findComponentUpward(instance, ['MenuUI', 'SubMenu']); const subMenu = inject(`subMenu:${parentMenu?.uid}`) as SubMenuProvider; return subMenu; } diff --git a/packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts b/packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts index 9207445f9..0ee93fd9a 100644 --- a/packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts +++ b/packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts @@ -16,7 +16,7 @@ function useMenu() { const parentPaths = computed(() => { let parent = instance.parent; const paths: string[] = [instance.props.path as string]; - while (parent?.type.name !== 'Menu') { + while (parent?.type.name !== 'MenuUI') { if (parent?.props.path) { paths.unshift(parent.props.path as string); } @@ -27,7 +27,7 @@ function useMenu() { }); const parentMenu = computed(() => { - return findComponentUpward(instance, ['Menu', 'SubMenu']); + return findComponentUpward(instance, ['MenuUI', 'SubMenu']); }); return { diff --git a/packages/@core/ui-kit/popup-ui/src/alert/alert.vue b/packages/@core/ui-kit/popup-ui/src/alert/alert.vue index d49e0cc8b..fd7b95dff 100644 --- a/packages/@core/ui-kit/popup-ui/src/alert/alert.vue +++ b/packages/@core/ui-kit/popup-ui/src/alert/alert.vue @@ -156,7 +156,7 @@ async function handleOpenChange(val: boolean) { :class=" cn( containerClass, - 'inset-x-0 mx-auto flex max-h-[80%] flex-col p-0 duration-300 sm:w-130 sm:max-w-[80%] sm:rounded-(--radius)', + 'flex max-h-[80%] flex-col p-0 duration-300 sm:w-130 sm:max-w-[80%] sm:rounded-(--radius)', { 'border border-border': bordered, 'shadow-3xl': !bordered, @@ -197,7 +197,7 @@ async function handleOpenChange(val: boolean) { {{ cancelText || $t('cancel') }} diff --git a/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue b/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue index 0a7fd35f0..5abbf3823 100644 --- a/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue +++ b/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue @@ -54,7 +54,8 @@ const components = globalShareState.getComponents(); const id = useId(); provide('DISMISSABLE_DRAWER_ID', id); -// const wrapperRef = ref(); +// @ts-expect-error unused +const wrapperRef = ref(); const { $t } = useSimpleLocale(); const { isMobile } = useIsMobile(); @@ -285,8 +286,8 @@ const getForceMount = computed(() => { -
import type { ExtendedModalApi, ModalProps } from './modal'; -import { - computed, - nextTick, - onDeactivated, - provide, - ref, - unref, - useId, - watch, -} from 'vue'; +import { computed, nextTick, onDeactivated, ref, unref, watch } from 'vue'; -import { - useIsMobile, - usePriorityValues, - useSimpleLocale, -} from '@vben-core/composables'; +import { usePriorityValues, useSimpleLocale } from '@vben-core/composables'; import { Expand, Shrink } from '@vben-core/icons'; import { Dialog, @@ -57,12 +44,7 @@ const headerRef = ref(); // @ts-expect-error unused const footerRef = ref(); -const id = useId(); - -provide('DISMISSABLE_MODAL_ID', id); - const { $t } = useSimpleLocale(); -const { isMobile } = useIsMobile(); const state = props.modalApi?.useStore?.(); const { @@ -101,7 +83,7 @@ const { zIndex, } = usePriorityValues(props, state); -const shouldFullscreen = computed(() => fullscreen.value || isMobile.value); +const shouldFullscreen = computed(() => fullscreen.value); const shouldDraggable = computed( () => draggable.value && !shouldFullscreen.value && header.value, @@ -199,15 +181,8 @@ function handleOpenAutoFocus(e: Event) { // pointer-down-outside function pointerDownOutside(e: Event) { - const target = e.target as HTMLElement; - const isDismissableModal = target?.dataset.dismissableModal; - if ( - !closeOnClickModal.value || - isDismissableModal !== id || - submitting.value - ) { + if (!closeOnClickModal.value || submitting.value) { e.preventDefault(); - e.stopPropagation(); } } @@ -216,6 +191,10 @@ function handleFocusOutside(e: Event) { e.stopPropagation(); } +function handleCloseAutoFocus(_e: Event) { + // allow reka-ui to return focus to the trigger element on close +} + const getForceMount = computed(() => { return !unref(destroyOnClose) && unref(firstOpened); }); @@ -233,7 +212,7 @@ function handleClosed() {