wupengfei
8 天以前 03ffdd67fc4c40f3e9443931a0aa55e508182873
feat: 字典
8个文件已添加
1个文件已删除
14个文件已修改
1843 ■■■■ 已修改文件
.eslintrc-auto-import.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
auto-imports.d.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/apiEnum.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/dic.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/user.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/dic.ts 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/dictionary.ts 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/enterprise.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/index.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/role.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/typings.d.ts 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/userInfo.ts 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/common/common.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/DictionaryManage/DataDictionary.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/DictionaryManage/DictionaryCategoryManage.vue 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/DictionaryManage/components/AddOrEditDictionaryCategory.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/DictionaryManage/components/AddOrEditDictionaryDialog.vue 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/DictionaryManage/components/AddOrEditSearchSetting.vue 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Permission/OperationUserManage.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Permission/components/SetOperationUserRoleDialog.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/System/ModuleManage.vue 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/api.d.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc-auto-import.json
@@ -26,6 +26,8 @@
    "EnumRoleWebApiDataPower": true,
    "EnumRoleWebApiDataPowerText": true,
    "EnumRoleWebApiDataPowerTextForFilter": true,
    "EnumUserInfoStatus": true,
    "EnumUserInfoStatusText": true,
    "EnumUserType": true,
    "EnumUserTypeText": true,
    "ExtractDefaultPropTypes": true,
auto-imports.d.ts
@@ -32,6 +32,8 @@
  const EnumRoleWebApiDataPower: typeof import('./src/constants/apiEnum')['EnumRoleWebApiDataPower']
  const EnumRoleWebApiDataPowerText: typeof import('./src/constants/apiEnumText')['EnumRoleWebApiDataPowerText']
  const EnumRoleWebApiDataPowerTextForFilter: typeof import('./src/constants/apiEnumText')['EnumRoleWebApiDataPowerTextForFilter']
  const EnumUserInfoStatus: typeof import('./src/constants/apiEnum')['EnumUserInfoStatus']
  const EnumUserInfoStatusText: typeof import('./src/constants/user')['EnumUserInfoStatusText']
  const EnumUserType: typeof import('./src/constants/apiEnum')['EnumUserType']
  const EnumUserTypeText: typeof import('./src/constants/apiEnumText')['EnumUserTypeText']
  const EnumWebApiMethod: typeof import('./src/constants/apiEnum')['EnumWebApiMethod']
@@ -163,7 +165,7 @@
  export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
  import('vue')
  // @ts-ignore
  export type { EnumClientType, EnumMenuType, EnumMenuVisitLevel, EnumPagedListOrder, EnumResourceController, EnumResourceMethod, EnumRoleWebApiDataPower, EnumUserType, EnumClientType, EnumMenuType, EnumMenuVisitLevel, EnumPagedListOrder, EnumResourceController, EnumResourceMethod, EnumRoleWebApiDataPower, EnumUserType } from './src/constants/apiEnum'
  export type { EnumClientType, EnumMenuType, EnumMenuVisitLevel, EnumPagedListOrder, EnumResourceController, EnumResourceMethod, EnumRoleWebApiDataPower, EnumUserInfoStatus, EnumUserType, EnumClientType, EnumMenuType, EnumMenuVisitLevel, EnumPagedListOrder, EnumResourceController, EnumResourceMethod, EnumRoleWebApiDataPower, EnumUserInfoStatus, EnumUserType } from './src/constants/apiEnum'
  import('./src/constants/apiEnum')
  // @ts-ignore
  export type { FlexWorkerEleSignEnum, FlexTaskWorkerHireEnum, FlexWorkerEleSignEnum, FlexTaskWorkerHireEnum } from './src/constants/cPerson'
@@ -221,6 +223,8 @@
    readonly EnumRoleWebApiDataPower: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumRoleWebApiDataPower']>
    readonly EnumRoleWebApiDataPowerText: UnwrapRef<typeof import('./src/constants/apiEnumText')['EnumRoleWebApiDataPowerText']>
    readonly EnumRoleWebApiDataPowerTextForFilter: UnwrapRef<typeof import('./src/constants/apiEnumText')['EnumRoleWebApiDataPowerTextForFilter']>
    readonly EnumUserInfoStatus: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserInfoStatus']>
    readonly EnumUserInfoStatusText: UnwrapRef<typeof import('./src/constants/user')['EnumUserInfoStatusText']>
    readonly EnumUserType: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserType']>
    readonly EnumUserTypeText: UnwrapRef<typeof import('./src/constants/apiEnumText')['EnumUserTypeText']>
    readonly FastButtonMap: UnwrapRef<typeof import('./src/constants/module')['FastButtonMap']>
