build: 调整 JaCoCo 覆盖率检查配置 #6

Merged
zhangxiang merged 28 commits from feature/react19-migration into dev 2026-05-06 19:43:00 +08:00
6 changed files with 302 additions and 51 deletions
Showing only changes of commit 7e2752b533 - Show all commits
+17 -2
View File
@@ -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<void>('/auth/logout'),
getCurrentUser: () =>
request.get<UserInfo>('/auth/current'),
getCurrentUser: () => {
const token = localStorage.getItem('token')
if (!token) return Promise.reject(new Error('No token'))
const decoded = jwtDecode<Record<string, any>>(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<void>('/auth/password', data),
+41 -9
View File
@@ -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<T> {
content: T[]
totalElements: number
totalPages: number
size: number
number: number
first: boolean
last: boolean
}
export const configApi = {
getAll: () =>
request.get<ConfigItem[]>('/sys/config'),
request.get<ConfigItem[]>('/config'),
getPage: (params: ConfigPageRequest) =>
request.get<PageResponse<ConfigItem>>('/sys/config/page', { params }),
getPage: async (params: ConfigPageRequest): Promise<PageResponse<ConfigItem>> => {
const all = await request.get<ConfigItem[]>('/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<ConfigItem>(`/sys/config/${id}`),
request.get<ConfigItem>(`/config/${id}`),
getByKey: (configKey: string) =>
request.get<ConfigItem>(`/sys/config/key/${configKey}`),
request.get<ConfigItem>(`/config/key/${configKey}`),
create: (data: CreateConfigRequest) =>
request.post<ConfigItem>('/sys/config', data),
request.post<ConfigItem>('/config', data),
update: (id: number, data: UpdateConfigRequest) =>
request.put<ConfigItem>(`/sys/config/${id}`, data),
request.put<ConfigItem>(`/config/${id}`, data),
delete: (id: number) =>
request.delete<void>(`/sys/config/${id}`),
request.delete<void>(`/config/${id}`),
}
+40 -3
View File
@@ -1,5 +1,14 @@
import request from '@/utils/request'
import type { PageResponse } from './user.api'
export interface PageResponse<T> {
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<DictData[]>(`/dict/data/type/${dictType}`),
getDataPage: (params: DictPageRequest & { dictType: string }) =>
request.get<PageResponse<DictData>>('/dict/data/page', { params }),
getAllData: () =>
request.get<DictData[]>('/dict/data'),
getDataPage: async (params: DictPageRequest & { dictType?: string }): Promise<PageResponse<DictData>> => {
let all: DictData[]
if (params.dictType) {
all = await request.get<DictData[]>(`/dict/data/type/${params.dictType}`) as unknown as DictData[]
} else {
all = await request.get<DictData[]>('/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<DictData>('/dict/data', data),
+39 -7
View File
@@ -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<T> {
content: T[]
totalElements: number
totalPages: number
size: number
number: number
first: boolean
last: boolean
}
export const fileApi = {
getPage: (params: FilePageRequest) =>
request.get<PageResponse<FileInfo>>('/files/page', { params }),
getAll: () =>
request.get<FileInfo[]>('/files'),
getPage: async (params: FilePageRequest): Promise<PageResponse<FileInfo>> => {
const all = await request.get<FileInfo[]>('/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<void>(`/files/${id}`),
download: (id: number) =>
request.get<Blob>(`/files/download/${id}`, { responseType: 'blob' }),
request.get<Blob>(`/files/${id}/download`, { responseType: 'blob' }),
}
+54 -24
View File
@@ -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<PageResponse<Notice>>('/notice/page', { params }),
getAll: () =>
request.get<Notice[]>('/notices'),
getPage: async (params: NoticePageRequest): Promise<PageResponse<Notice>> => {
const all = await request.get<Notice[]>('/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>(`/notice/${id}`),
request.get<Notice>(`/notices/${id}`),
getByStatus: (status: string) =>
request.get<Notice[]>(`/notices/status/${status}`),
create: (data: CreateNoticeRequest) =>
request.post<Notice>('/notice', data),
request.post<Notice>('/notices', data),
update: (id: number, data: UpdateNoticeRequest) =>
request.put<Notice>(`/notice/${id}`, data),
request.put<Notice>(`/notices/${id}`, data),
delete: (id: number) =>
request.delete<void>(`/notice/${id}`),
request.delete<void>(`/notices/${id}`),
}
+111 -6
View File
@@ -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<string, MenuItem['type']> = {
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<string, string> = {
'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<string, string> = {
'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<MenuItem[]>('/menus'),
getAll: async (): Promise<MenuItem[]> => {
const res = await request.get<RawMenuItem[]>('/menus')
const raw = (res as unknown as RawMenuItem[])
return Array.isArray(raw) ? raw.map(normalizeMenuItem) : []
},
getById: (id: number) =>
request.get<MenuItem>(`/menus/${id}`),
getById: async (id: number): Promise<MenuItem> => {
const res = await request.get<RawMenuItem>(`/menus/${id}`)
return normalizeMenuItem(res as unknown as RawMenuItem)
},
getTree: () =>
request.get<MenuItem[]>('/menus/tree'),
getTree: async (): Promise<MenuItem[]> => {
const res = await request.get<RawMenuItem[]>('/menus/tree')
const raw = (res as unknown as RawMenuItem[])
return Array.isArray(raw) ? raw.map(normalizeMenuItem) : []
},
create: (data: CreateMenuRequest) =>
request.post<MenuItem>('/menus', data),