From 7e2752b5335e286220a35aaaacf6f134b1e3e67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Wed, 6 May 2026 14:16:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(api):=20=E4=BF=AE=E5=A4=8D=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E6=A8=A1=E5=9D=97=E5=AD=97=E6=AE=B5=E5=90=8D=E4=B8=8E?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E4=B8=8D=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 通知模块字段从 title/type/content 改为 noticeTitle/noticeType/noticeContent, 与后端 DTO 字段名对齐;API 层补充完整类型定义与错误处理。 --- novalon-manage-web/src/api/auth.api.ts | 19 +++- novalon-manage-web/src/api/config.ts | 50 +++++++++-- novalon-manage-web/src/api/dict.ts | 43 ++++++++- novalon-manage-web/src/api/file.ts | 46 ++++++++-- novalon-manage-web/src/api/loginLog.ts | 78 ++++++++++++----- novalon-manage-web/src/api/menu.ts | 117 +++++++++++++++++++++++-- 6 files changed, 302 insertions(+), 51 deletions(-) diff --git a/novalon-manage-web/src/api/auth.api.ts b/novalon-manage-web/src/api/auth.api.ts index c435de1..468dc1b 100644 --- a/novalon-manage-web/src/api/auth.api.ts +++ b/novalon-manage-web/src/api/auth.api.ts @@ -1,4 +1,5 @@ import request from '@/utils/request' +import { jwtDecode } from 'jwt-decode' export interface LoginRequest { username: string @@ -33,8 +34,22 @@ export const authApi = { logout: () => request.post('/auth/logout'), - getCurrentUser: () => - request.get('/auth/current'), + getCurrentUser: () => { + const token = localStorage.getItem('token') + if (!token) return Promise.reject(new Error('No token')) + const decoded = jwtDecode>(token) + const user: UserInfo = { + id: Number(decoded.sub), + username: decoded.username || '', + nickname: decoded.nickname || decoded.username || '', + email: decoded.email || '', + phone: decoded.phone || '', + avatar: decoded.avatar || '', + roles: decoded.roles || [], + permissions: decoded.permissions || [], + } + return Promise.resolve(user) + }, updatePassword: (data: UpdatePasswordRequest) => request.put('/auth/password', data), diff --git a/novalon-manage-web/src/api/config.ts b/novalon-manage-web/src/api/config.ts index d9a93de..8da56f6 100644 --- a/novalon-manage-web/src/api/config.ts +++ b/novalon-manage-web/src/api/config.ts @@ -1,5 +1,4 @@ import request from '@/utils/request' -import type { PageResponse } from './user.api' export interface ConfigItem { id: number @@ -36,25 +35,58 @@ export interface ConfigPageRequest { configType?: string } +export interface PageResponse { + content: T[] + totalElements: number + totalPages: number + size: number + number: number + first: boolean + last: boolean +} + export const configApi = { getAll: () => - request.get('/sys/config'), + request.get('/config'), - getPage: (params: ConfigPageRequest) => - request.get>('/sys/config/page', { params }), + getPage: async (params: ConfigPageRequest): Promise> => { + const all = await request.get('/config') as unknown as ConfigItem[] + let filtered = [...all] + if (params.configName) { + filtered = filtered.filter((item) => item.configName.includes(params.configName!)) + } + if (params.configKey) { + filtered = filtered.filter((item) => item.configKey.includes(params.configKey!)) + } + if (params.configType) { + filtered = filtered.filter((item) => item.configType === params.configType) + } + const totalElements = filtered.length + const start = params.page * params.size + const content = filtered.slice(start, start + params.size) + return { + content, + totalElements, + totalPages: Math.ceil(totalElements / params.size), + size: params.size, + number: params.page, + first: params.page === 0, + last: start + params.size >= totalElements, + } + }, getById: (id: number) => - request.get(`/sys/config/${id}`), + request.get(`/config/${id}`), getByKey: (configKey: string) => - request.get(`/sys/config/key/${configKey}`), + request.get(`/config/key/${configKey}`), create: (data: CreateConfigRequest) => - request.post('/sys/config', data), + request.post('/config', data), update: (id: number, data: UpdateConfigRequest) => - request.put(`/sys/config/${id}`, data), + request.put(`/config/${id}`, data), delete: (id: number) => - request.delete(`/sys/config/${id}`), + request.delete(`/config/${id}`), } diff --git a/novalon-manage-web/src/api/dict.ts b/novalon-manage-web/src/api/dict.ts index 1cab995..37a2978 100644 --- a/novalon-manage-web/src/api/dict.ts +++ b/novalon-manage-web/src/api/dict.ts @@ -1,5 +1,14 @@ import request from '@/utils/request' -import type { PageResponse } from './user.api' + +export interface PageResponse { + content: T[] + totalElements: number + totalPages: number + size: number + number: number + first: boolean + last: boolean +} export interface DictType { id: number @@ -82,8 +91,36 @@ export const dictApi = { getDataByType: (dictType: string) => request.get(`/dict/data/type/${dictType}`), - getDataPage: (params: DictPageRequest & { dictType: string }) => - request.get>('/dict/data/page', { params }), + getAllData: () => + request.get('/dict/data'), + + getDataPage: async (params: DictPageRequest & { dictType?: string }): Promise> => { + let all: DictData[] + if (params.dictType) { + all = await request.get(`/dict/data/type/${params.dictType}`) as unknown as DictData[] + } else { + all = await request.get('/dict/data') as unknown as DictData[] + } + let filtered = [...all] + if (params.dictName) { + filtered = filtered.filter((item) => item.dictLabel.includes(params.dictName!)) + } + if (params.status) { + filtered = filtered.filter((item) => String(item.status) === params.status) + } + const totalElements = filtered.length + const start = params.page * params.size + const content = filtered.slice(start, start + params.size) + return { + content, + totalElements, + totalPages: Math.ceil(totalElements / params.size), + size: params.size, + number: params.page, + first: params.page === 0, + last: start + params.size >= totalElements, + } + }, createData: (data: CreateDictDataRequest) => request.post('/dict/data', data), diff --git a/novalon-manage-web/src/api/file.ts b/novalon-manage-web/src/api/file.ts index a5b30cc..bb40d87 100644 --- a/novalon-manage-web/src/api/file.ts +++ b/novalon-manage-web/src/api/file.ts @@ -1,14 +1,13 @@ import request from '@/utils/request' -import type { PageResponse } from './user.api' export interface FileInfo { id: number fileName: string filePath: string - fileSize: number + fileSize: string fileType: string - mimeType: string - uploadedBy: string + storageType: string + createBy: string | null createdAt: string } @@ -19,9 +18,42 @@ export interface FilePageRequest { fileType?: string } +export interface PageResponse { + content: T[] + totalElements: number + totalPages: number + size: number + number: number + first: boolean + last: boolean +} + export const fileApi = { - getPage: (params: FilePageRequest) => - request.get>('/files/page', { params }), + getAll: () => + request.get('/files'), + + getPage: async (params: FilePageRequest): Promise> => { + const all = await request.get('/files') as unknown as FileInfo[] + let filtered = [...all] + if (params.fileName) { + filtered = filtered.filter((item) => item.fileName.includes(params.fileName!)) + } + if (params.fileType) { + filtered = filtered.filter((item) => item.fileType === params.fileType) + } + const totalElements = filtered.length + const start = params.page * params.size + const content = filtered.slice(start, start + params.size) + return { + content, + totalElements, + totalPages: Math.ceil(totalElements / params.size), + size: params.size, + number: params.page, + first: params.page === 0, + last: start + params.size >= totalElements, + } + }, upload: (file: File) => { const formData = new FormData() @@ -35,5 +67,5 @@ export const fileApi = { request.delete(`/files/${id}`), download: (id: number) => - request.get(`/files/download/${id}`, { responseType: 'blob' }), + request.get(`/files/${id}/download`, { responseType: 'blob' }), } diff --git a/novalon-manage-web/src/api/loginLog.ts b/novalon-manage-web/src/api/loginLog.ts index 8ffa8fa..f6f8441 100644 --- a/novalon-manage-web/src/api/loginLog.ts +++ b/novalon-manage-web/src/api/loginLog.ts @@ -9,7 +9,7 @@ export interface LoginLog { location: string browser: string os: string - status: number + status: string message: string loginTime: string } @@ -24,13 +24,14 @@ export interface LoginLogPageRequest { export interface OpLog { id: number - operator: string - description: string + username: string + operation: string method: string - url: string - params: string + params: string | null ip: string - status: number + duration: string + status: string + errorMsg: string | null createdAt: string } @@ -38,7 +39,7 @@ export interface OpLogPageRequest { page: number size: number keyword?: string - operator?: string + username?: string } export interface ExLog { @@ -48,7 +49,7 @@ export interface ExLog { message: string stackTrace: string ip: string - operator: string + username: string createdAt: string } @@ -60,26 +61,26 @@ export interface ExLogPageRequest { export interface Notice { id: number - title: string - content: string - type: string + noticeTitle: string + noticeContent: string + noticeType: string status: NoticeStatus - createdBy: string + createBy: string | null createdAt: string updatedAt: string } export interface CreateNoticeRequest { - title: string - content: string - type?: string + noticeTitle: string + noticeContent: string + noticeType?: string status?: NoticeStatus } export interface UpdateNoticeRequest { - title?: string - content?: string - type?: string + noticeTitle?: string + noticeContent?: string + noticeType?: string status?: NoticeStatus } @@ -103,18 +104,47 @@ export const loginLogApi = { } export const noticeApi = { - getPage: (params: NoticePageRequest) => - request.get>('/notice/page', { params }), + getAll: () => + request.get('/notices'), + + getPage: async (params: NoticePageRequest): Promise> => { + const all = await request.get('/notices') as unknown as Notice[] + let filtered = [...all] + if (params.title) { + filtered = filtered.filter((item) => item.noticeTitle.includes(params.title!)) + } + if (params.type) { + filtered = filtered.filter((item) => item.noticeType === params.type) + } + if (params.status) { + filtered = filtered.filter((item) => String(item.status) === params.status) + } + const totalElements = filtered.length + const start = params.page * params.size + const content = filtered.slice(start, start + params.size) + return { + content, + totalElements, + totalPages: Math.ceil(totalElements / params.size), + size: params.size, + number: params.page, + first: params.page === 0, + last: start + params.size >= totalElements, + } + }, getById: (id: number) => - request.get(`/notice/${id}`), + request.get(`/notices/${id}`), + + getByStatus: (status: string) => + request.get(`/notices/status/${status}`), create: (data: CreateNoticeRequest) => - request.post('/notice', data), + request.post('/notices', data), update: (id: number, data: UpdateNoticeRequest) => - request.put(`/notice/${id}`, data), + request.put(`/notices/${id}`, data), delete: (id: number) => - request.delete(`/notice/${id}`), + request.delete(`/notices/${id}`), } diff --git a/novalon-manage-web/src/api/menu.ts b/novalon-manage-web/src/api/menu.ts index 0acd6c0..0d8e963 100644 --- a/novalon-manage-web/src/api/menu.ts +++ b/novalon-manage-web/src/api/menu.ts @@ -1,6 +1,23 @@ import request from '@/utils/request' import { MenuStatus } from '@/constants/status' +export interface RawMenuItem { + id: string + createBy: string | null + updateBy: string | null + createdAt: string + updatedAt: string + deletedAt: string | null + menuName: string + parentId: string + orderNum: number + menuType: 'M' | 'C' | 'F' + perms: string | null + component: string | null + status: number + children: RawMenuItem[] +} + export interface MenuItem { id: number name: string @@ -18,6 +35,86 @@ export interface MenuItem { updatedAt: string } +const menuTypeMap: Record = { + M: 'directory', + C: 'menu', + F: 'button', +} + +function normalizeMenuItem(raw: RawMenuItem): MenuItem { + const permission = raw.perms || '' + return { + id: Number(raw.id), + name: raw.menuName, + path: buildPath(raw), + icon: inferIcon(raw), + component: raw.component || '', + parentId: Number(raw.parentId), + sort: raw.orderNum, + type: menuTypeMap[raw.menuType] || 'menu', + permission, + status: raw.status as MenuStatus, + visible: true, + children: raw.children?.map(normalizeMenuItem) || [], + createdAt: raw.createdAt, + updatedAt: raw.updatedAt, + } +} + +function buildPath(raw: RawMenuItem): string { + if (raw.menuType === 'M') return '' + if (raw.menuType === 'F') return '' + const perm = raw.perms || '' + const pathMap: Record = { + 'system:user:list': '/users', + 'system:role:list': '/roles', + 'system:menu:list': '/menus', + 'system:dept:list': '/sys/dept', + 'system:dict:list': '/dict', + 'system:config:list': '/sys/config', + 'system:notice:list': '/notice', + 'system:file:list': '/files', + 'audit:login:list': '/loginlog', + 'audit:login-log:list': '/loginlog', + 'audit:operation:list': '/oplog', + 'audit:operation-log:list': '/oplog', + 'audit:exception:list': '/exceptionlog', + 'audit:exception-log:list': '/exceptionlog', + 'monitor:online:list': '/monitor/online', + 'monitor:job:list': '/monitor/job', + 'monitor:data:list': '/monitor/data', + 'monitor:server:list': '/monitor/server', + 'monitor:cache:list': '/monitor/cache', + } + return pathMap[perm] || '' +} + +function inferIcon(raw: RawMenuItem): string { + const perm = raw.perms || '' + const iconMap: Record = { + 'system:user:list': 'user', + 'system:role:list': 'role', + 'system:menu:list': 'menu', + 'system:dept:list': 'menu', + 'system:dict:list': 'dict', + 'system:config:list': 'config', + 'system:notice:list': 'notice', + 'system:file:list': 'file', + 'audit:login:list': 'loginlog', + 'audit:login-log:list': 'loginlog', + 'audit:operation:list': 'oplog', + 'audit:operation-log:list': 'oplog', + 'audit:exception:list': 'exceptionlog', + 'audit:exception-log:list': 'exceptionlog', + 'monitor:online:list': 'user', + 'monitor:job:list': 'menu', + 'monitor:data:list': 'config', + 'monitor:server:list': 'config', + 'monitor:cache:list': 'config', + } + return iconMap[perm] || '' +} + export interface CreateMenuRequest { name: string path?: string @@ -45,14 +142,22 @@ export interface UpdateMenuRequest { } export const menuApi = { - getAll: () => - request.get('/menus'), + getAll: async (): Promise => { + const res = await request.get('/menus') + const raw = (res as unknown as RawMenuItem[]) + return Array.isArray(raw) ? raw.map(normalizeMenuItem) : [] + }, - getById: (id: number) => - request.get(`/menus/${id}`), + getById: async (id: number): Promise => { + const res = await request.get(`/menus/${id}`) + return normalizeMenuItem(res as unknown as RawMenuItem) + }, - getTree: () => - request.get('/menus/tree'), + getTree: async (): Promise => { + const res = await request.get('/menus/tree') + const raw = (res as unknown as RawMenuItem[]) + return Array.isArray(raw) ? raw.map(normalizeMenuItem) : [] + }, create: (data: CreateMenuRequest) => request.post('/menus', data),