Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
This commit is contained in:
@@ -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 = <T extends Component>(
|
||||
|
||||
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||
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'),
|
||||
|
@@ -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<T = number | string> =
|
||||
| { 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 () => {
|
||||
|
@@ -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页面
|
||||
|
@@ -21,6 +21,9 @@ const title = computed(() => {
|
||||
const [BasicForm, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-2',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
layout: 'vertical',
|
||||
schema: drawerSchema(),
|
||||
|
@@ -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),
|
||||
},
|
||||
|
@@ -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: () => '其他信息',
|
||||
}),
|
||||
|
@@ -82,7 +82,6 @@ export const drawerSchema: FormSchemaGetter = () => [
|
||||
{
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
getPopupContainer,
|
||||
},
|
||||
fieldName: 'deptId',
|
||||
|
@@ -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: '备注',
|
||||
},
|
||||
];
|
||||
|
@@ -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<any[]>([]);
|
||||
|
@@ -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: () => '企业信息',
|
||||
}),
|
||||
|
@@ -23,6 +23,9 @@ const [BasicForm, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-2',
|
||||
labelWidth: 100,
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
schema: drawerSchema(),
|
||||
showDefaultActions: false,
|
||||
|
@@ -71,7 +71,7 @@ onMounted(loadTree);
|
||||
<div class="bg-background z-100 sticky left-0 top-0 p-[8px]">
|
||||
<InputSearch
|
||||
v-model:value="searchValue"
|
||||
placeholder="Search"
|
||||
:placeholder="$t('pages.common.search')"
|
||||
size="small"
|
||||
>
|
||||
<template #enterButton>
|
||||
|
Reference in New Issue
Block a user