refactor(projects): remove enum

This commit is contained in:
Soybean 2023-02-23 08:38:03 +08:00
parent 44b544745d
commit 21d5214247
31 changed files with 323 additions and 240 deletions

View File

@ -38,6 +38,11 @@ module.exports = {
group: 'external', group: 'external',
position: 'before' position: 'before'
}, },
{
pattern: '@/constants',
group: 'internal',
position: 'before'
},
{ {
pattern: '@/config', pattern: '@/config',
group: 'internal', group: 'internal',
@ -48,11 +53,6 @@ module.exports = {
group: 'internal', group: 'internal',
position: 'before' position: 'before'
}, },
{
pattern: '@/enum',
group: 'internal',
position: 'before'
},
{ {
pattern: '@/plugins', pattern: '@/plugins',
group: 'internal', group: 'internal',

View File

@ -3,7 +3,7 @@ import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
import { useAppStore, useThemeStore } from '@/store'; import { useAppStore, useThemeStore } from '@/store';
type LayoutMode = 'vertical' | 'horizontal'; type LayoutMode = 'vertical' | 'horizontal';
type LayoutHeaderProps = Record<EnumType.ThemeLayoutMode, App.GlobalHeaderProps>; type LayoutHeaderProps = Record<UnionKey.ThemeLayoutMode, App.GlobalHeaderProps>;
export function useBasicLayout() { export function useBasicLayout() {
const app = useAppStore(); const app = useAppStore();

View File

@ -42,8 +42,8 @@ export function useRouterPush(inSetup = true) {
* @param loginModule - * @param loginModule -
* @param redirectUrl - (),undefined表示取当前地址为重定向地址 * @param redirectUrl - (),undefined表示取当前地址为重定向地址
*/ */
function toLogin(loginModule?: EnumType.LoginModuleKey, redirectUrl?: string) { function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
const module: EnumType.LoginModuleKey = loginModule || 'pwd-login'; const module: UnionKey.LoginModule = loginModule || 'pwd-login';
const routeLocation: RouteLocationRaw = { const routeLocation: RouteLocationRaw = {
name: routeName('login'), name: routeName('login'),
params: { module } params: { module }
@ -57,7 +57,7 @@ export function useRouterPush(inSetup = true) {
* *
* @param module - * @param module -
*/ */
function toLoginModule(module: EnumType.LoginModuleKey) { function toLoginModule(module: UnionKey.LoginModule) {
const { query } = route.value; const { query } = route.value;
routerPush({ name: routeName('login'), params: { module }, query }); routerPush({ name: routeName('login'), params: { module }, query });
} }

View File

@ -1,10 +1,30 @@
export const loginModuleLabels: Record<UnionKey.LoginModule, string> = {
'pwd-login': '账密登录',
'code-login': '手机验证码登录',
register: '注册',
'reset-pwd': '重置密码',
'bind-wechat': '微信绑定'
};
export const userRoleLabels: Record<Auth.RoleType, string> = {
super: '超级管理员',
admin: '管理员',
user: '普通用户'
};
export const userRoleOptions: Common.OptionWithKey<Auth.RoleType>[] = [
{ value: 'super', label: userRoleLabels.super },
{ value: 'admin', label: userRoleLabels.admin },
{ value: 'user', label: userRoleLabels.user }
];
/** 用户性别 */ /** 用户性别 */
export const genderLabels: Record<UserManagement.GenderKey, string> = { export const genderLabels: Record<UserManagement.GenderKey, string> = {
0: '女', 0: '女',
1: '男' 1: '男'
}; };
export const genderOptions: { value: UserManagement.GenderKey; label: string }[] = [ export const genderOptions: Common.OptionWithKey<UserManagement.GenderKey>[] = [
{ value: '0', label: genderLabels['0'] }, { value: '0', label: genderLabels['0'] },
{ value: '1', label: genderLabels['1'] } { value: '1', label: genderLabels['1'] }
]; ];
@ -17,7 +37,7 @@ export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
4: '软删除' 4: '软删除'
}; };
export const userStatusOptions: { value: UserManagement.UserStatusKey; label: string }[] = [ export const userStatusOptions: Common.OptionWithKey<UserManagement.UserStatusKey>[] = [
{ value: '1', label: userStatusLabels['1'] }, { value: '1', label: userStatusLabels['1'] },
{ value: '2', label: userStatusLabels['2'] }, { value: '2', label: userStatusLabels['2'] },
{ value: '3', label: userStatusLabels['3'] }, { value: '3', label: userStatusLabels['3'] },

18
src/constants/common.ts Normal file
View File

@ -0,0 +1,18 @@
export const dataTypeLabels: { [K in TypeUtil.DataTypeStringKey]: TypeUtil.DataTypeString<K> } = {
string: '[object String]',
number: '[object Number]',
boolean: '[object Boolean]',
null: '[object Null]',
undefined: '[object Undefined]',
symbol: '[object Symbol]',
bigInt: '[object BigInt]',
object: '[object Object]',
function: '[object Function]',
array: '[object Array]',
date: '[object Date]',
regExp: '[object RegExp]',
promise: '[object Promise]',
set: '[object Set]',
map: '[object Map]',
file: '[object File]'
};

View File

@ -1 +1,3 @@
export * from './common';
export * from './system';
export * from './business'; export * from './business';

98
src/constants/system.ts Normal file
View File

@ -0,0 +1,98 @@
export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = {
vertical: '左侧菜单模式',
horizontal: '顶部菜单模式',
'vertical-mix': '左侧菜单混合模式',
'horizontal-mix': '顶部菜单混合模式'
};
export const themeLayoutModeOptions: Common.OptionWithKey<UnionKey.ThemeLayoutMode>[] = [
{
value: 'vertical',
label: themeLayoutModeLabels.vertical
},
{
value: 'horizontal',
label: themeLayoutModeLabels.horizontal
},
{
value: 'vertical-mix',
label: themeLayoutModeLabels['vertical-mix']
},
{
value: 'horizontal-mix',
label: themeLayoutModeLabels['horizontal-mix']
}
];
export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = {
chrome: '谷歌风格',
button: '按钮风格'
};
export const themeTabModeOptions: Common.OptionWithKey<UnionKey.ThemeTabMode>[] = [
{
value: 'chrome',
label: themeTabModeLabels.chrome
},
{
value: 'button',
label: themeTabModeLabels.button
}
];
export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = {
'flex-start': '居左',
center: '居中',
'flex-end': '居右'
};
export const themeHorizontalMenuPositionOptions: Common.OptionWithKey<UnionKey.ThemeHorizontalMenuPosition>[] = [
{
value: 'flex-start',
label: themeHorizontalMenuPositionLabels['flex-start']
},
{
value: 'center',
label: themeHorizontalMenuPositionLabels.center
},
{
value: 'flex-end',
label: themeHorizontalMenuPositionLabels['flex-end']
}
];
export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = {
'zoom-fade': '渐变',
'zoom-out': '闪现',
'fade-slide': '滑动',
fade: '消退',
'fade-bottom': '底部消退',
'fade-scale': '缩放消退'
};
export const themeAnimateModeOptions: Common.OptionWithKey<UnionKey.ThemeAnimateMode>[] = [
{
value: 'zoom-fade',
label: themeAnimateModeLabels['zoom-fade']
},
{
value: 'zoom-out',
label: themeAnimateModeLabels['zoom-out']
},
{
value: 'fade-slide',
label: themeAnimateModeLabels['fade-slide']
},
{
value: 'fade',
label: themeAnimateModeLabels.fade
},
{
value: 'fade-bottom',
label: themeAnimateModeLabels['fade-bottom']
},
{
value: 'fade-scale',
label: themeAnimateModeLabels['fade-scale']
}
];

View File

@ -1,15 +0,0 @@
/** 用户角色 */
export enum EnumUserRole {
super = '超级管理员',
admin = '管理员',
user = '普通用户'
}
/** 登录模块 */
export enum EnumLoginModule {
'pwd-login' = '账密登录',
'code-login' = '手机验证码登录',
'register' = '注册',
'reset-pwd' = '重置密码',
'bind-wechat' = '微信绑定'
}

View File

@ -1,24 +0,0 @@
/** http请求头的content-type类型 */
export enum EnumContentType {
json = 'application/json',
formUrlencoded = 'application/x-www-form-urlencoded',
formData = 'multipart/form-data'
}
/** 数据类型 */
export enum EnumDataType {
number = '[object Number]',
string = '[object String]',
boolean = '[object Boolean]',
null = '[object Null]',
undefined = '[object Undefined]',
object = '[object Object]',
array = '[object Array]',
function = '[object Function]',
date = '[object Date]',
regexp = '[object RegExp]',
promise = '[object Promise]',
set = '[object Set]',
map = '[object Map]',
file = '[object File]'
}

View File

@ -1,3 +0,0 @@
export * from './common';
export * from './system';
export * from './business';

View File

@ -1,36 +0,0 @@
/** 布局组件的名称 */
export enum EnumLayoutComponentName {
basic = 'basic-layout',
blank = 'blank-layout'
}
/** 布局模式 */
export enum EnumThemeLayoutMode {
'vertical' = '左侧菜单模式',
'horizontal' = '顶部菜单模式',
'vertical-mix' = '左侧菜单混合模式',
'horizontal-mix' = '顶部菜单混合模式'
}
/** 多页签风格 */
export enum EnumThemeTabMode {
'chrome' = '谷歌风格',
'button' = '按钮风格'
}
/** 水平模式的菜单位置 */
export enum EnumThemeHorizontalMenuPosition {
'flex-start' = '居左',
'center' = '居中',
'flex-end' = '居右'
}
/** 过渡动画类型 */
export enum EnumThemeAnimateMode {
'zoom-fade' = '渐变',
'zoom-out' = '闪现',
'fade-slide' = '滑动',
'fade' = '消退',
'fade-bottom' = '底部消退',
'fade-scale' = '缩放消退'
}

View File

@ -18,15 +18,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import type { PopoverPlacement } from 'naive-ui'; import type { PopoverPlacement } from 'naive-ui';
import type { EnumThemeLayoutMode } from '@/enum';
defineOptions({ name: 'LayoutCheckbox' }); defineOptions({ name: 'LayoutCheckbox' });
interface Props { interface Props {
/** 布局模式 */ /** 布局模式 */
mode: EnumType.ThemeLayoutMode; mode: UnionKey.ThemeLayoutMode;
/** 布局模式文本 */ /** 布局模式文本 */
label: EnumThemeLayoutMode; label: string;
/** 选中状态 */ /** 选中状态 */
checked: boolean; checked: boolean;
} }
@ -34,7 +33,7 @@ interface Props {
const props = defineProps<Props>(); const props = defineProps<Props>();
type LayoutConfig = Record< type LayoutConfig = Record<
EnumType.ThemeLayoutMode, UnionKey.ThemeLayoutMode,
{ {
placement: PopoverPlacement; placement: PopoverPlacement;
menuClass: string; menuClass: string;

View File

@ -18,7 +18,7 @@ export const constantRoutes: AuthRoute.Route[] = [
path: '/login', path: '/login',
component: 'self', component: 'self',
props: route => { props: route => {
const moduleType = (route.params.module as EnumType.LoginModuleKey) || 'pwd-login'; const moduleType = (route.params.module as UnionKey.LoginModule) || 'pwd-login';
return { return {
module: moduleType module: moduleType
}; };

View File

@ -46,7 +46,7 @@ export default class CustomAxiosInstance {
const handleConfig = { ...config }; const handleConfig = { ...config };
if (handleConfig.headers) { if (handleConfig.headers) {
// 数据转换 // 数据转换
const contentType = handleConfig.headers['Content-Type'] as string; const contentType = handleConfig.headers['Content-Type'] as UnionKey.ContentType;
handleConfig.data = await transformRequestData(handleConfig.data, contentType); handleConfig.data = await transformRequestData(handleConfig.data, contentType);
// 设置token // 设置token
handleConfig.headers.Authorization = localStg.get('token') || ''; handleConfig.headers.Authorization = localStg.get('token') || '';

View File

@ -1,4 +1,9 @@
import { EnumThemeAnimateMode, EnumThemeHorizontalMenuPosition, EnumThemeLayoutMode, EnumThemeTabMode } from '@/enum'; import {
themeLayoutModeOptions,
themeTabModeOptions,
themeHorizontalMenuPositionOptions,
themeAnimateModeOptions
} from '@/constants';
import jsonSetting from './theme.json'; import jsonSetting from './theme.json';
const themeColorList = [ const themeColorList = [
@ -34,12 +39,7 @@ const defaultThemeSetting: Theme.Setting = {
layout: { layout: {
minWidth: 900, minWidth: 900,
mode: 'vertical', mode: 'vertical',
modeList: [ modeList: themeLayoutModeOptions
{ value: 'vertical', label: EnumThemeLayoutMode.vertical },
{ value: 'vertical-mix', label: EnumThemeLayoutMode['vertical-mix'] },
{ value: 'horizontal', label: EnumThemeLayoutMode.horizontal },
{ value: 'horizontal-mix', label: EnumThemeLayoutMode['horizontal-mix'] }
]
}, },
themeColor: themeColorList[0], themeColor: themeColorList[0],
themeColorList, themeColorList,
@ -64,10 +64,7 @@ const defaultThemeSetting: Theme.Setting = {
visible: true, visible: true,
height: 44, height: 44,
mode: 'chrome', mode: 'chrome',
modeList: [ modeList: themeTabModeOptions,
{ value: 'chrome', label: EnumThemeTabMode.chrome },
{ value: 'button', label: EnumThemeTabMode.button }
],
isCache: true isCache: true
}, },
sider: { sider: {
@ -80,11 +77,7 @@ const defaultThemeSetting: Theme.Setting = {
}, },
menu: { menu: {
horizontalPosition: 'flex-start', horizontalPosition: 'flex-start',
horizontalPositionList: [ horizontalPositionList: themeHorizontalMenuPositionOptions
{ value: 'flex-start', label: EnumThemeHorizontalMenuPosition['flex-start'] },
{ value: 'center', label: EnumThemeHorizontalMenuPosition.center },
{ value: 'flex-end', label: EnumThemeHorizontalMenuPosition['flex-end'] }
]
}, },
footer: { footer: {
fixed: false, fixed: false,
@ -94,14 +87,7 @@ const defaultThemeSetting: Theme.Setting = {
page: { page: {
animate: true, animate: true,
animateMode: 'fade-slide', animateMode: 'fade-slide',
animateModeList: [ animateModeList: themeAnimateModeOptions
{ value: 'fade-slide', label: EnumThemeAnimateMode['fade-slide'] },
{ value: 'fade', label: EnumThemeAnimateMode.fade },
{ value: 'fade-bottom', label: EnumThemeAnimateMode['fade-bottom'] },
{ value: 'fade-scale', label: EnumThemeAnimateMode['fade-scale'] },
{ value: 'zoom-fade', label: EnumThemeAnimateMode['zoom-fade'] },
{ value: 'zoom-out', label: EnumThemeAnimateMode['zoom-out'] }
]
} }
}; };

View File

@ -58,7 +58,7 @@ export const useThemeStore = defineStore('theme-store', {
this.layout.minWidth = minWidth; this.layout.minWidth = minWidth;
}, },
/** 设置布局模式 */ /** 设置布局模式 */
setLayoutMode(mode: EnumType.ThemeLayoutMode) { setLayoutMode(mode: UnionKey.ThemeLayoutMode) {
this.layout.mode = mode; this.layout.mode = mode;
}, },
/** 设置侧边栏反转色 */ /** 设置侧边栏反转色 */
@ -106,7 +106,7 @@ export const useThemeStore = defineStore('theme-store', {
} }
}, },
/** 设置多页签风格 */ /** 设置多页签风格 */
setTabMode(mode: EnumType.ThemeTabMode) { setTabMode(mode: UnionKey.ThemeTabMode) {
this.tab.mode = mode; this.tab.mode = mode;
}, },
/** 设置多页签缓存 */ /** 设置多页签缓存 */
@ -138,7 +138,7 @@ export const useThemeStore = defineStore('theme-store', {
this.sider.mixChildMenuWidth = width; this.sider.mixChildMenuWidth = width;
}, },
/** 设置水平模式的菜单的位置 */ /** 设置水平模式的菜单的位置 */
setHorizontalMenuPosition(position: EnumType.ThemeHorizontalMenuPosition) { setHorizontalMenuPosition(position: UnionKey.ThemeHorizontalMenuPosition) {
this.menu.horizontalPosition = position; this.menu.horizontalPosition = position;
}, },
/** 设置底部是否固定 */ /** 设置底部是否固定 */
@ -158,7 +158,7 @@ export const useThemeStore = defineStore('theme-store', {
this.page.animate = animate; this.page.animate = animate;
}, },
/** 设置页面过渡动画类型 */ /** 设置页面过渡动画类型 */
setPageAnimateMode(mode: EnumType.ThemeAnimateMode) { setPageAnimateMode(mode: UnionKey.ThemeAnimateMode) {
this.page.animateMode = mode; this.page.animateMode = mode;
} }
} }

View File

@ -5,9 +5,8 @@ declare namespace Auth {
* - super: () * - super: ()
* - admin: 管理员 * - admin: 管理员
* - user: 用户 * - user: 用户
* - custom: 自定义角色
*/ */
type RoleType = keyof typeof import('@/enum').EnumUserRole; type RoleType = 'super' | 'admin' | 'user';
/** 用户信息 */ /** 用户信息 */
interface UserInfo { interface UserInfo {

View File

@ -12,6 +12,9 @@ declare namespace Common {
* [, true时执行的回调函数] * [, true时执行的回调函数]
*/ */
type StrategyAction = [boolean, () => void]; type StrategyAction = [boolean, () => void];
/** 选项数据 */
type OptionWithKey<K> = { value: K; label: string };
} }
/** 构建时间 */ /** 构建时间 */

View File

@ -1,24 +1,3 @@
/** 枚举的key类型 */
declare namespace EnumType {
/** 布局组件名称 */
type LayoutComponentName = keyof typeof import('@/enum').EnumLayoutComponentName;
/** 布局模式 */
type ThemeLayoutMode = keyof typeof import('@/enum').EnumThemeLayoutMode;
/** 多页签风格 */
type ThemeTabMode = keyof typeof import('@/enum').EnumThemeTabMode;
/** 水平模式的菜单位置 */
type ThemeHorizontalMenuPosition = keyof typeof import('@/enum').EnumThemeHorizontalMenuPosition;
/** 过渡动画 */
type ThemeAnimateMode = keyof typeof import('@/enum').EnumThemeAnimateMode;
/** 登录模块 */
type LoginModuleKey = keyof typeof import('@/enum').EnumLoginModule;
}
/** 请求的相关类型 */ /** 请求的相关类型 */
declare namespace Service { declare namespace Service {
/** /**
@ -143,13 +122,9 @@ declare namespace Theme {
/** 最小宽度 */ /** 最小宽度 */
minWidth: number; minWidth: number;
/** 布局模式 */ /** 布局模式 */
mode: EnumType.ThemeLayoutMode; mode: UnionKey.ThemeLayoutMode;
/** 布局模式列表 */ /** 布局模式列表 */
modeList: LayoutModeList[]; modeList: Common.OptionWithKey<UnionKey.ThemeLayoutMode>[];
}
interface LayoutModeList {
value: EnumType.ThemeLayoutMode;
label: import('@/enum').EnumThemeLayoutMode;
} }
/** 其他主题颜色 */ /** 其他主题颜色 */
@ -188,19 +163,13 @@ declare namespace Theme {
/** 多页签高度 */ /** 多页签高度 */
height: number; height: number;
/** 多页签风格 */ /** 多页签风格 */
mode: EnumType.ThemeTabMode; mode: UnionKey.ThemeTabMode;
/** 多页签风格列表 */ /** 多页签风格列表 */
modeList: ThemeTabModeList[]; modeList: Common.OptionWithKey<UnionKey.ThemeTabMode>[];
/** 开启多页签缓存 */ /** 开启多页签缓存 */
isCache: boolean; isCache: boolean;
} }
/** 多页签风格列表 */
interface ThemeTabModeList {
value: EnumType.ThemeTabMode;
label: import('@/enum').EnumThemeTabMode;
}
/** 侧边栏样式 */ /** 侧边栏样式 */
interface Sider { interface Sider {
/** 侧边栏反转色 */ /** 侧边栏反转色 */
@ -220,14 +189,9 @@ declare namespace Theme {
/** 菜单样式 */ /** 菜单样式 */
interface Menu { interface Menu {
/** 水平模式的菜单的位置 */ /** 水平模式的菜单的位置 */
horizontalPosition: EnumType.ThemeHorizontalMenuPosition; horizontalPosition: UnionKey.ThemeHorizontalMenuPosition;
/** 水平模式的菜单的位置列表 */ /** 水平模式的菜单的位置列表 */
horizontalPositionList: HorizontalMenuPositionList[]; horizontalPositionList: Common.OptionWithKey<UnionKey.ThemeHorizontalMenuPosition>[];
}
/** 水平模式的菜单的位置列表 */
interface HorizontalMenuPositionList {
value: EnumType.ThemeHorizontalMenuPosition;
label: import('@/enum').EnumThemeHorizontalMenuPosition;
} }
/** 底部样式 */ /** 底部样式 */
@ -245,14 +209,9 @@ declare namespace Theme {
/** 页面是否开启动画 */ /** 页面是否开启动画 */
animate: boolean; animate: boolean;
/** 动画类型 */ /** 动画类型 */
animateMode: EnumType.ThemeAnimateMode; animateMode: UnionKey.ThemeAnimateMode;
/** 动画类型列表 */ /** 动画类型列表 */
animateModeList: AnimateModeList[]; animateModeList: Common.OptionWithKey<UnionKey.ThemeAnimateMode>[];
}
/** 动画类型列表 */
interface AnimateModeList {
value: EnumType.ThemeAnimateMode;
label: import('@/enum').EnumThemeAnimateMode;
} }
} }

56
src/typings/union-key.d.ts vendored Normal file
View File

@ -0,0 +1,56 @@
declare namespace UnionKey {
/** http请求头的content-type类型 */
type ContentType = 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data';
/**
*
* - pwd-login: 账密登录
* - code-login: 手机验证码登录
* - register: 注册
* - reset-pwd: 重置密码
* - bind-wechat: 微信绑定
*/
type LoginModule = 'pwd-login' | 'code-login' | 'register' | 'reset-pwd' | 'bind-wechat';
/**
*
* - vertical: 左侧菜单模式
* - horizontal: 顶部菜单模式
* - vertical-mix: 左侧菜单混合模式
* - horizontal-mix: 顶部菜单混合模式
*/
type ThemeLayoutMode = 'vertical' | 'horizontal' | 'vertical-mix' | 'horizontal-mix';
/**
*
* - chrome: 谷歌风格
* - button: 按钮风格
*/
type ThemeTabMode = 'chrome' | 'button';
/**
*
* - flex-start: 居左
* - center: 居中
* - flex-end: 居右
*/
type ThemeHorizontalMenuPosition = 'flex-start' | 'center' | 'flex-end';
/**
*
* - zoom-fade: 渐变
* - zoom-out: 闪现
* - fade-slide: 滑动
* - fade: 消退
* - fade-bottom: 底部消退
* - fade-scale: 缩放消退
*/
type ThemeAnimateMode = 'zoom-fade' | 'zoom-out' | 'fade-slide' | 'fade' | 'fade-bottom' | 'fade-scale';
/**
*
* - basic
* - blank
*/
type LayoutComponentName = 'basic' | 'blank';
}

View File

@ -1,9 +1,30 @@
declare namespace TypeUtil { declare namespace TypeUtil {
type Noop = (...args: any) => any; type Noop = (...args: any) => any;
type UnionInclude<T, K extends keyof T> = K extends keyof T ? true : false; interface DataType {
number: number;
string: string;
boolean: boolean;
null: null;
undefined: undefined;
symbol: symbol;
bigInt: bigint;
object: Record<string, any>;
array: Array<any>;
function: (...args: any[]) => any | void;
date: Date;
regExp: RegExp;
promise: Promise<any>;
set: Set<any>;
map: Map<any, any>;
file: File;
}
type GetFunArgs<F extends Noop> = F extends (...args: infer P) => any ? P : never; type DataTypeStringKey = keyof DataType;
type DataTypeString<T extends DataTypeStringKey = DataTypeStringKey> = `[object ${Capitalize<T>}]`;
type UnionInclude<T, K extends keyof T> = K extends keyof T ? true : false;
type Writable<T> = { [K in keyof T]: T[K] }; type Writable<T> = { [K in keyof T]: T[K] };

View File

@ -1,57 +1,69 @@
import { EnumDataType } from '@/enum'; import { dataTypeLabels } from '@/constants';
export function isNumber<T extends number>(data: T | unknown): data is T { function getDataTypeString<K extends TypeUtil.DataTypeStringKey>(value: unknown) {
return Object.prototype.toString.call(data) === EnumDataType.number; return Object.prototype.toString.call(value) as TypeUtil.DataTypeString<K>;
} }
export function isString<T extends string>(data: T | unknown): data is T { export function isNumber<T extends number>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.string; return getDataTypeString(value) === dataTypeLabels.number;
} }
export function isBoolean<T extends boolean>(data: T | unknown): data is T { export function isString<T extends string>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.boolean; return getDataTypeString(value) === dataTypeLabels.string;
} }
export function isNull<T extends null>(data: T | unknown): data is T { export function isBoolean<T extends boolean>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.null; return getDataTypeString(value) === dataTypeLabels.boolean;
} }
export function isUndefined<T extends undefined>(data: T | unknown): data is T { export function isNull<T extends null>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.undefined; return getDataTypeString(value) === dataTypeLabels.null;
} }
export function isObject<T extends Record<string, any>>(data: T | unknown): data is T { export function isUndefined<T extends undefined>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.object; return getDataTypeString(value) === dataTypeLabels.undefined;
} }
export function isArray<T extends any[]>(data: T | unknown): data is T { export function isSymbol<T extends symbol>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.array; return getDataTypeString(value) === dataTypeLabels.symbol;
} }
export function isFunction<T extends (...args: any[]) => any | void | never>(data: T | unknown): data is T { export function isBigInt<T extends bigint>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.function; return getDataTypeString(value) === dataTypeLabels.bigInt;
} }
export function isDate<T extends Date>(data: T | unknown): data is T { export function isObject<T extends Record<string, any>>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.date; return getDataTypeString(value) === dataTypeLabels.object;
} }
export function isRegExp<T extends RegExp>(data: T | unknown): data is T { export function isArray<T extends any[]>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.regexp; return getDataTypeString(value) === dataTypeLabels.array;
} }
export function isPromise<T extends Promise<any>>(data: T | unknown): data is T { export function isFunction<T extends (...args: any[]) => any | void>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.promise; return getDataTypeString(value) === dataTypeLabels.function;
} }
export function isSet<T extends Set<any>>(data: T | unknown): data is T { export function isDate<T extends Date>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.set; return getDataTypeString(value) === dataTypeLabels.date;
} }
export function isMap<T extends Map<any, any>>(data: T | unknown): data is T { export function isRegExp<T extends RegExp>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.map; return getDataTypeString(value) === dataTypeLabels.regExp;
} }
export function isFile<T extends File>(data: T | unknown): data is T { export function isPromise<T extends Promise<any>>(value: T | unknown): value is T {
return Object.prototype.toString.call(data) === EnumDataType.file; return getDataTypeString(value) === dataTypeLabels.promise;
}
export function isSet<T extends Set<any>>(value: T | unknown): value is T {
return getDataTypeString(value) === dataTypeLabels.set;
}
export function isMap<T extends Map<any, any>>(value: T | unknown): value is T {
return getDataTypeString(value) === dataTypeLabels.map;
}
export function isFile<T extends File>(value: T | unknown): value is T {
return getDataTypeString(value) === dataTypeLabels.file;
} }

View File

@ -9,13 +9,13 @@ interface ModuleComponent {
default: RouteComponent; default: RouteComponent;
} }
type LayoutComponent = Record<EnumType.LayoutComponentName, Lazy<ModuleComponent>>; type LayoutComponent = Record<UnionKey.LayoutComponentName, Lazy<ModuleComponent>>;
/** /**
* vue文件() * vue文件()
* @param layoutType - * @param layoutType -
*/ */
export function getLayoutComponent(layoutType: EnumType.LayoutComponentName) { export function getLayoutComponent(layoutType: UnionKey.LayoutComponentName) {
const layoutComponent: LayoutComponent = { const layoutComponent: LayoutComponent = {
basic: BasicLayout, basic: BasicLayout,
blank: BlankLayout blank: BlankLayout

View File

@ -1,5 +1,5 @@
/** 获取登录页面模块的动态路由的正则 */ /** 获取登录页面模块的动态路由的正则 */
export function getLoginModuleRegExp() { export function getLoginModuleRegExp() {
const modules: EnumType.LoginModuleKey[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat']; const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat'];
return modules.join('|'); return modules.join('|');
} }

View File

@ -17,7 +17,7 @@ export async function handleServiceResult<T = any>(error: Service.RequestError |
/** 请求结果的适配器:用于接收适配器函数和请求结果 */ /** 请求结果的适配器:用于接收适配器函数和请求结果 */
export function adapter<T extends Service.ServiceAdapter>( export function adapter<T extends Service.ServiceAdapter>(
adapterFun: T, adapterFun: T,
...args: Service.MultiRequestResult<TypeUtil.GetFunArgs<T>> ...args: Service.MultiRequestResult<Parameters<T>>
): Service.RequestResult<ReturnType<T>> { ): Service.RequestResult<ReturnType<T>> {
let result: Service.RequestResult | undefined; let result: Service.RequestResult | undefined;

View File

@ -1,6 +1,5 @@
import qs from 'qs'; import qs from 'qs';
import FormData from 'form-data'; import FormData from 'form-data';
import { EnumContentType } from '@/enum';
import { isArray, isFile } from '../common'; import { isArray, isFile } from '../common';
/** /**
@ -8,15 +7,15 @@ import { isArray, isFile } from '../common';
* @param requestData - * @param requestData -
* @param contentType - Content-Type * @param contentType - Content-Type
*/ */
export async function transformRequestData(requestData: any, contentType?: string) { export async function transformRequestData(requestData: any, contentType?: UnionKey.ContentType) {
// application/json类型不处理 // application/json类型不处理
let data = requestData; let data = requestData;
// form类型转换 // form类型转换
if (contentType === EnumContentType.formUrlencoded) { if (contentType === 'application/x-www-form-urlencoded') {
data = qs.stringify(requestData); data = qs.stringify(requestData);
} }
// form-data类型转换 // form-data类型转换
if (contentType === EnumContentType.formData) { if (contentType === 'multipart/form-data') {
data = await handleFormData(requestData); data = await handleFormData(requestData);
} }

View File

@ -23,11 +23,11 @@
</n-button> </n-button>
<div class="flex-y-center justify-between"> <div class="flex-y-center justify-between">
<n-button class="flex-1" :block="true" @click="toLoginModule('code-login')"> <n-button class="flex-1" :block="true" @click="toLoginModule('code-login')">
{{ EnumLoginModule['code-login'] }} {{ loginModuleLabels['code-login'] }}
</n-button> </n-button>
<div class="w-12px"></div> <div class="w-12px"></div>
<n-button class="flex-1" :block="true" @click="toLoginModule('register')"> <n-button class="flex-1" :block="true" @click="toLoginModule('register')">
{{ EnumLoginModule.register }} {{ loginModuleLabels.register }}
</n-button> </n-button>
</div> </div>
</n-space> </n-space>
@ -38,7 +38,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import type { FormInst, FormRules } from 'naive-ui'; import type { FormInst, FormRules } from 'naive-ui';
import { EnumLoginModule } from '@/enum'; import { loginModuleLabels } from '@/constants';
import { useAuthStore } from '@/store'; import { useAuthStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { formRules } from '@/utils'; import { formRules } from '@/utils';

View File

@ -28,7 +28,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import type { Component } from 'vue'; import type { Component } from 'vue';
import { EnumLoginModule } from '@/enum'; import { loginModuleLabels } from '@/constants';
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { useAppInfo } from '@/composables'; import { useAppInfo } from '@/composables';
import { getColorPalette, mixColor } from '@/utils'; import { getColorPalette, mixColor } from '@/utils';
@ -36,7 +36,7 @@ import { BindWechat, CodeLogin, LoginBg, PwdLogin, Register, ResetPwd } from './
interface Props { interface Props {
/** 登录模块分类 */ /** 登录模块分类 */
module: EnumType.LoginModuleKey; module: UnionKey.LoginModule;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
@ -45,17 +45,17 @@ const theme = useThemeStore();
const { title } = useAppInfo(); const { title } = useAppInfo();
interface LoginModule { interface LoginModule {
key: EnumType.LoginModuleKey; key: UnionKey.LoginModule;
label: EnumLoginModule; label: string;
component: Component; component: Component;
} }
const modules: LoginModule[] = [ const modules: LoginModule[] = [
{ key: 'pwd-login', label: EnumLoginModule['pwd-login'], component: PwdLogin }, { key: 'pwd-login', label: loginModuleLabels['pwd-login'], component: PwdLogin },
{ key: 'code-login', label: EnumLoginModule['code-login'], component: CodeLogin }, { key: 'code-login', label: loginModuleLabels['code-login'], component: CodeLogin },
{ key: 'register', label: EnumLoginModule.register, component: Register }, { key: 'register', label: loginModuleLabels.register, component: Register },
{ key: 'reset-pwd', label: EnumLoginModule['reset-pwd'], component: ResetPwd }, { key: 'reset-pwd', label: loginModuleLabels['reset-pwd'], component: ResetPwd },
{ key: 'bind-wechat', label: EnumLoginModule['bind-wechat'], component: BindWechat } { key: 'bind-wechat', label: loginModuleLabels['bind-wechat'], component: BindWechat }
]; ];
const activeModule = computed(() => { const activeModule = computed(() => {

View File

@ -34,7 +34,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { watch } from 'vue'; import { watch } from 'vue';
import type { SelectOption } from 'naive-ui'; import type { SelectOption } from 'naive-ui';
import { EnumUserRole } from '@/enum'; import { userRoleOptions } from '@/constants';
import { useAppStore, useAuthStore } from '@/store'; import { useAppStore, useAuthStore } from '@/store';
import { usePermission } from '@/composables'; import { usePermission } from '@/composables';
@ -42,18 +42,7 @@ const app = useAppStore();
const auth = useAuthStore(); const auth = useAuthStore();
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
interface RoleList { const options: SelectOption[] = userRoleOptions;
label: string;
value: keyof typeof EnumUserRole;
}
const roleList: RoleList[] = [
{ label: EnumUserRole.super, value: 'super' },
{ label: EnumUserRole.admin, value: 'admin' },
{ label: EnumUserRole.user, value: 'user' }
];
const options: SelectOption[] = roleList as unknown as SelectOption[];
watch( watch(
() => auth.userInfo.userRole, () => auth.userInfo.userRole,

View File

@ -34,8 +34,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue'; import { ref, computed, reactive, watch } from 'vue';
import type { FormInst, FormItemRule } from 'naive-ui'; import type { FormInst, FormItemRule } from 'naive-ui';
import { formRules, createRequiredFormRule } from '@/utils';
import { genderOptions, userStatusOptions } from '@/constants'; import { genderOptions, userStatusOptions } from '@/constants';
import { formRules, createRequiredFormRule } from '@/utils';
export interface Props { export interface Props {
/** 弹窗可见性 */ /** 弹窗可见性 */

View File

@ -33,9 +33,9 @@ import { reactive, ref } from 'vue';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { NButton, NPopconfirm, NSpace, NTag } from 'naive-ui'; import { NButton, NPopconfirm, NSpace, NTag } from 'naive-ui';
import type { DataTableColumns, PaginationProps } from 'naive-ui'; import type { DataTableColumns, PaginationProps } from 'naive-ui';
import { genderLabels, userStatusLabels } from '@/constants';
import { fetchUserList } from '@/service'; import { fetchUserList } from '@/service';
import { useBoolean, useLoading } from '@/hooks'; import { useBoolean, useLoading } from '@/hooks';
import { genderLabels, userStatusLabels } from '@/constants';
import TableActionModal from './components/table-action-modal.vue'; import TableActionModal from './components/table-action-modal.vue';
import type { ModalType } from './components/table-action-modal.vue'; import type { ModalType } from './components/table-action-modal.vue';
import ColumnSetting from './components/column-setting.vue'; import ColumnSetting from './components/column-setting.vue';