src/constants/apiEnum.ts
@@ -53,6 +53,10 @@
  Resource = 3,
  /**用户角色 */
  Role = 4,
  /**用户信息 */
  UserInfo = 5,
  /**企业信息 */
  Enterprise = 6,
}
/** 资源请求方式 */
@@ -83,6 +87,14 @@
  All = 999,
}
/** 用户信息状态 */
export enum EnumUserInfoStatus {
  /**正常 */
  Normal = 10,
  /**禁用 */
  Disabled = 100,
}
/** 用户类型 */
export enum EnumUserType {
  /**个人 */
src/constants/dic.ts
@@ -1,23 +1,14 @@
export enum SearchType {
export enum CategoryCode {
  /**身份 */
  Identity = 210,
  Identity = '10',
  /**学历 */
  Education = 220,
  Education = '20',
  /**岗位 */
  Position = 230,
  Position = '30',
  /**证书类型 */
  CertificateType = 240,
  CertificateType = '40',
  /**福利 */
  Welfare = 250,
  Welfare = '50',
  /**行业类型 */
  IndustryCategory = 260,
  IndustryCategory = '60',
}
export const SearchTypeText = {
  [SearchType.Identity]: '身份',
  [SearchType.Education]: '学历',
  [SearchType.Position]: '岗位',
  [SearchType.CertificateType]: '证书类型',
  [SearchType.Welfare]: '福利',
  [SearchType.IndustryCategory]: '行业类型',
};
src/constants/index.ts
@@ -14,3 +14,5 @@
export * from './cPerson';
export * from './apiEnum';
export * from './apiEnumText';
export * from './user';
export * from './dic';
src/constants/user.ts
New file
@@ -0,0 +1,4 @@
export const EnumUserInfoStatusText = {
  [EnumUserInfoStatus.Normal]: '正常',
  [EnumUserInfoStatus.Disabled]: '禁用',
};
src/hooks/dic.ts
@@ -1,8 +1,109 @@
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import { SearchType } from '@/constants';
import * as dictionaryServices from '@/services/api/dictionary';
type UseSearchSettingTypeOptions = {
  searchType: number;
  belongType?: number;
  onSuccess?: (data: any[]) => any;
export function useGetDictionaryCategorySelect() {
  const { data: dictionaryCategoryList, refetch } = useQuery({
    queryKey: ['dictionaryServices/getDictionaryCategorySelect'],
    queryFn: async () => {
      let res = await dictionaryServices.getDictionaryCategorySelect({}, { showLoading: false });
      return res.map((x) => ({
        ...x,
        fieldNamesMap: x.data.fieldNames ? JSON.parse(x.data.fieldNames) : {},
      }));
    },
    placeholderData: () =>
      [] as API.SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption[],
  });
  const queryClient = useQueryClient();
  function ensureQueryData() {
    return queryClient.ensureQueryData<
      API.SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption[]
    >({
      queryKey: ['dictionaryServices/getDictionaryCategorySelect'],
    });
  }
  function getDictionaryCategoryById(id: string) {
    return dictionaryCategoryList.value.find((x) => x.value === id);
  }
  function getDictionaryCategoryByCode(code: string) {
    return dictionaryCategoryList.value.find((x) => x.code === code);
  }
  function getDictionaryCategoryNameByCode(code: string) {
    return getDictionaryCategoryByCode(code)?.label ?? '';
  }
  return {
    dictionaryCategoryList,
    ensureQueryData,
    getDictionaryCategoryById,
    getDictionaryCategoryNameByCode,
    getDictionaryCategoryByCode,
  };
}
type UseDictionaryDataSelectOptions = {
  categoryId?: MaybeRef<string>;
  categoryCode?: MaybeRef<string>;
};
export function useDictionaryDataSelect({
  categoryId,
  categoryCode,
}: UseDictionaryDataSelectOptions) {
  const { data: dictionaryDataList, refetch } = useQuery({
    queryKey: ['dictionaryServices/getDictionaryDataSelect'],
    queryFn: async () => {
      let res = await dictionaryServices.getDictionaryDataSelect(
        {
          categoryId: unref(categoryId),
          categoryCode: unref(categoryCode),
        },
        { showLoading: false }
      );
      return res.map((x) => ({
        ...x,
        code: x.data?.code ?? '',
      }));
    },
    placeholderData: () =>
      [] as API.SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption[],
    enabled: !!unref(categoryId) || !!unref(categoryCode),
  });
  function getDictionaryDataNameById(id: string) {
    return dictionaryDataList.value?.find((x) => x.value === id)?.label;
  }
  function getDictionaryDataByCode(code: string) {
    return dictionaryDataList.value?.find((x) => x.code === code);
  }
  function getDictionaryDataNameByCode(code: string) {
    return getDictionaryDataByCode(code)?.label ?? '';
  }
  const queryClient = useQueryClient();
  function ensureQueryData() {
    return queryClient.ensureQueryData<
      API.SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption[]
    >({
      queryKey: ['dictionaryServices/getDictionaryDataSelect'],
    });
  }
  return {
    dictionaryDataList,
    ensureQueryData,
    refetch,
    getDictionaryDataNameById,
    getDictionaryDataNameByCode,
    getDictionaryDataByCode,
  };
}
src/services/api/dictionary.ts
@@ -2,7 +2,60 @@
// @ts-ignore
import { request } from '@/utils/request';
/** 获取字典数据分页列表 POST /api/main/dictionary/getDictionaryDatas */
/** 删除数据字典类别 DELETE /api/main/dictionary/deleteDictionaryCategory */
export async function deleteDictionaryCategory(
  body: API.DeleteDictionaryCategoryCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/main/dictionary/deleteDictionaryCategory', {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 获取数据字典类别分页列表数据 POST /api/main/dictionary/getDictionaryCategories */
export async function getDictionaryCategories(
  body: API.GetDictionaryCategoriesQuery,
  options?: API.RequestConfig
) {
  return request<API.PagedListQueryResultGetDictionaryCategoriesQueryResultItem>(
    '/api/main/dictionary/getDictionaryCategories',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json-patch+json',
      },
      data: body,
      ...(options || {}),
    }
  );
}
/** 查询数据字典类别选择器数据 GET /api/main/dictionary/getDictionaryCategorySelect */
export async function getDictionaryCategorySelect(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.APIgetDictionaryCategorySelectParams,
  options?: API.RequestConfig
) {
  return request<API.SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption[]>(
    '/api/main/dictionary/getDictionaryCategorySelect',
    {
      method: 'GET',
      params: {
        ...params,
        request: undefined,
        ...params['request'],
      },
      ...(options || {}),
    }
  );
}
/** 获取数据字典分页列表数据 POST /api/main/dictionary/getDictionaryDatas */
export async function getDictionaryDatas(
  body: API.GetDictionaryDatasQuery,
  options?: API.RequestConfig
@@ -19,3 +72,66 @@
    }
  );
}
/** 查询数据字典选择器 GET /api/main/dictionary/getDictionaryDataSelect */
export async function getDictionaryDataSelect(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.APIgetDictionaryDataSelectParams,
  options?: API.RequestConfig
) {
  return request<API.SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption[]>(
    '/api/main/dictionary/getDictionaryDataSelect',
    {
      method: 'GET',
      params: {
        ...params,
      },
      ...(options || {}),
    }
  );
}
/** 保存数据字典类别 POST /api/main/dictionary/saveDictionaryCategory */
export async function saveDictionaryCategory(
  body: API.SaveDictionaryCategoryCommand,
  options?: API.RequestConfig
) {
  return request<string>('/api/main/dictionary/saveDictionaryCategory', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 保存数据字典 POST /api/main/dictionary/saveDictionaryData */
export async function saveDictionaryData(
  body: API.SaveDictionaryDataCommand,
  options?: API.RequestConfig
) {
  return request<string>('/api/main/dictionary/saveDictionaryData', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 设置数据字典是否禁用 PUT /api/main/dictionary/setDictionaryDataIsDisabled */
export async function setDictionaryDataIsDisabled(
  body: API.SetDictionaryDataIsDisabledCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/main/dictionary/setDictionaryDataIsDisabled', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
src/services/api/enterprise.ts
New file
@@ -0,0 +1,18 @@
/* eslint-disable */
// @ts-ignore
import { request } from '@/utils/request';
/** 查询企业信息分页列表数据 POST /api/user/enterprise/getEnterprises */
export async function getEnterprises(body: API.GetEnterprisesQuery, options?: API.RequestConfig) {
  return request<API.PagedListQueryResultGetEnterprisesQueryResultItem>(
    '/api/user/enterprise/getEnterprises',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json-patch+json',
      },
      data: body,
      ...(options || {}),
    }
  );
}
src/services/api/index.ts
@@ -2,15 +2,19 @@
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as dictionary from './dictionary';
import * as auth from './auth';
import * as menu from './menu';
import * as dictionary from './dictionary';
import * as resource from './resource';
import * as role from './role';
import * as userInfo from './userInfo';
import * as enterprise from './enterprise';
export default {
  dictionary,
  auth,
  menu,
  dictionary,
  resource,
  role,
  userInfo,
  enterprise,
};
src/services/api/role.ts
@@ -41,6 +41,21 @@
  });
}
/** 查询角色用户列表 GET /api/user/role/getRoleUserInfos */
export async function getRoleUserInfos(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.APIgetRoleUserInfosParams,
  options?: API.RequestConfig
) {
  return request<API.GetRoleUserInfosQueryResultItem[]>('/api/user/role/getRoleUserInfos', {
    method: 'GET',
    params: {
      ...params,
    },
    ...(options || {}),
  });
}
/** 保存角色 POST /api/user/role/saveRole */
export async function saveRole(body: API.SaveRoleCommand, options?: API.RequestConfig) {
  return request<string>('/api/user/role/saveRole', {
@@ -52,3 +67,33 @@
    ...(options || {}),
  });
}
/** 设置角色是否禁用 PUT /api/user/role/setRoleIsDisabled */
export async function setRoleIsDisabled(
  body: API.SetRoleIsDisabledCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/role/setRoleIsDisabled', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 设置角色用户 PUT /api/user/role/setRoleUserInfos */
export async function setRoleUserInfos(
  body: API.SetRoleUserInfosCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/role/setRoleUserInfos', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
src/services/api/typings.d.ts
@@ -13,6 +13,20 @@
    request?: GetCurrentLogierMenusQuery;
  }
  interface APIgetDictionaryCategorySelectParams {
    /** 查询数据字典类别选择器数据 */
    request?: GetDictionaryCategorySelectQuery;
  }
  interface APIgetDictionaryDataSelectParams {
    /** 类别Id(Id/编号二选一) */
    categoryId?: string;
    /** 类别编号(Id/编号二选一) */
    categoryCode?: string;
    /** 上级Id */
    parentId?: string;
  }
  interface APIgetMenuParams {
    /** Id */
    id?: string;
@@ -46,6 +60,22 @@
  interface APIgetRoleParams {
    /** Id */
    id?: string;
  }
  interface APIgetRoleUserInfosParams {
    /** 角色Id */
    roleId?: string;
  }
  interface APIgetUserInfoRolesParams {
    /** 用户Id */
    userInfoId?: string;
    /** 客户端类型 */
    clientType?: EnumClientType;
  }
  interface DeleteDictionaryCategoryCommand {
    ids: string[];
  }
  interface DeleteMenuCommand {
@@ -103,6 +133,10 @@
    Resource = 3,
    /**用户角色 */
    Role = 4,
    /**用户信息 */
    UserInfo = 5,
    /**企业信息 */
    Enterprise = 6,
  }
  enum EnumResourceMethod {
@@ -129,6 +163,13 @@
    CurrentEnterprise = 30,
    /**查询所有 */
    All = 999,
  }
  enum EnumUserInfoStatus {
    /**正常 */
    Normal = 10,
    /**禁用 */
    Disabled = 100,
  }
  enum EnumUserType {
@@ -289,6 +330,100 @@
    timestamp?: number;
  }
  interface FriendlyResultListGetRoleUserInfosQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    /** 数据 */
    data?: GetRoleUserInfosQueryResultItem[];
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultListGetUserInfoRolesQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    /** 数据 */
    data?: GetUserInfoRolesQueryResultItem[];
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultListSelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    /** 数据 */
    data?: SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption[];
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultListSelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    /** 数据 */
    data?: SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption[];
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultPagedListQueryResultGetDictionaryCategoriesQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    data?: PagedListQueryResultGetDictionaryCategoriesQueryResultItem;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultPagedListQueryResultGetDictionaryDatasQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
@@ -297,6 +432,42 @@
    /** 错误码 */
    errorCode?: string;
    data?: PagedListQueryResultGetDictionaryDatasQueryResultItem;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultPagedListQueryResultGetEnterprisesQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    data?: PagedListQueryResultGetEnterprisesQueryResultItem;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultPagedListQueryResultGetOperationUserInfosQueryResultItem {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    data?: PagedListQueryResultGetOperationUserInfosQueryResultItem;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
@@ -355,11 +526,98 @@
  type GetCurrentLogierMenusQuery = Record<string, any>;
  interface GetDictionaryDatasQuery {
  interface GetDictionaryCategoriesQuery {
    pageModel?: PagedListQueryPageModel;
    /** 关键字 */
    keywords?: string;
  }
  type GetDictionaryDatasQueryResultItem = Record<string, any>;
  interface GetDictionaryCategoriesQueryResultItem {
    /** Id */
    id?: string;
    /** 编号 */
    code?: string;
    /** 名称 */
    name?: string;
    /** 字段名(逗号隔开) */
    fieldNames?: string;
    /** 排序 */
    sort?: number;
  }
  type GetDictionaryCategorySelectQuery = Record<string, any>;
  interface GetDictionaryDatasQuery {
    pageModel?: PagedListQueryPageModel;
    /** 类别Id(Id/编号二选一) */
    categoryId?: string;
    /** 类别编号(Id/编号二选一) */
    categoryCode?: string;
    /** 关键字 */
    keywords?: string;
  }
  interface GetDictionaryDatasQueryResultItem {
    /** Id */
    id?: string;
    /** 类别Id */
    categoryId?: string;
    /** 类别编号 */
    categoryCode?: string;
    /** 类别名称 */
    categoryName?: string;
    category?: GetDictionaryDatasQueryResultItemCategory;
    /** 上级Id */
    parentId?: string;
    /** 编号 */
    code?: string;
    /** 显示内容 */
    content: string;
    /** 字段1 */
    field1?: string;
    /** 字段2 */
    field2?: string;
    /** 字段3 */
    field3?: string;
    /** 字段4 */
    field4?: string;
    /** 字段5 */
    field5?: string;
    /** 排序 */
    sort?: number;
    /** 是否禁用 */
    isDisabled?: boolean;
  }
  interface GetDictionaryDatasQueryResultItemCategory {
    /** 类别编号 */
    code?: string;
    /** 名称 */
    name?: string;
  }
  interface GetEnterprisesQuery {
    pageModel?: PagedListQueryPageModel;
    /** 关键字 */
    keywords?: string;
    /** 是否已配置 */
    isConfigured?: boolean;
  }
  interface GetEnterprisesQueryResultItem {
    /** Id */
    id?: string;
    /** 企业全称 */
    enterpriseName?: string;
    /** 法人姓名 */
    legalPerson?: string;
    /** 统一社会信用代码 */
    societyCreditCode?: string;
    /** 联系人 */
    contacts?: string;
    /** 联系电话 */
    contactNumber?: string;
  }
  interface GetMenuQueryResult {
    /** Id */
@@ -477,6 +735,37 @@
    remark?: string;
  }
  interface GetOperationUserInfosQuery {
    pageModel?: PagedListQueryPageModel;
    /** 关键字 */
    keywords?: string;
  }
  interface GetOperationUserInfosQueryResultItem {
    /** Id */
    id?: string;
    /** 姓名 */
    name?: string;
    /** 用户名 */
    userName?: string;
    /** 手机号 */
    phoneNumber?: string;
    /** 备注 */
    remark?: string;
    /** 角色 */
    roles?: GetOperationUserInfosQueryResultItemRole[];
    status?: EnumUserInfoStatus;
  }
  interface GetOperationUserInfosQueryResultItemRole {
    /** 用户Id */
    userInfoId?: string;
    /** 角色Id */
    id?: string;
    /** 名称 */
    name?: string;
  }
  interface GetResourceFieldsQueryResultItem {
    /** 编号 */
    code?: string;
@@ -537,6 +826,8 @@
    pageModel?: PagedListQueryPageModel;
    userType?: EnumUserType;
    clientType?: EnumClientType;
    /** 关键字 */
    keywords?: string;
  }
  interface GetRolesQueryResultItem {
@@ -551,6 +842,32 @@
    dataPower?: EnumRoleWebApiDataPower;
    /** 备注 */
    remark?: string;
    /** 是否禁用 */
    isDisabled?: boolean;
    /** 用户数量 */
    userCount?: number;
  }
  interface GetRoleUserInfosQueryResultItem {
    /** 用户Id */
    id?: string;
    /** 姓名 */
    name?: string;
    /** 用户名 */
    userName?: string;
    /** 是否选中 */
    isChecked?: boolean;
  }
  interface GetUserInfoRolesQueryResultItem {
    /** 角色Id */
    id?: string;
    /** 名称 */
    name?: string;
    /** 备注 */
    remark?: string;
    /** 是否选中 */
    isChecked?: boolean;
  }
  interface PagedListQueryPageModel {
@@ -568,10 +885,28 @@
    order?: EnumPagedListOrder;
  }
  interface PagedListQueryResultGetDictionaryCategoriesQueryResultItem {
    pageModel?: PagedListQueryResultPageModel;
    /** 数据 */
    data?: GetDictionaryCategoriesQueryResultItem[];
  }
  interface PagedListQueryResultGetDictionaryDatasQueryResultItem {
    pageModel?: PagedListQueryResultPageModel;
    /** 数据 */
    data?: GetDictionaryDatasQueryResultItem[];
  }
  interface PagedListQueryResultGetEnterprisesQueryResultItem {
    pageModel?: PagedListQueryResultPageModel;
    /** 数据 */
    data?: GetEnterprisesQueryResultItem[];
  }
  interface PagedListQueryResultGetOperationUserInfosQueryResultItem {
    pageModel?: PagedListQueryResultPageModel;
    /** 数据 */
    data?: GetOperationUserInfosQueryResultItem[];
  }
  interface PagedListQueryResultGetRolesQueryResultItem {
@@ -607,6 +942,46 @@
    accessToken?: string;
    /** 刷新令牌 */
    refreshToken?: string;
  }
  interface SaveDictionaryCategoryCommand {
    /** Id */
    id?: string;
    /** 编号 */
    code: string;
    /** 名称 */
    name: string;
    /** 字段名(逗号隔开) */
    fieldNames?: string;
    /** 排序 */
    sort?: number;
  }
  interface SaveDictionaryDataCommand {
    /** Id */
    id?: string;
    /** 类别Id */
    categoryId?: string;
    /** 上级Id */
    parentId?: string;
    /** 编号 */
    code?: string;
    /** 显示内容 */
    content: string;
    /** 字段1 */
    field1?: string;
    /** 字段2 */
    field2?: string;
    /** 字段3 */
    field3?: string;
    /** 字段4 */
    field4?: string;
    /** 字段5 */
    field5?: string;
    /** 排序 */
    sort?: number;
    /** 是否禁用 */
    isDisabled?: boolean;
  }
  interface SaveMenuButtonCommand {
@@ -750,6 +1125,30 @@
    resources?: GetRoleQueryResultResource[];
  }
  interface SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption {
    /** 值 */
    value?: string;
    /** 标签 */
    label?: string;
    /** 数据 */
    data?: any;
  }
  interface SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption {
    /** 值 */
    value?: string;
    /** 标签 */
    label?: string;
    /** 数据 */
    data?: any;
  }
  interface SetDictionaryDataIsDisabledCommand {
    ids?: string[];
    /** 是否已禁用 */
    isDisabled?: boolean;
  }
  interface SetMenuSwitchCommand {
    /** Id */
    ids?: string[];
@@ -759,4 +1158,30 @@
    /** 是否缓存(null时不更新) */
    isCache?: boolean;
  }
  interface SetRoleIsDisabledCommand {
    ids?: string[];
    /** 是否已禁用 */
    isDisabled?: boolean;
  }
  interface SetRoleUserInfosCommand {
    /** 角色Id */
    roleId?: string;
    /** 用户Id */
    userInfoIds?: string[];
  }
  interface SetUserInfoRolesCommand {
    /** 用户Id */
    userInfoId?: string;
    /** 角色Id */
    roleIds?: string[];
  }
  interface SetUserInfoStatusCommand {
    /** Id */
    ids?: string[];
    status?: EnumUserInfoStatus;
  }
}
src/services/api/userInfo.ts
New file
@@ -0,0 +1,66 @@
/* eslint-disable */
// @ts-ignore
import { request } from '@/utils/request';
/** 查询运营端用户分页列表数据 POST /api/user/userInfo/getOperationUserInfos */
export async function getOperationUserInfos(
  body: API.GetOperationUserInfosQuery,
  options?: API.RequestConfig
) {
  return request<API.PagedListQueryResultGetOperationUserInfosQueryResultItem>(
    '/api/user/userInfo/getOperationUserInfos',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json-patch+json',
      },
      data: body,
      ...(options || {}),
    }
  );
}
/** 查询用户角色列表 GET /api/user/userInfo/getUserInfoRoles */
export async function getUserInfoRoles(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.APIgetUserInfoRolesParams,
  options?: API.RequestConfig
) {
  return request<API.GetUserInfoRolesQueryResultItem[]>('/api/user/userInfo/getUserInfoRoles', {
    method: 'GET',
    params: {
      ...params,
    },
    ...(options || {}),
  });
}
/** 设置用户信息角色 PUT /api/user/userInfo/setUserInfoRoles */
export async function setUserInfoRoles(
  body: API.SetUserInfoRolesCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/userInfo/setUserInfoRoles', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 设置用户信息状态 PUT /api/user/userInfo/setUserInfoStatus */
export async function setUserInfoStatus(
  body: API.SetUserInfoStatusCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/userInfo/setUserInfoStatus', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
src/utils/common/common.ts
@@ -106,3 +106,12 @@
export function filterNumbersFromString(str: string) {
  return str.replace(/\D/g, '');
}
export function formatRoleName(roleName: string) {
  let lastUnderscoreIndex = roleName.lastIndexOf('_');
  if (lastUnderscoreIndex !== -1) {
    roleName = roleName.substring(0, lastUnderscoreIndex);
  }
  return roleName;
}
src/views/DictionaryManage/DataDictionary.vue
@@ -5,26 +5,15 @@
        <template #query>
          <QueryFilterItem>
            <FieldSelect
              v-model="extraParamState.searchType"
              v-model="extraParamState.categoryId"
              @change="getList()"
              :value-enum="SearchTypeText"
              :value-enum="dictionaryCategoryList"
              placeholder="请选择所属类别"
            ></FieldSelect>
          </QueryFilterItem>
          <QueryFilterItem v-if="extraParamState.searchType === SearchType.Position">
            <FieldSelect
              v-model="extraParamState.parentId"
              @change="getList()"
              :value-enum="typeList"
              enum-label-key="name"
              enum-value-key="id"
              placeholder="请选择行业类型"
              clearable
            ></FieldSelect>
          </QueryFilterItem>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.name"
              v-model="extraParamState.keywords"
              style="width: 200px"
              placeholder="请输入名称"
              @on-click-search="getList"
@@ -44,19 +33,22 @@
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
        <template #columns="{ row, column }">
          <template v-if="column.property === 'status'">
            <FieldSwitch
              v-model="row.status"
              active-text="显示"
              inactive-text="隐藏"
              :before-change="() => setCategoryVis(row)"
            />
          </template>
        <template #isDisabled="{ row }">
          <FieldSwitch
            v-model="row.isDisabled"
            active-text="启用"
            inactive-text="禁用"
            :active-value="false"
            :inactive-value="true"
            :before-change="() => setCategoryVis(row)"
          />
        </template>
        <template #category="{ row }">
          {{ row.category?.name }}
        </template>
      </ProTableV2>
    </AppContainer>
    <AddOrEditSearchSetting v-bind="dialogProps" :typeList="typeList" />
    <AddOrEditDictionaryDialog v-bind="dialogProps" />
  </LoadingLayout>
</template>
@@ -74,20 +66,13 @@
  UploadUserFile,
  FieldSwitch,
  FieldSelect,
  FieldRadio,
} from '@bole-core/components';
import { useAccess } from '@/hooks';
import {
  SearchType,
  SearchTypeText,
  // BelongType,
  // BelongTypeText,
  BooleanOptions,
} from '@/constants';
import { OrderInputType, Message } from '@bole-core/core';
import AddOrEditSearchSetting from './components/AddOrEditSearchSetting.vue';
import { convertApi2FormUrl } from '@/utils';
import { useQueryClient } from '@tanstack/vue-query';
import { useAccess, useDictionaryDataSelect, useGetDictionaryCategorySelect } from '@/hooks';
import { Message } from '@bole-core/core';
import AddOrEditDictionaryDialog from './components/AddOrEditDictionaryDialog.vue';
import { convertApi2FormUrl, convertApi2FormUrlOnlyOne } from '@/utils';
import * as dictionaryServices from '@/services/api/dictionary';
import { CategoryCode } from '@/constants';
defineOptions({
  name: 'DataDictionary',
@@ -101,14 +86,23 @@
  operationBtnMap,
});
const { dictionaryCategoryList, ensureQueryData, getDictionaryCategoryNameByCode } =
  useGetDictionaryCategorySelect();
const { getDictionaryDataNameByCode } = useDictionaryDataSelect({
  categoryCode: CategoryCode.IndustryCategory,
});
const BaseState = {
  loading: true,
};
const queryClient = useQueryClient();
const typeList = ref([]);
const state = reactive({ ...BaseState });
onMounted(async () => {
  const dictionaryCategoryList = await ensureQueryData();
  if (dictionaryCategoryList.length > 0) {
    extraParamState.categoryId = dictionaryCategoryList[0].value;
  }
  await getList();
  state.loading = false;
});
@@ -122,23 +116,16 @@
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetSearchSettingListInput = {
      let params: API.GetDictionaryDatasQuery = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        name: extraParamState.name,
        // belongType: Number(extraParamState.belongType),
        searchType: Number(extraParamState.searchType),
        status: extraParamState.status,
        categoryId: extraParamState.categoryId,
        keywords: extraParamState.keywords,
      };
      if (extraParamState.searchType === SearchType.Position) {
        params.isRecommend = extraParamState.isRecommend;
        params.parentId = extraParamState.parentId;
      }
      let res = await searchSettingServices.getSearchSettingList(params, {
      let res = await dictionaryServices.getDictionaryDatas(params, {
        showLoading: !state.loading,
      });
      return res;
@@ -148,34 +135,38 @@
  },
  {
    defaultExtraParams: {
      name: '',
      searchType: SearchType.Identity,
      orderInput: [{ property: 'sort', order: OrderInputType.Asc }],
      status: '' as any as boolean,
      isRecommend: '' as any as boolean,
      parentId: '',
      categoryId: '',
      keywords: '',
      orderInput: [{ property: 'sort', order: EnumPagedListOrder.Asc }],
    },
    queryKey: ['searchSettingServices/getSearchSettingList'],
    queryKey: ['dictionaryServices/getDictionaryDatas'],
    columnsRenderProps: {
      searchType: { type: 'enum', valueEnum: SearchTypeText },
      field1: {
        formatter(row: API.GetDictionaryDatasQueryResultItem) {
          return row.categoryCode == CategoryCode.Position
            ? getDictionaryDataNameByCode(row.field1)
            : '';
        },
      },
    },
  }
);
function openDialog(row?: API.GetSearchSettingList) {
function openDialog(row?: API.GetDictionaryDatasQueryResultItem) {
  if (row) {
    handleEdit({
      id: row.id,
      searchType: extraParamState.searchType,
      name: row.name,
      categoryId: row.categoryId,
      code: row.code,
      content: row.content,
      sort: row.sort,
      status: row.status,
      src: row.src?.length ? [convertApi2FormUrl(row.src)] : [],
      parentId: row.parentId ?? '',
      isDisabled: row.isDisabled,
      field1: row.field1,
      field2: convertApi2FormUrlOnlyOne(row.field2),
    });
  } else {
    handleAdd({
      searchType: extraParamState.searchType,
      categoryId: extraParamState.categoryId,
    });
  }
}
@@ -184,55 +175,47 @@
  onConfirm: handleAddOrEdit,
  defaultFormParams: {
    id: '',
    searchType: SearchType.Identity,
    name: '',
    categoryId: '',
    code: '',
    content: '',
    sort: 0,
    status: true,
    src: [] as UploadUserFile[],
    parentId: '',
    isDisabled: false,
    field1: '',
    field2: [] as UploadUserFile[],
  },
});
async function handleAddOrEdit() {
  try {
    let params: API.CreateOrEditSearchInput = {
      searchType: extraParamState.searchType,
      name: editForm.name,
    let params: API.SaveDictionaryDataCommand = {
      categoryId: editForm.categoryId,
      code: editForm.code,
      sort: editForm.sort,
      status: editForm.status,
      src: editForm.src?.[0]?.path ?? '',
      parentId: editForm.parentId ?? '',
      content: editForm.content,
      isDisabled: editForm.isDisabled,
      field1: editForm.field1,
      field2: editForm.field2?.[0]?.path ?? '',
    };
    if (editForm.id) {
      params.id = editForm.id;
    }
    let res = await searchSettingServices.createOrEditSearchSetting(params);
    let res = await dictionaryServices.saveDictionaryData(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
      dialogState.dialogVisible = false;
      updateCategoryMenu();
    }
  } catch (error) {}
}
function updateCategoryMenu() {
  queryClient.invalidateQueries({
    queryKey: [
      'searchSettingServices/getTypeSearchSettingList',
      { searchType: extraParamState.searchType, belongType: null },
    ],
  });
}
async function setCategoryVis(row: API.GetSearchSettingList) {
async function setCategoryVis(row: API.GetDictionaryDatasQueryResultItem) {
  try {
    let params: API.EnableSearchSettingInput = {
      id: row.id,
      status: !row.status,
    await Message.tipMessage(`确认要${row.isDisabled ? '启用' : '禁用'}吗?`);
    let params: API.SetDictionaryDataIsDisabledCommand = {
      ids: [row.id],
      isDisabled: !row.isDisabled,
    };
    let res = await searchSettingServices.enableSearchSetting(params);
    updateCategoryMenu();
    let res = await dictionaryServices.setDictionaryDataIsDisabled(params);
    getList(paginationState.pageIndex);
    return !!res;
  } catch (error) {}
src/views/DictionaryManage/DictionaryCategoryManage.vue
New file
@@ -0,0 +1,165 @@
<template>
  <LoadingLayout :loading="state.loading">
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.keywords"
              style="width: 200px"
              placeholder="名称/编号"
              @on-click-search="getList"
              @keyup.enter="getList()"
            >
            </SearchInput>
          </QueryFilterItem>
        </template>
        <template #btn>
          <el-button
            v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
            @click="openDialog()"
            icon="Plus"
            type="primary"
            >新增</el-button
          >
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
      </ProTableV2>
    </AppContainer>
    <AddOrEditDictionaryCategory v-bind="dialogProps" />
  </LoadingLayout>
</template>
<script setup lang="ts">
import {
  ProTableQueryFilterBar,
  OperationBtnType,
  ProTableV2,
  SearchInput,
  LoadingLayout,
  AppContainer,
  QueryFilterItem,
  useTable,
  useFormDialog,
} from '@bole-core/components';
import { useAccess } from '@/hooks';
import { Message } from '@bole-core/core';
import AddOrEditDictionaryCategory from './components/AddOrEditDictionaryCategory.vue';
import { useQueryClient } from '@tanstack/vue-query';
import * as dictionaryServices from '@/services/api/dictionary';
defineOptions({
  name: 'DictionaryCategoryManage',
});
const operationBtnMap: Record<string, OperationBtnType> = {
  editBtn: { emits: { onClick: (role) => openDialog(role) } },
  delBtn: { emits: { onClick: (role) => handleDel(role) }, props: { type: 'danger' } },
};
const { checkSubModuleItemShow, column, operationBtns } = useAccess({
  operationBtnMap,
});
const BaseState = {
  loading: true,
};
const state = reactive({ ...BaseState });
onMounted(async () => {
  await getList();
  state.loading = false;
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetDictionaryCategoriesQuery = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        keywords: extraParamState.keywords,
      };
      let res = await dictionaryServices.getDictionaryCategories(params, {
        showLoading: !state.loading,
      });
      return res;
    } catch (error) {
      console.log('error: ', error);
    }
  },
  {
    defaultExtraParams: {
      keywords: '',
      orderInput: [{ property: 'sort', order: EnumPagedListOrder.Asc }],
    },
    queryKey: ['dictionaryServices/getDictionaryCategories'],
    columnsRenderProps: {},
  }
);
function openDialog(row?: API.GetDictionaryCategoriesQueryResultItem) {
  if (row) {
    handleEdit({
      id: row.id,
      name: row.name,
      sort: row.sort,
      code: row.code,
      fieldNames: row.fieldNames,
    });
  } else {
    handleAdd();
  }
}
const { dialogProps, handleAdd, handleEdit, editForm } = useFormDialog({
  onConfirm: handleAddOrEdit,
  defaultFormParams: {
    id: '',
    name: '',
    code: '',
    fieldNames: '',
    sort: 0,
  },
});
async function handleAddOrEdit() {
  try {
    let params: API.SaveDictionaryCategoryCommand = {
      code: editForm.code,
      name: editForm.name,
      sort: editForm.sort,
      fieldNames: editForm.fieldNames,
    };
    if (editForm.id) {
      params.id = editForm.id;
    }
    let res = await dictionaryServices.saveDictionaryCategory(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
async function handleDel(row: API.GetDictionaryCategoriesQueryResultItem) {
  try {
    await Message.tipMessage('确认要删除该类别吗?');
    let params: API.DeleteDictionaryCategoryCommand = { ids: [row.id] };
    let res = await dictionaryServices.deleteDictionaryCategory(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
</script>
src/views/DictionaryManage/components/AddOrEditDictionaryCategory.vue
New file
@@ -0,0 +1,90 @@
<template>
  <ProDialog
    :title="`${title}类别`"
    v-model="visible"
    @close="onDialogClose"
    destroy-on-close
    draggable
  >
    <ProForm :model="form" ref="dialogForm" label-width="90px">
      <ProFormItemV2 label="名称:" prop="name" :check-rules="[{ message: '请输入名称' }]">
        <ProFormText
          placeholder="请输入名称"
          v-model.trim="form.name"
          :maxlength="15"
        ></ProFormText>
      </ProFormItemV2>
      <ProFormItemV2 label="编号:" prop="code">
        <ProFormText placeholder="请输入编号" v-model.trim="form.code"></ProFormText>
      </ProFormItemV2>
      <ProFormItemV2 label="字段名:" prop="fieldNames">
        <ProFormText placeholder="请输入编号" v-model.trim="form.fieldNames"></ProFormText>
      </ProFormItemV2>
      <ProFormItemV2 label="排序:" prop="sort">
        <ProFormInputNumber
          v-model="form.sort"
          :controls="false"
          :min="0"
          :max="999999"
        ></ProFormInputNumber>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import {
  ProDialog,
  ProForm,
  ProFormItemV2,
  ProFormText,
  ProFormInputNumber,
} from '@bole-core/components';
defineOptions({
  name: 'AddOrEditDictionaryCategory',
});
type Form = {
  id?: string;
  name: string;
  sort: number;
  code: string;
  fieldNames: string;
};
const form = defineModel<Form>('form');
const visible = defineModel<boolean>('modelValue');
const title = computed(() => (form.value.id ? '编辑' : '新增'));
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
</script>
src/views/DictionaryManage/components/AddOrEditDictionaryDialog.vue
New file
@@ -0,0 +1,142 @@
<template>
  <ProDialog
    :title="`${title}类别`"
    v-model="visible"
    @close="onDialogClose"
    destroy-on-close
    draggable
  >
    <ProForm :model="form" ref="dialogForm" label-width="90px">
      <ProFormItemV2
        label="行业类型:"
        prop="field1"
        v-if="category?.data?.code === '30'"
        :check-rules="[{ message: '请选择行业类型' }]"
      >
        <ProFormSelect
          v-model="form.field1"
          :value-enum="dictionaryDataList"
          enum-value-key="code"
        />
      </ProFormItemV2>
      <ProFormItemV2 label="名称:" prop="content" :check-rules="[{ message: '请输入名称' }]">
        <ProFormText
          placeholder="请输入名称"
          v-model.trim="form.content"
          :maxlength="15"
        ></ProFormText>
      </ProFormItemV2>
      <ProFormItemV2 label="排序:" prop="sort">
        <ProFormInputNumber
          v-model="form.sort"
          :controls="false"
          :min="0"
          :max="999999"
        ></ProFormInputNumber>
      </ProFormItemV2>
      <ProFormItemV2 label="编号:" prop="code">
        <ProFormText v-model.trim="form.code"></ProFormText>
      </ProFormItemV2>
      <ProFormItemV2 label="图片:" prop="src" v-if="category?.data?.code === '50'">
        <ProFormImageUpload v-model:file-url="form.field2" :limitFileCount="1"></ProFormImageUpload>
      </ProFormItemV2>
      <ProFormItemV2 label="状态:" prop="status">
        <ProFormRadio
          v-model="form.isDisabled"
          :value-enum="[
            { label: '启用', value: false },
            { label: '禁用', value: true },
          ]"
        ></ProFormRadio>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import {
  ProDialog,
  ProForm,
  ProFormItemV2,
  ProFormText,
  ProFormInputNumber,
  ProFormSelect,
  ProFormRadio,
  UploadUserFile,
  ProFormImageUpload,
} from '@bole-core/components';
import { useDictionaryDataSelect, useGetDictionaryCategorySelect } from '@/hooks';
import { CategoryCode } from '@/constants';
defineOptions({
  name: 'AddOrEditDictionaryDialog',
});
type Form = {
  id?: string;
  categoryId: string;
  content: string;
  code: string;
  sort: number;
  isDisabled: boolean;
  field1?: string;
  field2?: UploadUserFile[];
};
const form = defineModel<Form>('form');
const visible = defineModel<boolean>('modelValue');
const title = computed(() => (form.value.id ? '编辑' : '新增'));
const { getDictionaryCategoryById } = useGetDictionaryCategorySelect();
const { dictionaryDataList, refetch, getDictionaryDataNameById } = useDictionaryDataSelect({
  categoryCode: computed(() => CategoryCode.IndustryCategory),
});
const category = computed(() => {
  return getDictionaryCategoryById(form.value.categoryId);
});
watch(
  () => visible.value,
  (value) => {
    if (value) {
      refetch();
    }
  },
  {
    immediate: true,
  }
);
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
</script>
src/views/DictionaryManage/components/AddOrEditSearchSetting.vue
File was deleted
src/views/Permission/OperationUserManage.vue
New file
@@ -0,0 +1,175 @@
<template>
  <LoadingLayout :loading="state.loading">
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.keywords"
              style="width: 200px"
              placeholder="角色名称"
              @on-click-search="getList"
              @keyup.enter="getList()"
            >
            </SearchInput>
          </QueryFilterItem>
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
        <template #roles="{ row }">
          {{ row.roles?.map((x) => formatRoleName(x.name)).join() }}
        </template>
        <template #status="{ row }">
          <FieldSwitch
            v-model="row.status"
            active-text="启用"
            inactive-text="禁用"
            :active-value="EnumUserInfoStatus.Normal"
            :inactive-value="EnumUserInfoStatus.Disabled"
            :before-change="() => setStatus(row)"
          />
        </template>
      </ProTableV2>
    </AppContainer>
    <SetOperationUserRoleDialog v-bind="dialogProps" />
  </LoadingLayout>
</template>
<script setup lang="ts">
import {
  ProTableQueryFilterBar,
  OperationBtnType,
  ProTableV2,
  SearchInput,
  LoadingLayout,
  AppContainer,
  QueryFilterItem,
  useTable,
  FieldSwitch,
  useFormDialog,
} from '@bole-core/components';
import { useAccess } from '@/hooks';
import { formatRoleName } from '@/utils';
import * as userInfoServices from '@/services/api/userInfo';
import { Message } from '@bole-core/core';
import { EnumUserInfoStatus } from '@/constants';
import SetOperationUserRoleDialog from './components/SetOperationUserRoleDialog.vue';
defineOptions({
  name: 'OperationUserManage',
});
const operationBtnMap: Record<string, OperationBtnType> = {
  setRoleBtn: { emits: { onClick: (role) => openDialog(role) } },
};
const { checkSubModuleItemShow, column, operationBtns } = useAccess({
  operationBtnMap,
});
const BaseState = {
  loading: true,
};
const state = reactive({ ...BaseState });
onMounted(async () => {
  await getList();
  state.loading = false;
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetOperationUserInfosQuery = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        keywords: extraParamState.keywords,
      };
      let res = await userInfoServices.getOperationUserInfos(params, {
        showLoading: !state.loading,
      });
      return res;
    } catch (error) {}
  },
  {
    defaultExtraParams: {
      keywords: '',
      orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
    },
    queryKey: ['userInfoServices/getOperationUserInfos'],
    columnsRenderProps: {},
  }
);
async function setStatus(row: API.GetOperationUserInfosQueryResultItem) {
  try {
    await Message.tipMessage(
      `确认要${row.status === EnumUserInfoStatus.Normal ? '禁用' : '启用'}该账号吗?`
    );
    let params: API.SetUserInfoStatusCommand = {
      ids: [row.id],
      status:
        row.status === EnumUserInfoStatus.Normal
          ? EnumUserInfoStatus.Disabled
          : EnumUserInfoStatus.Normal,
    };
    let res = await userInfoServices.setUserInfoStatus(params);
    return !!res;
  } catch (error) {}
}
const { dialogProps, handleEdit, editForm } = useFormDialog({
  onConfirm: setUserInfoRoles,
  defaultFormParams: {
    roleIds: [] as string[],
    userInfoId: '',
    roles: [] as API.GetOperationUserInfosQueryResultItem[],
  },
});
async function openDialog(row?: API.GetOperationUserInfosQueryResultItem) {
  if (row) {
    const roles = await getUserInfoRoles(row);
    handleEdit({
      userInfoId: row.id,
      roleIds: row.roles?.map((x) => x.id),
      roles: roles,
    });
  }
}
async function setUserInfoRoles() {
  try {
    let params: API.SetUserInfoRolesCommand = {
      userInfoId: editForm.userInfoId,
      roleIds: editForm.roleIds,
    };
    let res = await userInfoServices.setUserInfoRoles(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
async function getUserInfoRoles(row: API.GetOperationUserInfosQueryResultItem) {
  try {
    let params: API.APIgetUserInfoRolesParams = {
      userInfoId: row.id,
      // clientType: row.clientType,
    };
    let res = await userInfoServices.getUserInfoRoles(params);
    return res;
  } catch (error) {}
}
</script>
src/views/Permission/components/SetOperationUserRoleDialog.vue
New file
@@ -0,0 +1,61 @@
<template>
  <ProDialog title="设置角色" v-model="visible" @close="onDialogClose" destroy-on-close draggable>
    <ProForm :model="form" ref="dialogForm" label-width="90px">
      <ProFormItemV2 label="角色" prop="roleIds" :check-rules="[{ message: '请选择角色' }]">
        <ProFormCheckbox
          v-model="form.roleIds"
          :value-enum="form.roles"
          enumLabelKey="name"
          enum-value-key="id"
        ></ProFormCheckbox>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import { ProDialog, ProForm, ProFormItemV2, ProFormCheckbox } from '@bole-core/components';
defineOptions({
  name: 'SetOperationUserRoleDialog',
});
type Form = {
  userInfoId: string;
  roleIds: string[];
  roles: API.GetOperationUserInfosQueryResultItem[];
};
const form = defineModel<Form>('form');
const visible = defineModel({ type: Boolean });
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
</script>
src/views/System/ModuleManage.vue
@@ -556,17 +556,32 @@
    if (drawerState.type === SubModuleType.Column) {
      let columnModuleList = drawerState.tableData; //.filter((d) => d.isEdit);
      if (columnModuleList.length > 0) {
        const groups = currentDrawerModule.value.groups.map((group) => {
          if (group.group === state.group) {
            group.fields = columnModuleList.map((c) => ({
        let groups = [...currentDrawerModule.value.groups];
        const isExist = groups.some((g) => g.group === state.group);
        if (isExist) {
          groups = groups.map((group) => {
            if (group.group === state.group) {
              group.fields = columnModuleList.map((c) => ({
                code: c.enCode,
                name: c.name,
                width: c.width,
                sort: c.sortCode,
              }));
            }
            return group;
          });
        } else {
          const group: API.GetMenuQueryResultGroup = {
            group: state.group,
            fields: columnModuleList.map((c) => ({
              code: c.enCode,
              name: c.name,
              width: c.width,
              sort: c.sortCode,
            }));
          }
          return group;
        });
            })),
          };
          groups.push(group);
        }
        let params: API.SaveMenuCommand = {
          ...currentDrawerModule.value,
          groups: groups,
types/api.d.ts
@@ -14,5 +14,17 @@
    customErrorHandler?: (error: any) => boolean;
  }
  interface SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOptionMap{
    field1?:string
  }
  interface SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOption{
    fieldNamesMap?: SelectQueryResultOptionGuidGetDictionaryCategorySelectQueryOptionMap;
    code?:string
  }
  interface SelectQueryResultOptionGuidGetDictionaryDataSelectQueryResultOption{
    code?:string
  }
}