diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 352ed11e..ae927803 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -62,7 +62,7 @@ body: description: Before submitting the issue, please make sure you do the following # description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com). options: - - label: Read the [docs](https://anncwb.github.io/vue-vben-admin-doc/) + - label: Read the [docs](https://doc.vben.pro/) required: true - label: Ensure the code is up to date. (Some issues have been fixed in the latest version) required: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index e40eac66..393334e8 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -62,7 +62,7 @@ body: label: Validations description: Before submitting the issue, please make sure you do the following options: - - label: Read the [docs](https://anncwb.github.io/vue-vben-admin-doc/) + - label: Read the [docs](https://doc.vben.pro/) required: true - label: Ensure the code is up to date. (Some issues have been fixed in the latest version) required: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a94800..14e99aa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 1.1.3 + +**Bug Fixes** + +- 节点树在编辑 & 空数组(不勾选)情况 勾选节点会造成watch延迟触发 导致会带上父节点id造成id重复 +- 节点树在节点独立情况下的控制台warning: Invalid prop: type check failed for prop "value". Expected Array, got Object + +**Others** + +- 角色管理 优化Drawer布局 +- unplugin-vue-components插件(默认未开启) 需要排除Button组件 全局已经默认导入了 + # 1.1.2 **Features** diff --git a/apps/web-antd/src/adapter/component/index.ts b/apps/web-antd/src/adapter/component/index.ts index f5bb321e..9f8a059f 100644 --- a/apps/web-antd/src/adapter/component/index.ts +++ b/apps/web-antd/src/adapter/component/index.ts @@ -8,7 +8,7 @@ import type { BaseFormComponentType } from '@vben/common-ui'; import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState } from '@vben/common-ui'; +import { ApiSelect, globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { @@ -51,6 +51,7 @@ const withDefaultPlaceholder = ( // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 export type ComponentType = + | 'ApiSelect' | 'AutoComplete' | 'Checkbox' | 'CheckboxGroup' @@ -58,6 +59,7 @@ export type ComponentType = | 'DefaultButton' | 'Divider' | 'FileUpload' + | 'IconPicker' | 'ImageUpload' | 'Input' | 'InputNumber' @@ -83,7 +85,20 @@ async function initComponentAdapter() { // 如果你的组件体积比较大,可以使用异步加载 // Button: () => // import('xxx').then((res) => res.Button), - + ApiSelect: (props, { attrs, slots }) => { + return h( + ApiSelect, + { + ...props, + ...attrs, + component: Select, + loadingSlot: 'suffixIcon', + visibleEvent: 'onDropdownVisibleChange', + modelField: 'value', + }, + slots, + ); + }, AutoComplete, Checkbox, CheckboxGroup, @@ -93,6 +108,7 @@ async function initComponentAdapter() { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, + IconPicker, Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), diff --git a/apps/web-antd/src/components/tree/src/tree-select-panel.vue b/apps/web-antd/src/components/tree/src/tree-select-panel.vue index 5c9a6a81..9a2a7744 100644 --- a/apps/web-antd/src/components/tree/src/tree-select-panel.vue +++ b/apps/web-antd/src/components/tree/src/tree-select-panel.vue @@ -8,6 +8,7 @@ import { computed, nextTick, onMounted, type PropType, ref, watch } from 'vue'; import { findGroupParentIds, treeToList } from '@vben/utils'; import { Checkbox, Tree } from 'ant-design-vue'; +import { uniq } from 'lodash-es'; /** 需要禁止透传 */ defineOptions({ inheritAttrs: false }); @@ -73,6 +74,8 @@ const checkedRealKeys = ref<(number | string)[]>([]); /** * 取第一次的menuTree id 设置到checkedMenuKeys * 主要为了解决没有任何修改 直接点击保存的情况 + * + * length为0情况(即新增时候没有勾选节点) 勾选这里会延迟触发 节点会拼接上父节点 导致ID重复 */ const stop = watch([checkedKeys, () => props.treeData], () => { if ( @@ -86,7 +89,10 @@ const stop = watch([checkedKeys, () => props.treeData], () => { checkedKeys.value as any, { id: props.fieldNames.key }, ); - checkedRealKeys.value = [...parentIds, ...checkedKeys.value]; + /** + * uniq 解决上面的id重复问题 + */ + checkedRealKeys.value = uniq([...parentIds, ...checkedKeys.value]); stop(); } if (!props.checkStrictly && checkedKeys.value.length > 0) { @@ -98,19 +104,21 @@ const stop = watch([checkedKeys, () => props.treeData], () => { /** * - * @param checkedKeys 已经选中的子节点的ID + * @param checkedStateKeys 已经选中的子节点的ID * @param info info.halfCheckedKeys为父节点的ID */ type CheckedState = | { checked: T[]; halfChecked: T[] } | T[]; -function handleChecked(checkedKeys: CheckedState, info: CheckInfo) { +function handleChecked(checkedStateKeys: CheckedState, info: CheckInfo) { // 数组的话为节点关联 - if (Array.isArray(checkedKeys)) { + if (Array.isArray(checkedStateKeys)) { const halfCheckedKeys: number[] = (info.halfCheckedKeys || []) as number[]; - checkedRealKeys.value = [...halfCheckedKeys, ...checkedKeys]; + checkedRealKeys.value = [...halfCheckedKeys, ...checkedStateKeys]; } else { - checkedRealKeys.value = [...checkedKeys.checked]; + checkedRealKeys.value = [...checkedStateKeys.checked]; + // fix: Invalid prop: type check failed for prop "value". Expected Array, got Object + checkedKeys.value = [...checkedStateKeys.checked]; } } @@ -137,9 +145,10 @@ function handleCheckStrictlyChange(e: CheckboxChangeEvent) { /** * 暴露方法来获取用于提交的全部节点 + * uniq去重(保险方案) */ defineExpose({ - getCheckedKeys: () => checkedRealKeys.value, + getCheckedKeys: () => uniq(checkedRealKeys.value), }); onMounted(async () => { diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts index 6990ba8b..42769f51 100644 --- a/apps/web-antd/src/router/access.ts +++ b/apps/web-antd/src/router/access.ts @@ -207,7 +207,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) { const vbenMenuList = backMenuToVbenMenu(backMenuList); // 特别注意 这里要深拷贝 const menuList = [...cloneDeep(localMenuList), ...vbenMenuList]; - console.log('menuList', menuList); + // console.log('menuList', menuList); return menuList; }, // 可以指定没有权限跳转403页面 diff --git a/apps/web-antd/src/views/system/client/client-drawer.vue b/apps/web-antd/src/views/system/client/client-drawer.vue index cdfad0de..cce41494 100644 --- a/apps/web-antd/src/views/system/client/client-drawer.vue +++ b/apps/web-antd/src/views/system/client/client-drawer.vue @@ -21,6 +21,9 @@ const title = computed(() => { const [BasicForm, formApi] = useVbenForm({ commonConfig: { formItemClass: 'col-span-2', + componentProps: { + class: 'w-full', + }, }, layout: 'vertical', schema: drawerSchema(), diff --git a/apps/web-antd/src/views/system/client/data.tsx b/apps/web-antd/src/views/system/client/data.tsx index 4e9e6e3b..6240e9c0 100644 --- a/apps/web-antd/src/views/system/client/data.tsx +++ b/apps/web-antd/src/views/system/client/data.tsx @@ -134,7 +134,6 @@ export const drawerSchema: FormSchemaGetter = () => [ { component: 'Select', componentProps: { - class: 'w-full', getPopupContainer, mode: 'multiple', optionFilterProp: 'label', @@ -148,7 +147,6 @@ export const drawerSchema: FormSchemaGetter = () => [ component: 'Select', componentProps: { allowClear: false, - class: 'w-full', getPopupContainer, options: getDictOptions(DictEnum.SYS_DEVICE_TYPE), }, diff --git a/apps/web-antd/src/views/system/oss-config/data.tsx b/apps/web-antd/src/views/system/oss-config/data.tsx index 06409ade..7fcc1bfd 100644 --- a/apps/web-antd/src/views/system/oss-config/data.tsx +++ b/apps/web-antd/src/views/system/oss-config/data.tsx @@ -99,7 +99,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider1', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '基本信息', }), @@ -134,7 +134,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider2', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '认证信息', }), @@ -157,7 +157,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider3', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '其他信息', }), diff --git a/apps/web-antd/src/views/system/post/data.ts b/apps/web-antd/src/views/system/post/data.ts index 57bcae1f..8e92e089 100644 --- a/apps/web-antd/src/views/system/post/data.ts +++ b/apps/web-antd/src/views/system/post/data.ts @@ -82,7 +82,6 @@ export const drawerSchema: FormSchemaGetter = () => [ { component: 'TreeSelect', componentProps: { - class: 'w-full', getPopupContainer, }, fieldName: 'deptId', diff --git a/apps/web-antd/src/views/system/role/data.tsx b/apps/web-antd/src/views/system/role/data.tsx index ed39e2e8..85692a28 100644 --- a/apps/web-antd/src/views/system/role/data.tsx +++ b/apps/web-antd/src/views/system/role/data.tsx @@ -154,12 +154,13 @@ export const drawerSchema: FormSchemaGetter = () => [ defaultValue: [], fieldName: 'menuIds', label: '菜单权限', + formItemClass: 'col-span-2', }, { component: 'Textarea', defaultValue: '', fieldName: 'remark', - formItemClass: 'items-baseline', + formItemClass: 'items-baseline col-span-2', label: '备注', }, ]; diff --git a/apps/web-antd/src/views/system/role/role-drawer.vue b/apps/web-antd/src/views/system/role/role-drawer.vue index 01f4d637..340966cf 100644 --- a/apps/web-antd/src/views/system/role/role-drawer.vue +++ b/apps/web-antd/src/views/system/role/role-drawer.vue @@ -24,12 +24,12 @@ const [BasicForm, formApi] = useVbenForm({ componentProps: { class: 'w-full', }, - formItemClass: 'col-span-2', + formItemClass: 'col-span-1', }, layout: 'vertical', schema: drawerSchema(), showDefaultActions: false, - wrapperClass: 'grid-cols-2', + wrapperClass: 'grid-cols-2 gap-x-4', }); const menuTree = ref([]); diff --git a/apps/web-antd/src/views/system/tenant/data.tsx b/apps/web-antd/src/views/system/tenant/data.tsx index 7d8f7113..01689484 100644 --- a/apps/web-antd/src/views/system/tenant/data.tsx +++ b/apps/web-antd/src/views/system/tenant/data.tsx @@ -101,7 +101,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider1', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '基本信息', }), @@ -132,7 +132,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider2', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '管理员信息', }), @@ -167,7 +167,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider3', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '租户设置', }), @@ -175,7 +175,6 @@ export const drawerSchema: FormSchemaGetter = () => [ { component: 'Select', componentProps: { - class: 'w-full', getPopupContainer, }, fieldName: 'packageId', @@ -237,7 +236,7 @@ export const drawerSchema: FormSchemaGetter = () => [ orientation: 'center', }, fieldName: 'divider4', - labelClass: 'w-0', + hideLabel: true, renderComponentContent: () => ({ default: () => '企业信息', }), diff --git a/apps/web-antd/src/views/system/tenant/tenant-drawer.vue b/apps/web-antd/src/views/system/tenant/tenant-drawer.vue index 4ab90edd..679b876e 100644 --- a/apps/web-antd/src/views/system/tenant/tenant-drawer.vue +++ b/apps/web-antd/src/views/system/tenant/tenant-drawer.vue @@ -23,6 +23,9 @@ const [BasicForm, formApi] = useVbenForm({ commonConfig: { formItemClass: 'col-span-2', labelWidth: 100, + componentProps: { + class: 'w-full', + }, }, schema: drawerSchema(), showDefaultActions: false, diff --git a/apps/web-antd/src/views/system/user/dept-tree.vue b/apps/web-antd/src/views/system/user/dept-tree.vue index 5b20546c..ad7ba42a 100644 --- a/apps/web-antd/src/views/system/user/dept-tree.vue +++ b/apps/web-antd/src/views/system/user/dept-tree.vue @@ -71,7 +71,7 @@ onMounted(loadTree);