diff --git a/components.d.ts b/components.d.ts index 59ed0a0..2b980a0 100644 --- a/components.d.ts +++ b/components.d.ts @@ -38,6 +38,7 @@ declare module 'vue' { WdFab: typeof import('@wot-ui/ui/components/wd-fab/wd-fab.vue')['default'] WdForm: typeof import('@wot-ui/ui/components/wd-form/wd-form.vue')['default'] WdFormItem: typeof import('@wot-ui/ui/components/wd-form-item/wd-form-item.vue')['default'] + WdGap: typeof import('@wot-ui/ui/components/wd-gap/wd-gap.vue')['default'] WdGrid: typeof import('@wot-ui/ui/components/wd-grid/wd-grid.vue')['default'] WdGridItem: typeof import('@wot-ui/ui/components/wd-grid-item/wd-grid-item.vue')['default'] WdIcon: typeof import('@wot-ui/ui/components/wd-icon/wd-icon.vue')['default'] diff --git a/src/App.vue b/src/App.vue index d18088c..afc612e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,3 +9,7 @@ onLaunch(() => { onShow(() => {}); + + diff --git a/src/pages.json b/src/pages.json index 01690ee..61e64e8 100644 --- a/src/pages.json +++ b/src/pages.json @@ -7,7 +7,10 @@ "backgroundTextStyle": "@bgTxtStyle", "backgroundColorTop": "@bgColorTop", "backgroundColorBottom": "@bgColorBottom", - "enablePullDownRefresh": false + "enablePullDownRefresh": false, + "onReachBottomDistance": 50, + "animationType": "pop-in", + "animationDuration": 300 }, "pages": [ // GENERATED BY UNI-PAGES, PLATFORM: H5 || MP-WEIXIN @@ -212,6 +215,8 @@ "subPackages": [], "tabBar": { "custom": true, + "customize": true, + "overlay": true, "height": "0", "color": "@tabColor", "selectedColor": "@tabSelectedColor", diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue index 1ecde95..30ff52c 100644 --- a/src/pages/login/index.vue +++ b/src/pages/login/index.vue @@ -720,18 +720,18 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); display: flex; flex-direction: column; align-items: center; - margin-top: 16rpx; - margin-bottom: 72rpx; + margin-top: 8rpx; + margin-bottom: 40rpx; } .login__logo { - width: 160rpx; - height: 160rpx; - margin-bottom: 32rpx; + width: 120rpx; + height: 120rpx; + margin-bottom: 20rpx; } .login__brand-name { - font-size: 40rpx; + font-size: 36rpx; font-weight: 600; letter-spacing: 0.05em; color: var(--color-text); @@ -739,8 +739,9 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); .login__card { width: 100%; - padding: 64rpx; + padding: 44rpx; background-color: var(--color-bg); + border: 2rpx solid var(--color-border-light); border-radius: 48rpx; box-shadow: 0 20rpx 50rpx -10rpx rgba(0, 0, 0, 0.1); @@ -753,25 +754,25 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); // 卡片头部 .login__card-head { - margin-bottom: 64rpx; + margin-bottom: 36rpx; text-align: center; } .login__card-title { - font-size: 48rpx; + font-size: 40rpx; font-weight: 700; color: var(--color-text); } .login__card-subtitle { display: block; - margin-top: 16rpx; - font-size: 28rpx; + margin-top: 8rpx; + font-size: 26rpx; color: var(--color-text-secondary); } .login__form-item { - margin-top: 32rpx; + margin-top: 28rpx; &:first-child { margin-top: 0; @@ -781,7 +782,7 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); // 覆盖 wd-form-item 默认样式,仅用于校验和错误提示 :deep(.wd-form-item) { padding: 0 !important; - margin-top: 32rpx; + margin-top: 28rpx; background: transparent; &:first-child { @@ -816,7 +817,7 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); .login__field { display: flex; align-items: center; - height: 96rpx; + height: 88rpx; padding: 0 32rpx; background-color: var(--color-bg-secondary); border-radius: 24rpx; @@ -842,7 +843,7 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); align-items: center; justify-content: center; width: 100%; - height: 96rpx; + height: 88rpx; font-size: 32rpx; font-weight: 600; color: var(--color-text-inverse); @@ -884,7 +885,7 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); .login__mode-switch { display: flex; justify-content: center; - padding-top: 32rpx; + padding-top: 24rpx; } .login__mode-switch-text { @@ -903,7 +904,7 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); .login__divider { display: flex; align-items: center; - margin: 48rpx 0; + margin: 32rpx 0; } .login__divider-line { @@ -925,8 +926,8 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); } .login__wx-icon { - width: 80rpx; - height: 80rpx; + width: 72rpx; + height: 72rpx; &:active { transform: scale(0.95); @@ -937,8 +938,8 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); display: flex; align-items: flex-start; justify-content: center; - padding-top: 32rpx; - margin-top: 48rpx; + padding-top: 24rpx; + margin-top: 32rpx; border-top: 2rpx solid var(--color-border-light); } @@ -979,3 +980,28 @@ onShow(() => uni.setNavigationBarTitle({ title: "" })); border-radius: 8rpx; } + + diff --git a/src/pages/work/config/index.vue b/src/pages/work/config/index.vue index eea1650..aeba2a7 100644 --- a/src/pages/work/config/index.vue +++ b/src/pages/work/config/index.vue @@ -51,22 +51,27 @@ {{ formData.id ? "编辑配置" : "新增配置" }} - - - - - + + + + + + + + + + + - + - 取消 + 取消 保存 @@ -77,6 +82,8 @@ @@ -98,7 +105,7 @@ definePage({ import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { LoadMoreState } from "@wot-ui/ui/components/wd-loadmore/types"; -import { FormRules } from "@wot-ui/ui/components/wd-form/types"; +import { toFormSchema } from "@/utils/form"; import { useToast, useDialog } from "@wot-ui/ui"; import ConfigAPI, { type ConfigPageQuery, ConfigItem, ConfigForm } from "@/api/config"; import { hasPermission } from "@/utils/permission"; @@ -128,11 +135,11 @@ const initialFormData: ConfigForm = { const formData = reactive({ ...initialFormData }); -const rules: FormRules = { +const rules = toFormSchema({ configName: [{ required: true, message: "请输入配置名称" }], configKey: [{ required: true, message: "请输入配置键名" }], configValue: [{ required: true, message: "请输入配置键值" }], -}; +}); // 搜索触发 const handleSearch = () => loadConfigList(); @@ -198,17 +205,18 @@ function closeConfigDialog() { } // 操作菜单分发 -function handleActionSelect({ value }: { value: string }) { - const item = currentActionItem.value; +function handleActionSelect({ item }: { item: any }) { + const value = item.name; + const configItem = currentActionItem.value; if (value === "编辑") { - openConfigDialog(item.id); + openConfigDialog(configItem.id); } else if (value === "删除") { messageBox({ title: "确认删除", - msg: `确定要删除配置「${item.configName}」吗?`, + msg: `确定要删除配置「${configItem.configName}」吗?`, type: "warning", }).then(async () => { - await ConfigAPI.deleteById(item.id!); + await ConfigAPI.deleteById(configItem.id!); toast.success("删除成功"); loadConfigList(); }); diff --git a/src/pages/work/dept/index.vue b/src/pages/work/dept/index.vue index b47573f..c67229a 100644 --- a/src/pages/work/dept/index.vue +++ b/src/pages/work/dept/index.vue @@ -43,36 +43,38 @@ {{ formData.id ? "编辑部门" : "新增部门" }} - - + + - - - - - - - - - + + + + + + + + + + + + + - 取消 + 取消 保存 - + { formData.parentId = Number(value[value.length - 1]) || 0; }; -const rules: FormRules = { +const rules = toFormSchema({ name: [{ required: true, message: "请输入部门名称" }], code: [{ required: true, message: "请输入部门编号" }], parentId: [{ required: true, message: "请选择上级部门" }], -}; +}); // 搜索触发 const handleSearch = () => loadDeptList(); @@ -205,7 +207,8 @@ function loadDeptList() { } // 操作菜单分发 -function handleActionSelect({ value }: { value: string }) { +function handleActionSelect({ item }: { item: any }) { + const value = item.name; const dept = currentActionItem.value; if (value === "新增子部门") { handleAddChild(dept); diff --git a/src/pages/work/dict/index.vue b/src/pages/work/dict/index.vue index 17be4f4..002d6fd 100644 --- a/src/pages/work/dict/index.vue +++ b/src/pages/work/dict/index.vue @@ -23,7 +23,7 @@ 字典编码:{{ item.dictCode }} - + {{ item.status === 1 ? "启用" : "禁用" }} @@ -54,21 +54,24 @@ {{ formData.id ? "编辑字典" : "新增字典" }} - - - - - - - + + + + + + + + + + + - + 取消 @@ -84,7 +87,7 @@ @select="handleActionSelect" /> - + @@ -97,7 +100,7 @@ definePage({ import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { useRouter } from "uni-mini-router"; import { LoadMoreState } from "@wot-ui/ui/components/wd-loadmore/types"; -import { FormRules } from "@wot-ui/ui/components/wd-form/types"; +import { toFormSchema } from "@/utils/form"; import { useToast, useDialog } from "@wot-ui/ui"; import DictAPI, { type DictTypeForm, type DictTypePageQuery, type DictTypeItem } from "@/api/dict"; import { hasPermission } from "@/utils/permission"; @@ -124,10 +127,10 @@ const initialFormData: DictTypeForm = { const formData = reactive({ ...initialFormData }); -const rules: FormRules = { +const rules = toFormSchema({ name: [{ required: true, message: "请输入字典名称" }], dictCode: [{ required: true, message: "请输入字典编码" }], -}; +}); const handleSearch = () => loadDictTypeList(); @@ -241,8 +244,8 @@ function showDictActions(item: DictTypeItem) { actionSheetVisible.value = true; } -function handleActionSelect({ value }: { value: string }) { - pendingAction.value[value]?.(); +function handleActionSelect({ item }: { item: any }) { + pendingAction.value[item.name]?.(); } onReachBottom(() => { diff --git a/src/pages/work/dict/item/index.vue b/src/pages/work/dict/item/index.vue index b2a9220..2a511aa 100644 --- a/src/pages/work/dict/item/index.vue +++ b/src/pages/work/dict/item/index.vue @@ -25,7 +25,7 @@ 字典值:{{ item.value }} · 排序:{{ item.sort }} - + {{ item.status === 1 ? "启用" : "禁用" }} @@ -56,24 +56,27 @@ {{ formData.id ? "编辑字典数据" : "新增字典数据" }} - - - - - - - - - - + + + + + + + + + + + + + + - + 取消 @@ -91,6 +94,8 @@ @@ -104,7 +109,7 @@ definePage({ import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { LoadMoreState } from "@wot-ui/ui/components/wd-loadmore/types"; -import { FormRules } from "@wot-ui/ui/components/wd-form/types"; +import { toFormSchema } from "@/utils/form"; import { useToast, useDialog } from "@wot-ui/ui"; import DictAPI, { type DictItemForm, type DictItemPageQuery, type DictDataItem } from "@/api/dict"; import { hasPermission } from "@/utils/permission"; @@ -136,10 +141,10 @@ const initialFormData: DictItemForm = { const formData = reactive({ ...initialFormData }); -const rules: FormRules = { +const rules = toFormSchema({ label: [{ required: true, message: "请输入字典项标签" }], value: [{ required: true, message: "请输入字典项值" }], -}; +}); const handleSearch = () => loadItemList(); @@ -259,8 +264,8 @@ function showItemActions(item: DictDataItem) { actionSheetVisible.value = true; } -function handleActionSelect({ value }: { value: string }) { - pendingAction.value[value]?.(); +function handleActionSelect({ item }: { item: any }) { + pendingAction.value[item.name]?.(); } onReachBottom(() => { diff --git a/src/pages/work/menu/index.vue b/src/pages/work/menu/index.vue index 032ad6d..bdb6ddc 100644 --- a/src/pages/work/menu/index.vue +++ b/src/pages/work/menu/index.vue @@ -52,51 +52,44 @@ {{ formData.id ? "编辑菜单" : "新增菜单" }} - - + + - - - - 目录 - 菜单 - 按钮 - - - - - - - - - - - - - + + + + + + + 目录 + 菜单 + 按钮 + + + + + + + + + + + + + + + + + + + + @@ -107,7 +100,7 @@ - + { formData.parentId = String(value[value.length - 1]) || "0"; }; -const rules: FormRules = { +const rules = toFormSchema({ name: [{ required: true, message: "请输入菜单名称" }], type: [{ required: true, message: "请选择菜单类型" }], parentId: [{ required: true, message: "请选择上级菜单" }], -}; +}); const handleSearch = () => loadMenuList(); @@ -265,7 +258,8 @@ function loadMenuList() { } // 操作菜单分发 -function handleActionSelect({ value }: { value: string }) { +function handleActionSelect({ item }: { item: any }) { + const value = item.name; const menu = currentActionItem.value; if (value === "新增子菜单") { handleAddChild(menu); diff --git a/src/pages/work/notice/index.vue b/src/pages/work/notice/index.vue index fcd2713..f6d0fec 100644 --- a/src/pages/work/notice/index.vue +++ b/src/pages/work/notice/index.vue @@ -27,7 +27,7 @@ {{ item.publisherName || "系统管理员" }} - + {{ getStatusText(item.publishStatus) }} @@ -106,30 +106,31 @@ {{ formData.id ? "编辑通知" : "新增通知" }} - - - - - - - - - - - - - 全体 - 指定用户 - - + + + + + + + + + + + + + + 全体 + 指定用户 + + + - + 取消 @@ -149,6 +150,8 @@ @@ -162,7 +165,7 @@ definePage({ import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { LoadMoreState } from "@wot-ui/ui/components/wd-loadmore/types"; -import { FormRules } from "@wot-ui/ui/components/wd-form/types"; +import { toFormSchema } from "@/utils/form"; import { useToast, useDialog } from "@wot-ui/ui"; import NoticeAPI, { type NoticePageQuery, @@ -197,9 +200,9 @@ const initialFormData: NoticeForm = { }; const formData = reactive({ ...initialFormData }); -const formRules: FormRules = { +const formRules = toFormSchema({ title: [{ required: true, message: "请输入通知标题" }], -}; +}); // 获取状态样式 const getStatusType = ( @@ -387,8 +390,8 @@ function showNoticeActions(item: NoticeItem) { actionSheetVisible.value = true; } -function handleActionSelect({ value }: { value: string }) { - pendingAction.value[value]?.(); +function handleActionSelect({ item }: { item: any }) { + pendingAction.value[item.name]?.(); } onReachBottom(() => { diff --git a/src/pages/work/role/index.vue b/src/pages/work/role/index.vue index d45156d..d53565e 100644 --- a/src/pages/work/role/index.vue +++ b/src/pages/work/role/index.vue @@ -25,7 +25,7 @@ {{ item.code }} - + {{ item.status === 1 ? "正常" : "禁用" }} @@ -70,23 +70,25 @@ {{ formData.id ? "编辑角色" : "新增角色" }} - - - - + + + + + + + + - - - - - - - + + + + + + + 取消 @@ -96,7 +98,7 @@ - + []>([ { label: "自定义部门数据", value: 5 }, ]); -const rules: FormRules = { +const rules = toFormSchema({ name: [{ required: true, message: "请输入角色名称" }], code: [{ required: true, message: "请输入角色编码" }], dataScope: [{ required: true, message: "请选择数据权限" }], -}; +}); // 搜索触发 const handleSearch = () => loadRoleList(); @@ -225,16 +227,17 @@ function closeRoleDialog() { } // 操作菜单分发 -function handleActionSelect({ value }: { value: string }) { - const item = currentActionItem.value; +function handleActionSelect({ item }: { item: any }) { + const value = item.name; + const role = currentActionItem.value; if (value === "编辑") { - openRoleDialog(item.id); + openRoleDialog(role.id); } else if (value === "分配权限") { - handleAssignPerm(item.id); + handleAssignPerm(role.id); } else if (value === "删除") { messageBox({ title: "确认删除", - msg: `确定要删除角色「${item.name}」吗?`, + msg: `确定要删除角色「${role.name}」吗?`, type: "warning", }).then(async () => { await RoleAPI.deleteByIds(String(item.id)); diff --git a/src/pages/work/user/index.vue b/src/pages/work/user/index.vue index 52f4fcc..d0f2c93 100644 --- a/src/pages/work/user/index.vue +++ b/src/pages/work/user/index.vue @@ -71,7 +71,7 @@ {{ item.roleNames }} · {{ item.deptName }} - + {{ item.status === 1 ? "正常" : "禁用" }} @@ -116,36 +116,41 @@ {{ formData.id ? "编辑用户" : "新增用户" }} - - + + - + + + + + + + - - - - - - + + + + + + + + + + 取消 @@ -155,7 +160,7 @@ - + 重置密码 - + - + 取消 @@ -206,7 +205,7 @@ definePage({ import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { LoadMoreState } from "@wot-ui/ui/components/wd-loadmore/types"; -import { FormRules } from "@wot-ui/ui/components/wd-form/types"; +import { toFormSchema } from "@/utils/form"; import { useQueue, useToast, useDialog } from "@wot-ui/ui"; import UserAPI, { type UserPageQuery, UserItem, UserForm } from "@/api/user"; import RoleAPI from "@/api/role"; @@ -288,12 +287,12 @@ const handleDeptConfirm = ({ value, selectedItems }: any) => { formData.deptId = value[value.length - 1]; }; -const rules: FormRules = { +const rules = toFormSchema({ username: [{ required: true, message: "请输入用户名" }], nickname: [{ required: true, message: "请输入昵称" }], roleIds: [{ required: true, message: "请选择角色" }], deptId: [{ required: true, message: "请选择部门" }], -}; +}); // 排序切换 const handleSortChange = ({ value }: { value: string | number }) => { @@ -478,8 +477,8 @@ function showUserActions(item: UserItem) { actionSheetVisible.value = true; } -function handleActionSelect({ value }: { value: string }) { - pendingAction.value[value]?.(); +function handleActionSelect({ item }: { item: any }) { + pendingAction.value[item.name]?.(); } // 打开重置密码弹窗 diff --git a/src/store/modules/theme.ts b/src/store/modules/theme.ts index a1ea074..6d6027b 100644 --- a/src/store/modules/theme.ts +++ b/src/store/modules/theme.ts @@ -29,49 +29,11 @@ export const useThemeStore = defineStore("theme", () => { /** * 深色主题变量(仅在 dark 模式下注入) + * 注意:Wot UI v2 内置了完整的暗黑模式,不需要手动覆盖各个组件变量。 + * 只需在 ConfigProvider 上设置 theme="dark" + 引入官方主题 SCSS 即可。 + * 这里只保留颜色名映射,供自定义 CSS 类使用。 */ - const darkThemeVars = { - darkBackground: "#1f2937", - darkBackground2: "#111827", - darkBackground3: "#1e293b", - darkBackground4: "#374151", - darkBackground5: "#4b5563", - darkBackground6: "#6b7280", - darkBackground7: "#9ca3af", - darkColor: "#f9fafb", - darkColor2: "#9ca3af", - darkColor3: "#6b7280", - filledOppo: "#1f2937", - cardBg: "#1f2937", - cardBorderColor: "#374151", - cardTitleColor: "#f9fafb", - cardContentColor: "#9ca3af", - gridItemBg: "#1f2937", - gridItemTextColor: "#f9fafb", - gridItemIconColor: "#9ca3af", - cellBg: "#1f2937", - popupBg: "#1f2937", - searchBg: "#1f2937", - searchInputBg: "#374151", - inputBg: "#374151", - textareaBg: "#374151", - pickerBg: "#1f2937", - dialogBg: "#1f2937", - actionSheetBg: "#1f2937", - tabsNavBg: "#1f2937", - tabbarBg: "#1f2937", - navbarBg: "#1f2937", - buttonNormalBg: "#374151", - borderMain: "#374151", - borderLight: "#4b5563", - textMain: "#f9fafb", - textSecondary: "#9ca3af", - textPlaceholder: "#6b7280", - iconMain: "#f9fafb", - iconSecondary: "#9ca3af", - baseBlack: "#1f2937", - baseWhite: "#f9fafb", - }; + const darkThemeVars = {}; /** 主题变量(计算属性,根据模式动态切换) */ const themeVars = computed(() => { diff --git a/src/styles/index.scss b/src/styles/index.scss index e5a862f..b86b594 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -118,6 +118,7 @@ body { font-weight: bold; font-size: 32rpx; margin-bottom: 16rpx; + color: var(--wot-text-main); } diff --git a/src/styles/theme.scss b/src/styles/theme.scss index 1825263..fe7fe80 100644 --- a/src/styles/theme.scss +++ b/src/styles/theme.scss @@ -19,7 +19,6 @@ page { --z-dialog: 500; --z-toast: 600; --z-navbar: 700; - --z-fab: 800; // ----------------------------------------------------------------------- // 主题色 @@ -84,19 +83,10 @@ page { --shadow-lg: 0 20rpx 30rpx rgba(0, 0, 0, 0.1); // ----------------------------------------------------------------------- - // wot-design-uni 组件库变量 + // 以下只保留主色调自定义,其余交给 Wot UI 官方主题 // ----------------------------------------------------------------------- --wot-color-theme: var(--color-primary); - --wot-color-success: var(--color-success); - --wot-color-warning: var(--color-warning); - --wot-color-danger: var(--color-danger); - --wot-button-normal-bg: var(--color-bg); - --wot-color-bg: var(--color-bg); - --wot-color-bg-light: var(--color-bg-secondary); - --wot-color-text: var(--color-text); - --wot-color-text-secondary: var(--color-text-secondary); - --wot-color-text-placeholder: var(--color-text-placeholder); - --wot-color-border: var(--color-border); + --wot-fab-z-index: 999; // ----------------------------------------------------------------------- // 间距规范(8rpx 网格基数) @@ -183,20 +173,7 @@ page { --shadow-lg: 0 20rpx 30rpx rgba(0, 0, 0, 0.4); // ----------------------------------------------------------------------- - // wot-design-uni 组件库变量 + // 以下只保留主色调自定义,其余交给 Wot UI 官方暗黑模式 // ----------------------------------------------------------------------- --wot-color-theme: var(--color-primary); - --wot-color-success: var(--color-success); - --wot-color-warning: var(--color-warning); - --wot-color-danger: var(--color-danger); - --wot-button-normal-bg: var(--color-bg-secondary); - --wot-color-bg: var(--color-bg); - --wot-color-bg-light: var(--color-bg-secondary); - --wot-color-text: var(--color-text); - --wot-color-text-secondary: var(--color-text-secondary); - --wot-color-text-placeholder: var(--color-text-placeholder); - --wot-color-border: var(--color-border); - --wot-radio-button-bg: var(--color-bg-tertiary); - --wot-radio-button-checked-bg: var(--color-primary); - --wot-radio-label-color: var(--color-text); } diff --git a/src/types/auto-imports.d.ts b/src/types/auto-imports.d.ts index cae3dda..a1d5181 100644 --- a/src/types/auto-imports.d.ts +++ b/src/types/auto-imports.d.ts @@ -136,6 +136,7 @@ declare global { const theme: typeof import('../composables/types/theme')['theme'] const themeColorOptions: typeof import('../composables/useTheme')['themeColorOptions'] const themeVars: typeof import('../composables/types/theme')['themeVars'] + const toFormSchema: typeof import('../utils/form')['toFormSchema'] const toRaw: typeof import('vue')['toRaw'] const toRef: typeof import('vue')['toRef'] const toRefs: typeof import('vue')['toRefs'] @@ -337,6 +338,7 @@ declare module 'vue' { readonly store: UnwrapRef readonly storeToRefs: UnwrapRef readonly themeColorOptions: UnwrapRef + readonly toFormSchema: UnwrapRef readonly toRaw: UnwrapRef readonly toRef: UnwrapRef readonly toRefs: UnwrapRef diff --git a/src/utils/form.ts b/src/utils/form.ts new file mode 100644 index 0000000..dd182d4 --- /dev/null +++ b/src/utils/form.ts @@ -0,0 +1,36 @@ +import type { FormSchema } from "@wot-ui/ui/components/wd-form/types"; + +/** + * v1 FormRules → v2 FormSchema 适配器 + * 将旧版 rules 格式转换为 v2 的 schema 格式 + */ +export function toFormSchema( + rules: Record +): FormSchema { + return { + validate(model: Record) { + const issues: { path: Array; message: string }[] = []; + for (const [field, fieldRules] of Object.entries(rules)) { + const value = model[field]; + for (const rule of fieldRules) { + if (rule.required) { + const isEmpty = + value === undefined || + value === null || + (typeof value === "string" && value.trim() === "") || + (Array.isArray(value) && value.length === 0); + if (isEmpty) { + issues.push({ path: [field], message: rule.message || `${field} 为必填项` }); + break; + } + } + if (rule.pattern && typeof value === "string" && !rule.pattern.test(value)) { + issues.push({ path: [field], message: rule.message || `${field} 格式不正确` }); + break; + } + } + } + return issues; + }, + }; +}