From 8d0185b35a26d1e1271af29fc5634046f7ceab40 Mon Sep 17 00:00:00 2001 From: wangys <3401275564@qq.com> Date: Mon, 6 Oct 2025 16:49:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AFtypes=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schoolNewsWeb/src/apis/auth.ts | 71 ++++++ schoolNewsWeb/src/apis/index.ts | 257 +++++++++++++++++--- schoolNewsWeb/src/apis/menu.ts | 92 +++++++ schoolNewsWeb/src/apis/user.ts | 153 ++++++++++++ schoolNewsWeb/src/domain/index.ts | 2 - schoolNewsWeb/src/domain/types/common.ts | 19 -- schoolNewsWeb/src/types/auth/index.ts | 86 +++++++ schoolNewsWeb/src/types/base/index.ts | 76 ++++++ schoolNewsWeb/src/types/constants/index.ts | 30 +++ schoolNewsWeb/src/types/dept/index.ts | 47 ++++ schoolNewsWeb/src/types/enums/index.ts | 76 ++++++ schoolNewsWeb/src/types/index.ts | 33 +++ schoolNewsWeb/src/types/menu/index.ts | 59 +++++ schoolNewsWeb/src/types/permission/index.ts | 26 ++ schoolNewsWeb/src/types/role/index.ts | 34 +++ schoolNewsWeb/src/types/user/index.ts | 70 ++++++ 16 files changed, 1081 insertions(+), 50 deletions(-) create mode 100644 schoolNewsWeb/src/apis/auth.ts create mode 100644 schoolNewsWeb/src/apis/menu.ts create mode 100644 schoolNewsWeb/src/apis/user.ts delete mode 100644 schoolNewsWeb/src/domain/index.ts delete mode 100644 schoolNewsWeb/src/domain/types/common.ts create mode 100644 schoolNewsWeb/src/types/auth/index.ts create mode 100644 schoolNewsWeb/src/types/base/index.ts create mode 100644 schoolNewsWeb/src/types/constants/index.ts create mode 100644 schoolNewsWeb/src/types/dept/index.ts create mode 100644 schoolNewsWeb/src/types/enums/index.ts create mode 100644 schoolNewsWeb/src/types/index.ts create mode 100644 schoolNewsWeb/src/types/menu/index.ts create mode 100644 schoolNewsWeb/src/types/permission/index.ts create mode 100644 schoolNewsWeb/src/types/role/index.ts create mode 100644 schoolNewsWeb/src/types/user/index.ts diff --git a/schoolNewsWeb/src/apis/auth.ts b/schoolNewsWeb/src/apis/auth.ts new file mode 100644 index 0000000..64b6163 --- /dev/null +++ b/schoolNewsWeb/src/apis/auth.ts @@ -0,0 +1,71 @@ +/** + * @description 认证相关API + * @author yslg + * @since 2025-10-06 + */ + +import { api } from './index'; +import type { LoginParam, LoginDomain } from '@/types'; + +/** + * 认证API服务 + */ +export const authApi = { + /** + * 用户登录 + * @param loginParam 登录参数 + * @returns Promise + */ + async login(loginParam: LoginParam): Promise { + const response = await api.post('/auth/login', loginParam); + return response.data.data!; + }, + + /** + * 用户登出 + * @returns Promise + */ + async logout(): Promise { + const response = await api.post('/auth/logout'); + return response.data.data!; + }, + + /** + * 获取验证码 + * @returns Promise<{captchaId: string, captchaImage: string}> + */ + async getCaptcha(): Promise<{ captchaId: string; captchaImage: string }> { + const response = await api.get<{ captchaId: string; captchaImage: string }>('/auth/captcha'); + return response.data.data!; + }, + + /** + * 刷新Token + * @returns Promise + */ + async refreshToken(): Promise { + const response = await api.post('/auth/refresh-token'); + return response.data.data!; + }, + + /** + * 发送手机验证码 + * @param phone 手机号 + * @returns Promise + */ + async sendSmsCode(phone: string): Promise { + const response = await api.post('/auth/send-sms-code', { phone }); + return response.data.data!; + }, + + /** + * 发送邮箱验证码 + * @param email 邮箱 + * @returns Promise + */ + async sendEmailCode(email: string): Promise { + const response = await api.post('/auth/send-email-code', { email }); + return response.data.data!; + } +}; + diff --git a/schoolNewsWeb/src/apis/index.ts b/schoolNewsWeb/src/apis/index.ts index f7e2777..7cba056 100644 --- a/schoolNewsWeb/src/apis/index.ts +++ b/schoolNewsWeb/src/apis/index.ts @@ -1,50 +1,249 @@ -import axios, { AxiosRequestConfig } from "axios"; -import { ElLoading } from "element-plus"; +import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"; +import { ElLoading, ElMessage } from "element-plus"; +import type { ResultDomain } from "@/types"; +/** + * 扩展AxiosRequestConfig以支持自定义配置 + */ +interface CustomAxiosRequestConfig extends AxiosRequestConfig { + /** 是否显示加载动画 */ + showLoading?: boolean; + /** 是否显示错误提示 */ + showError?: boolean; + /** 是否需要token */ + requiresAuth?: boolean; +} + +/** + * Token管理 + */ +export const TokenManager = { + /** 获取token */ + getToken(): string | null { + return localStorage.getItem('token'); + }, + + /** 设置token */ + setToken(token: string): void { + localStorage.setItem('token', token); + }, + + /** 移除token */ + removeToken(): void { + localStorage.removeItem('token'); + }, + + /** 检查是否有token */ + hasToken(): boolean { + return !!this.getToken(); + } +}; + +/** + * 创建axios实例 + */ const request = axios.create({ - baseURL: "/api", + baseURL: import.meta.env.VITE_API_BASE_URL || "/api", timeout: 30000, headers: { 'Content-Type': 'application/json;charset=UTF-8', } -}) +}); let loadingInstance: ReturnType | null = null; -request.interceptors.request.use(config => { - if (config.showLoading) { - loadingInstance = ElLoading.service({ - lock: true, - text: "加载中...", - background: "rgba(0, 0, 0, 0.7)", - }); +/** + * 请求拦截器 + */ +request.interceptors.request.use( + (config: CustomAxiosRequestConfig) => { + // 显示加载动画 + if (config.showLoading !== false) { + loadingInstance = ElLoading.service({ + lock: true, + text: "加载中...", + background: "rgba(0, 0, 0, 0.7)", + }); + } + + // 添加token + const token = TokenManager.getToken(); + if (token && config.headers) { + config.headers.Authorization = `Bearer ${token}`; + } + + return config; + }, + (error: AxiosError) => { + if (loadingInstance) { + loadingInstance.close(); + loadingInstance = null; + } + return Promise.reject(error); } - return config; -}); +); -request.interceptors.response.use(response => { - if (loadingInstance) { - loadingInstance.close(); - loadingInstance = null; +/** + * 响应拦截器 + */ +request.interceptors.response.use( + (response: AxiosResponse>) => { + // 关闭加载动画 + if (loadingInstance) { + loadingInstance.close(); + loadingInstance = null; + } + + const result = response.data; + + // 检查是否为ResultDomain格式 + if (result && typeof result === 'object' && 'code' in result) { + // 检查登录状态 + if (result.login === false) { + ElMessage.error(result.message || '请先登录'); + TokenManager.removeToken(); + // 跳转到登录页 + window.location.href = '/login'; + return Promise.reject(new Error('未登录')); + } + + // 检查权限 + if (result.auth === false) { + ElMessage.error(result.message || '没有权限访问'); + return Promise.reject(new Error('无权限')); + } + + // 检查业务逻辑是否成功 + if (!result.success) { + const config = response.config as CustomAxiosRequestConfig; + if (config.showError !== false) { + ElMessage.error(result.message || '操作失败'); + } + return Promise.reject(new Error(result.message || '操作失败')); + } + + // 返回成功的数据 + return response; + } + + // 非ResultDomain格式,直接返回 + return response; + }, + (error: AxiosError>) => { + // 关闭加载动画 + if (loadingInstance) { + loadingInstance.close(); + loadingInstance = null; + } + + const config = error.config as CustomAxiosRequestConfig; + + // 处理HTTP错误 + if (error.response) { + const { status, data } = error.response; + + switch (status) { + case 401: + ElMessage.error('认证失败,请重新登录'); + TokenManager.removeToken(); + window.location.href = '/login'; + break; + case 403: + ElMessage.error('没有权限访问该资源'); + break; + case 404: + ElMessage.error('请求的资源不存在'); + break; + case 500: + ElMessage.error(data?.message || '服务器内部错误'); + break; + default: + if (config?.showError !== false) { + ElMessage.error(data?.message || '请求失败'); + } + } + } else if (error.request) { + // 请求已发送但没有收到响应 + ElMessage.error('网络错误,请检查网络连接'); + } else { + // 其他错误 + if (config?.showError !== false) { + ElMessage.error(error.message || '请求失败'); + } + } + + return Promise.reject(error); } - return response; -}); +); +/** + * API封装 + */ export const api = { - get: function(url: string, config = {} as AxiosRequestConfig) { return request.get(url, config) }, - post: function(url: string, data = {}, config = {} as AxiosRequestConfig) { return request.post(url, data, config) }, - put: function(url: string, data = {}, config = {} as AxiosRequestConfig) { return request.put(url, data, config) }, - delete: function(url: string, config = {} as AxiosRequestConfig) { return request.delete(url, config) }, - upload: function(url: string, formData: FormData, config = {} as AxiosRequestConfig) { - return request.post(url, formData, { + /** + * GET请求 + */ + get(url: string, config?: CustomAxiosRequestConfig): Promise>> { + return request.get>(url, config); + }, + + /** + * POST请求 + */ + post(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise>> { + return request.post>(url, data, config); + }, + + /** + * PUT请求 + */ + put(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise>> { + return request.put>(url, data, config); + }, + + /** + * DELETE请求 + */ + delete(url: string, config?: CustomAxiosRequestConfig): Promise>> { + return request.delete>(url, config); + }, + + /** + * PATCH请求 + */ + patch(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise>> { + return request.patch>(url, data, config); + }, + + /** + * 文件上传 + */ + upload(url: string, formData: FormData, config?: CustomAxiosRequestConfig): Promise>> { + return request.post>(url, formData, { ...config, headers: { 'Content-Type': 'multipart/form-data', - ...(config.headers as Record) + ...(config?.headers as Record) } - }) + }); + }, + + /** + * 文件下载 + */ + download(url: string, filename?: string, config?: CustomAxiosRequestConfig): Promise { + return request.get(url, { + ...config, + responseType: 'blob' + }).then((response) => { + const blob = new Blob([response.data]); + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.download = filename || 'download'; + link.click(); + window.URL.revokeObjectURL(link.href); + }); } -} - +}; export default request; \ No newline at end of file diff --git a/schoolNewsWeb/src/apis/menu.ts b/schoolNewsWeb/src/apis/menu.ts new file mode 100644 index 0000000..778c13f --- /dev/null +++ b/schoolNewsWeb/src/apis/menu.ts @@ -0,0 +1,92 @@ +/** + * @description 菜单相关API + * @author yslg + * @since 2025-10-06 + */ + +import { api } from './index'; +import type { SysMenu, MenuTreeNode } from '@/types'; + +/** + * 菜单API服务 + */ +export const menuApi = { + /** + * 获取当前用户的菜单树 + * @returns Promise + */ + async getCurrentUserMenuTree(): Promise { + const response = await api.get('/menu/user-tree'); + return response.data.dataList! as MenuTreeNode[]; + }, + + /** + * 获取所有菜单列表 + * @returns Promise + */ + async getMenuList(): Promise { + const response = await api.get('/menu/list'); + return response.data.dataList!; + }, + + /** + * 获取菜单树 + * @returns Promise + */ + async getMenuTree(): Promise { + const response = await api.get('/menu/tree'); + return response.data.dataList! as MenuTreeNode[]; + }, + + /** + * 根据ID获取菜单 + * @param menuId 菜单ID + * @returns Promise + */ + async getMenuById(menuId: string): Promise { + const response = await api.get(`/menu/${menuId}`); + return response.data.data!; + }, + + /** + * 创建菜单 + * @param menu 菜单信息 + * @returns Promise 返回菜单ID + */ + async createMenu(menu: SysMenu): Promise { + const response = await api.post('/menu', menu); + return response.data.data!; + }, + + /** + * 更新菜单 + * @param menuId 菜单ID + * @param menu 菜单信息 + * @returns Promise + */ + async updateMenu(menuId: string, menu: SysMenu): Promise { + const response = await api.put(`/menu/${menuId}`, menu); + return response.data.data!; + }, + + /** + * 删除菜单 + * @param menuId 菜单ID + * @returns Promise + */ + async deleteMenu(menuId: string): Promise { + const response = await api.delete(`/menu/${menuId}`); + return response.data.data!; + }, + + /** + * 获取子菜单列表 + * @param parentId 父菜单ID + * @returns Promise + */ + async getChildMenus(parentId: string): Promise { + const response = await api.get(`/menu/children/${parentId}`); + return response.data.dataList!; + } +}; + diff --git a/schoolNewsWeb/src/apis/user.ts b/schoolNewsWeb/src/apis/user.ts new file mode 100644 index 0000000..98dbfa1 --- /dev/null +++ b/schoolNewsWeb/src/apis/user.ts @@ -0,0 +1,153 @@ +/** + * @description 用户相关API + * @author yslg + * @since 2025-10-06 + */ + +import { api } from './index'; +import type { SysUser, SysUserInfo, UserVO, PageDomain, PageParam } from '@/types'; + +/** + * 用户API服务 + */ +export const userApi = { + /** + * 获取当前用户信息 + * @returns Promise + */ + async getCurrentUser(): Promise { + const response = await api.get('/user/current'); + return response.data.data!; + }, + + /** + * 更新当前用户信息 + * @param user 用户信息 + * @returns Promise + */ + async updateCurrentUser(user: SysUser): Promise { + const response = await api.put('/user/current', user); + return response.data.data!; + }, + + /** + * 更新用户详细信息 + * @param userInfo 用户详细信息 + * @returns Promise + */ + async updateUserInfo(userInfo: SysUserInfo): Promise { + const response = await api.put('/user/info', userInfo); + return response.data.data!; + }, + + /** + * 修改密码 + * @param oldPassword 旧密码 + * @param newPassword 新密码 + * @returns Promise + */ + async changePassword(oldPassword: string, newPassword: string): Promise { + const response = await api.post('/user/change-password', { + oldPassword, + newPassword + }); + return response.data.data!; + }, + + /** + * 获取用户列表(分页) + * @param pageParam 分页参数 + * @returns Promise> + */ + async getUserList(pageParam: PageParam): Promise> { + const response = await api.get('/user/list', { + params: pageParam + }); + return response.data.pageDomain!; + }, + + /** + * 根据ID获取用户 + * @param userId 用户ID + * @returns Promise + */ + async getUserById(userId: string): Promise { + const response = await api.get(`/user/${userId}`); + return response.data.data!; + }, + + /** + * 创建用户 + * @param user 用户信息 + * @returns Promise 返回用户ID + */ + async createUser(user: SysUser): Promise { + const response = await api.post('/user', user); + return response.data.data!; + }, + + /** + * 更新用户 + * @param userId 用户ID + * @param user 用户信息 + * @returns Promise + */ + async updateUser(userId: string, user: SysUser): Promise { + const response = await api.put(`/user/${userId}`, user); + return response.data.data!; + }, + + /** + * 删除用户 + * @param userId 用户ID + * @returns Promise + */ + async deleteUser(userId: string): Promise { + const response = await api.delete(`/user/${userId}`); + return response.data.data!; + }, + + /** + * 批量删除用户 + * @param userIds 用户ID列表 + * @returns Promise + */ + async batchDeleteUsers(userIds: string[]): Promise { + const response = await api.post('/user/batch-delete', { userIds }); + return response.data.data!; + }, + + /** + * 启用/禁用用户 + * @param userId 用户ID + * @param status 状态 0-启用 1-禁用 + * @returns Promise + */ + async changeUserStatus(userId: string, status: number): Promise { + const response = await api.patch(`/user/${userId}/status`, { status }); + return response.data.data!; + }, + + /** + * 重置用户密码 + * @param userId 用户ID + * @returns Promise 返回新密码 + */ + async resetPassword(userId: string): Promise { + const response = await api.post(`/user/${userId}/reset-password`); + return response.data.data!; + }, + + /** + * 上传用户头像 + * @param file 文件 + * @returns Promise 返回头像URL + */ + async uploadAvatar(file: File): Promise { + const formData = new FormData(); + formData.append('file', file); + const response = await api.upload('/user/avatar', formData); + return response.data.data!; + } +}; + diff --git a/schoolNewsWeb/src/domain/index.ts b/schoolNewsWeb/src/domain/index.ts deleted file mode 100644 index e7fc46e..0000000 --- a/schoolNewsWeb/src/domain/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -// 导出通用类型 -export * from "./types/common"; diff --git a/schoolNewsWeb/src/domain/types/common.ts b/schoolNewsWeb/src/domain/types/common.ts deleted file mode 100644 index 44b5a4c..0000000 --- a/schoolNewsWeb/src/domain/types/common.ts +++ /dev/null @@ -1,19 +0,0 @@ -// 通用响应类型 -interface ApiResponse { - code: number; - message: string; - success: boolean; - failure: boolean; - auth: boolean; - data?: T; - dataList?: T[]; -} - -// 扩展 axios 配置类型 -declare module "axios" { - interface AxiosRequestConfig { - showLoading?: boolean; - } -} - -export { ApiResponse }; diff --git a/schoolNewsWeb/src/types/auth/index.ts b/schoolNewsWeb/src/types/auth/index.ts new file mode 100644 index 0000000..d7e0498 --- /dev/null +++ b/schoolNewsWeb/src/types/auth/index.ts @@ -0,0 +1,86 @@ +/** + * @description 认证相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { SysUser, SysUserInfo } from '../user'; +import { DeptRoleVO } from '../dept'; +import { SysPermission } from '../permission'; +import { SysMenu } from '../menu'; +import { LoginType } from '../enums'; + +/** + * 登录参数 + */ +export interface LoginParam { + /** 登录类型 */ + loginType?: LoginType; + /** 用户名 */ + username?: string; + /** 邮箱 */ + email?: string; + /** 手机号 */ + phone?: string; + /** 微信ID */ + wechatID?: string; + /** 密码 */ + password?: string; + /** 验证码 */ + captcha?: string; + /** 验证码ID */ + captchaId?: string; + /** 记住我 */ + rememberMe?: boolean; +} + +/** + * 登录域对象 - 包含登录后的所有用户信息 + */ +export interface LoginDomain { + /** 用户基本信息 */ + user?: SysUser; + /** 用户详细信息 */ + userInfo?: SysUserInfo; + /** 用户角色列表 */ + roles?: DeptRoleVO[]; + /** 用户权限列表 */ + permissions?: SysPermission[]; + /** 用户菜单列表 */ + menus?: SysMenu[]; + /** JWT令牌 */ + token?: string; + /** 令牌过期时间 */ + tokenExpireTime?: string; + /** 登录时间 */ + loginTime?: string; + /** 登录IP地址 */ + ipAddress?: string; + /** 登录类型 */ + loginType?: LoginType; +} + +/** + * 登录日志 + */ +export interface SysLoginLog { + /** ID */ + id?: string; + /** 用户ID */ + userID?: string; + /** 用户名 */ + username?: string; + /** 登录状态 0-失败 1-成功 */ + status?: number; + /** 登录消息 */ + message?: string; + /** 登录时间 */ + loginTime?: string; + /** 登录IP */ + ipAddress?: string; + /** 浏览器 */ + browser?: string; + /** 操作系统 */ + os?: string; +} + diff --git a/schoolNewsWeb/src/types/base/index.ts b/schoolNewsWeb/src/types/base/index.ts new file mode 100644 index 0000000..9024e74 --- /dev/null +++ b/schoolNewsWeb/src/types/base/index.ts @@ -0,0 +1,76 @@ +/** + * @description 基础数据传输对象类型定义 + * @author yslg + * @since 2025-10-06 + */ + +/** + * 基础DTO - 包含所有实体的公共字段 + */ +export interface BaseDTO { + /** 主键ID */ + id?: string; + /** 创建时间 */ + createTime?: string; + /** 更新时间 */ + updateTime?: string; + /** 删除时间 */ + deleteTime?: string; + /** 是否删除 */ + deleted?: boolean; +} + +/** + * 分页参数 + */ +export interface PageParam { + /** 当前页码 */ + page?: number; + /** 每页条数 */ + size?: number; + /** 排序字段 */ + orderBy?: string; + /** 排序方向 asc/desc */ + orderDirection?: 'asc' | 'desc'; +} + +/** + * 分页结果 + */ +export interface PageDomain { + /** 当前页码 */ + page: number; + /** 每页条数 */ + size: number; + /** 总记录数 */ + total: number; + /** 总页数 */ + pages: number; + /** 数据列表 */ + records: T[]; +} + +/** + * 统一返回结果 + */ +export interface ResultDomain { + /** 状态码 */ + code: number; + /** 返回消息 */ + message: string; + /** 操作是否成功 */ + success: boolean; + /** 是否登录 */ + login: boolean; + /** 是否有权限 */ + auth: boolean; + /** 返回数据 */ + data?: T; + /** 返回数据列表 */ + dataList?: T[]; + /** 分页参数 */ + pageParam?: PageParam; + /** 分页信息 */ + pageDomain?: PageDomain; +} + diff --git a/schoolNewsWeb/src/types/constants/index.ts b/schoolNewsWeb/src/types/constants/index.ts new file mode 100644 index 0000000..3bc8435 --- /dev/null +++ b/schoolNewsWeb/src/types/constants/index.ts @@ -0,0 +1,30 @@ +/** + * @description 常量定义 + * @author yslg + * @since 2025-10-06 + */ + +/** + * 存储键名常量 + */ +export const StorageKeys = { + /** Token */ + TOKEN: 'token', + /** 用户信息 */ + USER_INFO: 'userInfo', + /** 登录信息 */ + LOGIN_INFO: 'loginInfo' +} as const; + +/** + * 分页默认值常量 + */ +export const PageDefaults = { + /** 默认页码 */ + PAGE: 1, + /** 默认每页条数 */ + SIZE: 10, + /** 每页条数选项 */ + SIZE_OPTIONS: [10, 20, 50, 100] +} as const; + diff --git a/schoolNewsWeb/src/types/dept/index.ts b/schoolNewsWeb/src/types/dept/index.ts new file mode 100644 index 0000000..fafd83e --- /dev/null +++ b/schoolNewsWeb/src/types/dept/index.ts @@ -0,0 +1,47 @@ +/** + * @description 部门相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { BaseDTO } from '../base'; +import { SysRole } from '../role'; + +/** + * 系统部门 + */ +export interface SysDept extends BaseDTO { + /** 部门ID */ + deptID?: string; + /** 父部门ID */ + parentID?: string; + /** 部门名称 */ + name?: string; + /** 部门描述 */ + description?: string; + /** 创建人 */ + creator?: string; + /** 更新人 */ + updater?: string; +} + +/** + * 部门角色VO + */ +export interface DeptRoleVO { + /** 部门信息 */ + dept?: SysDept; + /** 角色信息 */ + role?: SysRole; +} + +/** + * 部门角色关联 + */ +export interface SysDeptRole extends BaseDTO { + /** 部门ID */ + deptID?: string; + /** 角色ID */ + roleID?: string; +} + diff --git a/schoolNewsWeb/src/types/enums/index.ts b/schoolNewsWeb/src/types/enums/index.ts new file mode 100644 index 0000000..6955e9b --- /dev/null +++ b/schoolNewsWeb/src/types/enums/index.ts @@ -0,0 +1,76 @@ +/** + * @description 枚举类型统一导出 + * @author yslg + * @since 2025-10-06 + */ + +/** + * HTTP 状态码枚举 + */ +export enum HttpStatus { + /** 成功 */ + OK = 200, + /** 错误请求 */ + BAD_REQUEST = 400, + /** 未授权 */ + UNAUTHORIZED = 401, + /** 禁止访问 */ + FORBIDDEN = 403, + /** 未找到 */ + NOT_FOUND = 404, + /** 服务器错误 */ + INTERNAL_SERVER_ERROR = 500 +} + +/** + * 用户状态枚举 + */ +export enum UserStatus { + /** 正常 */ + NORMAL = 0, + /** 禁用 */ + DISABLED = 1, + /** 锁定 */ + LOCKED = 2 +} + +/** + * 性别枚举 + */ +export enum Gender { + /** 未知 */ + UNKNOWN = 0, + /** 男 */ + MALE = 1, + /** 女 */ + FEMALE = 2 +} + +/** + * 菜单类型枚举 + */ +export enum MenuType { + /** 目录 */ + DIRECTORY = 0, + /** 菜单 */ + MENU = 1, + /** 按钮 */ + BUTTON = 2 +} + +/** + * 登录类型枚举 + */ +export enum LoginType { + /** 用户名登录 */ + USERNAME = 'username', + /** 邮箱登录 */ + EMAIL = 'email', + /** 手机号登录 */ + PHONE = 'phone', + /** 微信登录 */ + WECHAT = 'wechat', + /** 密码登录 */ + PASSWORD = 'password' +} + diff --git a/schoolNewsWeb/src/types/index.ts b/schoolNewsWeb/src/types/index.ts new file mode 100644 index 0000000..d281575 --- /dev/null +++ b/schoolNewsWeb/src/types/index.ts @@ -0,0 +1,33 @@ +/** + * @description 类型定义统一导出入口 + * @author yslg + * @since 2025-10-06 + */ + +// 基础类型 +export * from './base'; + +// 用户相关 +export * from './user'; + +// 角色相关 +export * from './role'; + +// 部门相关 +export * from './dept'; + +// 菜单相关 +export * from './menu'; + +// 权限相关 +export * from './permission'; + +// 认证相关 +export * from './auth'; + +// 枚举类型 +export * from './enums'; + +// 常量 +export * from './constants'; + diff --git a/schoolNewsWeb/src/types/menu/index.ts b/schoolNewsWeb/src/types/menu/index.ts new file mode 100644 index 0000000..2ecd026 --- /dev/null +++ b/schoolNewsWeb/src/types/menu/index.ts @@ -0,0 +1,59 @@ +/** + * @description 菜单相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { BaseDTO } from '../base'; +import { MenuType } from '../enums'; + +/** + * 系统菜单 + */ +export interface SysMenu extends BaseDTO { + /** 菜单ID */ + menuID?: string; + /** 父菜单ID */ + parentID?: string; + /** 菜单名称 */ + name?: string; + /** 菜单描述 */ + description?: string; + /** 菜单URL/路径 */ + url?: string; + /** 菜单图标 */ + icon?: string; + /** 菜单顺序 */ + orderNum?: number; + /** 菜单类型 0-目录 1-菜单 2-按钮 */ + type?: MenuType; + /** 创建人 */ + creator?: string; + /** 更新人 */ + updater?: string; + /** 子菜单列表(前端使用) */ + children?: SysMenu[]; +} + +/** + * 菜单权限关联 + */ +export interface SysMenuPermission extends BaseDTO { + /** 菜单ID */ + menuID?: string; + /** 权限ID */ + permissionID?: string; +} + +/** + * 菜单树节点(用于树形展示) + */ +export interface MenuTreeNode extends SysMenu { + /** 子节点 */ + children?: MenuTreeNode[]; + /** 是否展开 */ + expanded?: boolean; + /** 是否选中 */ + checked?: boolean; +} + diff --git a/schoolNewsWeb/src/types/permission/index.ts b/schoolNewsWeb/src/types/permission/index.ts new file mode 100644 index 0000000..870d945 --- /dev/null +++ b/schoolNewsWeb/src/types/permission/index.ts @@ -0,0 +1,26 @@ +/** + * @description 权限相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { BaseDTO } from '../base'; + +/** + * 系统权限 + */ +export interface SysPermission extends BaseDTO { + /** 权限ID */ + permissionID?: string; + /** 权限名称 */ + name?: string; + /** 权限描述 */ + description?: string; + /** 权限编码 */ + code?: string; + /** 创建人 */ + creator?: string; + /** 更新人 */ + updater?: string; +} + diff --git a/schoolNewsWeb/src/types/role/index.ts b/schoolNewsWeb/src/types/role/index.ts new file mode 100644 index 0000000..d4ff38b --- /dev/null +++ b/schoolNewsWeb/src/types/role/index.ts @@ -0,0 +1,34 @@ +/** + * @description 角色相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { BaseDTO } from '../base'; + +/** + * 系统角色 + */ +export interface SysRole extends BaseDTO { + /** 角色ID */ + roleID?: string; + /** 角色名称 */ + name?: string; + /** 角色描述 */ + description?: string; + /** 创建人 */ + creator?: string; + /** 更新人 */ + updater?: string; +} + +/** + * 角色权限关联 + */ +export interface SysRolePermission extends BaseDTO { + /** 角色ID */ + roleID?: string; + /** 权限ID */ + permissionID?: string; +} + diff --git a/schoolNewsWeb/src/types/user/index.ts b/schoolNewsWeb/src/types/user/index.ts new file mode 100644 index 0000000..bd9b1e9 --- /dev/null +++ b/schoolNewsWeb/src/types/user/index.ts @@ -0,0 +1,70 @@ +/** + * @description 用户相关类型定义 + * @author yslg + * @since 2025-10-06 + */ + +import { BaseDTO } from '../base'; + +/** + * 系统用户 + */ +export interface SysUser extends BaseDTO { + /** 用户名 */ + username?: string; + /** 密码(不应在前端显示) */ + password?: string; + /** 邮箱 */ + email?: string; + /** 手机号 */ + phone?: string; + /** 微信ID */ + wechatID?: string; + /** 用户状态 0-正常 1-禁用 */ + status?: number; +} + +/** + * 用户详细信息 + */ +export interface SysUserInfo extends BaseDTO { + /** 用户ID */ + userID?: string; + /** 真实姓名 */ + realName?: string; + /** 昵称 */ + nickname?: string; + /** 头像URL */ + avatar?: string; + /** 性别 0-未知 1-男 2-女 */ + gender?: number; + /** 出生日期 */ + birthday?: string; + /** 个人简介 */ + bio?: string; + /** 地址 */ + address?: string; +} + +/** + * 用户VO - 用于前端展示 + */ +export interface UserVO { + /** 用户基本信息 */ + user?: SysUser; + /** 用户详细信息 */ + userInfo?: SysUserInfo; +} + +/** + * 用户部门角色关联 + */ +export interface SysUserDeptRole extends BaseDTO { + /** 用户ID */ + userID?: string; + /** 部门ID */ + deptID?: string; + /** 角色ID */ + roleID?: string; +} +