feat(@vben/web-antd): 实现部门列表的部门名称模糊搜索功能,优化代码结构

- 新增 fuzzyMatch 函数实现模糊匹配- 新增 filterDeptTree 函数实现部门树的过滤
- 修改部门列表的查询逻辑,支持模糊搜索
- 优化部分代码结构
This commit is contained in:
Kven 2025-06-29 00:30:10 +08:00
parent 2a94aad171
commit 91412b45cd
7 changed files with 80 additions and 136 deletions

View File

@ -28,12 +28,19 @@ export namespace RoleApi {
export interface RoleListRecord extends Role {
name: string;
}
export interface RoleListResult {
records: RoleListRecord[];
total: number;
}
}
// 查询所有的角色列表、
export function queryRoleList(data: RoleApi.RoleListParams) {
export function queryRoleList(data: string) {
// return axios.get('/rest/role',data);
return requestClient.get<Array<RoleApi.Role>>('/rest/role', { params: data });
return requestClient.get<RoleApi.RoleListResult>('/rest/role', {
params: data,
});
}
// 切换启用状态

View File

@ -105,6 +105,11 @@ export namespace UserApi {
address?: string;
avatar?: string;
}
export interface UserInfoResult {
user: User;
permissions: string[];
}
}
/**
@ -176,7 +181,7 @@ export function selfUpdate(data: UserApi.UserUpdateRecord) {
// 获取个人用户信息
export function getUserInfo() {
return requestClient.get<UserApi.User>('/rest/user/self');
return requestClient.get<UserApi.UserInfoResult>('/rest/user/self');
}
// 部门的审核员

View File

@ -12,6 +12,37 @@ import { $t } from '#/locales';
const treeData = ref([]);
// utils.ts 或直接放在 data.ts 中
function fuzzyMatch(str: string, keyword: string): boolean {
if (!keyword) return true;
const reg = new RegExp([...keyword].join('.*'), 'i');
return reg.test(str);
}
export function filterDeptTree(
data: DeptApi.Dept[],
keyword: string,
): DeptApi.Dept[] {
if (!keyword) return data;
// 修改为 forEach 写法
const result: DeptApi.Dept[] = [];
data.forEach((node) => {
const match = fuzzyMatch(node.name, keyword);
const filteredChildren = node.children
? filterDeptTree(node.children, keyword)
: [];
if (match || filteredChildren.length > 0) {
result.push({
...node,
children: filteredChildren,
});
}
});
return result;
}
function transformToTreeData(data: any) {
return data.map((item) => ({
value: item.id,
@ -78,28 +109,6 @@ export function useGridFormSchema(): VbenFormSchema[] {
fieldName: 'name',
label: '部门名称',
},
// {
// component: 'Select',
// componentProps: {
// allowClear: true,
// options: [
// { label: $t('common.enabled'), value: true },
// { label: $t('common.disabled'), value: false },
// ],
// },
// fieldName: 'enable',
// label: '状态',
// },
// {
// component: 'Input',
// fieldName: 'remark',
// label: '备注',
// },
// {
// component: 'RangePicker',
// fieldName: 'createTime',
// label: '创建时间',
// },
];
}

View File

@ -5,6 +5,8 @@ import type {
} from '#/adapter/vxe-table';
import type { DeptApi } from '#/api';
import { ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
@ -15,7 +17,7 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getAllDeptTree, removeDept } from '#/api';
import { $t } from '#/locales';
import { useColumns, useGridFormSchema } from './data';
import { filterDeptTree, useColumns, useGridFormSchema } from './data';
// import AuthForm from './modules/auth-form.vue';
import Form from './modules/form.vue';
@ -24,11 +26,6 @@ const [FormModal, formModalApi] = useVbenModal({
destroyOnClose: true,
});
// const [AuthFormModal, authFormModalApi] = useVbenModal({
// connectedComponent: AuthForm,
// destroyOnClose: true,
// });
/**
* 编辑部门
* @param row
@ -99,6 +96,15 @@ function onActionClick({ code, row }: OnActionClickParams<DeptApi.Dept>) {
}
}
const fullDeptData = ref<DeptApi.Dept[] | null>(null);
async function loadFullDeptData() {
if (!fullDeptData.value) {
fullDeptData.value = await getAllDeptTree(0);
}
return fullDeptData.value;
}
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
// fieldMappingTime: [['createTime', ['startTime', 'endTime']]],
@ -114,10 +120,15 @@ const [Grid, gridApi] = useVbenVxeGrid({
},
proxyConfig: {
ajax: {
query: async (_params) => {
const res = await getAllDeptTree(0);
query: async (_, formValues) => {
//
const allData = await loadFullDeptData();
// name
const { name } = formValues || {};
//
const filteredData = filterDeptTree(allData, name || '');
return {
items: res,
items: filteredData,
};
},
},

View File

@ -8,7 +8,7 @@ import { getAllDeptTree, queryRoleList } from '#/api';
// import { $t } from '#/locales';
const treeData = ref([]);
const optionsRoleData = ref([]);
const optionsRoleData = ref<object[]>([]);
queryRoleList('').then((res) => {
optionsRoleData.value = res.records.map((item) => ({
@ -29,93 +29,6 @@ function transformToTreeData(data: any) {
getAllDeptTree(1).then((res) => {
treeData.value = transformToTreeData(res);
});
// export function useFormSchema(): VbenFormSchema[] {
// return [
// {
// component: 'Input',
// fieldName: 'username',
// label: '用户名称',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'name',
// label: '昵称',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'email',
// label: 'Email',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'phone',
// label: '电话',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'password',
// label: '密码',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'address',
// label: '地址',
// },
// {
// component: 'RadioGroup',
// componentProps: {
// buttonStyle: 'solid',
// options: [
// { label: $t('common.enabled'), value: true },
// { label: $t('common.disabled'), value: false },
// ],
// optionType: 'button',
// },
// defaultValue: true,
// fieldName: 'enable',
// label: '状态',
// },
// {
// component: 'Textarea',
// fieldName: 'remark',
// label: '备注',
// },
// {
// component: 'Select',
// rules: 'required',
// componentProps: {
// allowClear: true,
// mode: 'multiple',
// // api: queryRoleList(''),
// options: optionsRoleData,
// class: 'w-full',
// labelField: 'name',
// valueField: 'id',
// },
// fieldName: 'roleIds',
// label: '所属角色',
// },
// {
// component: 'TreeSelect',
// componentProps: {
// allowClear: true,
// // api: getAllDeptTree(1),
// treeData,
// class: 'w-full',
// labelField: 'name',
// valueField: 'id',
// childrenField: 'children',
// },
// fieldName: 'deptId',
// label: '所属部门',
// },
// ];
// }
export function useGridFormSchema(): VbenFormSchema[] {
return [

View File

@ -14,9 +14,9 @@ import {
import { PptListView, PptWorkView } from './components';
const temp = ref([]);
const temp = ref<PPTTempItem[]>([]);
const hitsory = ref([]);
const history = ref([]);
const loading = ref(true);
const itemMessage = ref<ResultItem[]>([]);
@ -26,8 +26,8 @@ const getLogs = async (appid: string, limit: number) => {
appid,
limit,
});
// hitsory
hitsory.value = res.reverse();
// history
history.value = res.reverse();
loading.value = false;
};
@ -42,7 +42,7 @@ const getTemp = async () => {
async function handleClick(item: PPTTempItem) {
// temp = item;
const res = await getWorkflowInfo({
appid: item.appId,
appid: item?.appId || '',
workflowRunId: item.workflowRunId,
});
itemMessage.value = [];
@ -67,7 +67,7 @@ function handleNewConversation() {
itemMessage.value = [];
}
const currentTemp = ref<null | PPTTempItem>(null);
const currentTemp = ref<PPTTempItem | undefined>();
async function handleClickMode(item: PPTTempItem) {
notification.success({
@ -90,7 +90,7 @@ onMounted(() => {
<PptListView
title="选择模板"
:temp="temp"
:items="hitsory"
:items="history"
:loading="loading"
@click-mode="handleClickMode"
@click="handleClick"

View File

@ -34,10 +34,12 @@ interface ResultItem {
}
interface WorkflowContext {
userId: string;
conversationId: string;
files: unknown[];
inputs: Record<string, unknown>;
userId: string;
inputs: {
[key: string]: any;
};
files: [];
}
interface WorkflowResult {
@ -56,10 +58,7 @@ interface WorkflowResult {
interface PropsWork {
itemMessage?: ResultItem[];
item?: PPTTempItem;
runWorkflow?: (
appId: any,
context: WorkflowContext,
) => Promise<WorkflowResult>;
runWorkflow?: (appId: any, data: WorkflowContext) => Promise<WorkflowResult>;
}
interface MenuItem {