This commit is contained in:
dap
2024-12-05 08:06:55 +08:00
101 changed files with 878 additions and 1170 deletions

View File

@@ -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'),

View File

@@ -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 () => {

View File

@@ -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页面

View File

@@ -21,6 +21,9 @@ const title = computed(() => {
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
formItemClass: 'col-span-2',
componentProps: {
class: 'w-full',
},
},
layout: 'vertical',
schema: drawerSchema(),

View File

@@ -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),
},

View File

@@ -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: () => '其他信息',
}),

View File

@@ -82,7 +82,6 @@ export const drawerSchema: FormSchemaGetter = () => [
{
component: 'TreeSelect',
componentProps: {
class: 'w-full',
getPopupContainer,
},
fieldName: 'deptId',

View File

@@ -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: '备注',
},
];

View File

@@ -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[]>([]);

View File

@@ -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: () => '企业信息',
}),

View File

@@ -23,6 +23,9 @@ const [BasicForm, formApi] = useVbenForm({
commonConfig: {
formItemClass: 'col-span-2',
labelWidth: 100,
componentProps: {
class: 'w-full',
},
},
schema: drawerSchema(),
showDefaultActions: false,

View File

@@ -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>