add log component: prolist

mgy
Dawn1Ocean 2024-04-02 02:55:09 +08:00
parent 0d1665f609
commit 2cb4684130
17 changed files with 350 additions and 604 deletions

View File

@ -220,11 +220,26 @@ request:
### 获取日志列表 `GET /admin/loglist`
request:
```json
{
"pageIndex": 1,
"size": 10,
}
```
data:
```json
{
"page": 1,
"total": 24,
"success": true,
"data": [
{
"op": "宇航员",
"avatar": "https://...",
"time": "2024-03-07T19:52:48.523303",
"operation": 2,
"target": 1,
@ -236,7 +251,10 @@ data:
"id": 514,
"info": "何君琳"
}
},
},
// ...
]
}
```
前端显示的信息:"{op} 于 {time} {operation} 了 {target}{prev.info} -> {curr.info}"

152
mock/loglist.json 100644
View File

@ -0,0 +1,152 @@
[
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:48.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:49.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:50.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "晓洋",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:51.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:52.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:53.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:54.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:55.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:56.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
},
{
"op": "宇航员",
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"time": "2024-03-07T19:52:57.523303",
"operation": 2,
"target": 1,
"prev": {
"id": 114,
"info": "马嘉祺"
},
"curr": {
"id": 514,
"info": "何君琳"
}
}
]

View File

@ -1,5 +1,6 @@
import sheet from './sheet.json'
import sheetlist from './sheetlist.json'
import loglist from './loglist.json';
import sheet from './sheet.json';
import sheetlist from './sheetlist.json';
module.exports = {
'GET /admin/stats': {
@ -43,20 +44,9 @@ module.exports = {
},
'GET /admin/loglist': {
success: true,
data: {
op: '宇航员',
time: '2024-03-07T19:52:48.523303',
operation: 2,
target: 1,
prev: {
id: 114,
info: '马嘉祺',
},
curr: {
id: 514,
info: '何君琳',
},
},
page: 1,
total: 24,
data: loglist,
},
'GET /api/currentUser': {
data: {

View File

@ -1,5 +1,5 @@
import { AvatarDropdown, AvatarName, PageFooter } from '@/components';
import { currentUser as queryCurrentUser } from '@/services/ant-design-pro/api';
import { currentUser as queryCurrentUser } from '@/services/api';
import { LinkOutlined } from '@ant-design/icons';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { SettingDrawer } from '@ant-design/pro-components';
@ -7,6 +7,7 @@ import type { RunTimeLayoutConfig } from '@umijs/max';
import { Link, history } from '@umijs/max';
import defaultSettings from '../config/defaultSettings';
import { errorConfig } from './requestErrorConfig';
import { API } from './services/typings';
const isDev = process.env.NODE_ENV === 'development';
const loginPath = '/user/login';

View File

@ -1,4 +1,4 @@
import { outLogin } from '@/services/ant-design-pro/api';
import { outLogin } from '@/services/api';
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
import { history, useModel } from '@umijs/max';
import { Spin } from 'antd';

View File

@ -1,12 +1,88 @@
import { Todo } from '@/components';
import { PageContainer } from '@ant-design/pro-components';
import { PageContainer, ProList } from '@ant-design/pro-components';
import { Card } from 'antd';
import moment from 'moment';
import request from 'umi-request';
import transInfo, { LogsItem } from './logItem';
const Logs: React.FC = () => {
return (
<PageContainer>
<Card>
<Todo />
<ProList<LogsItem>
search={{
filterType: 'light',
}}
rowKey="op"
headerTitle="日志列表"
request={async (params = {} as Record<string, any>) =>
request<{
data: LogsItem[];
}>('http://127.0.0.1:8000/admin/loglist', {
params,
})
}
pagination={{
pageSize: 5,
}}
metas={{
title: {
dataIndex: 'op',
title: '用户',
},
avatar: {
dataIndex: 'avatar',
search: false,
},
description: {
dataIndex: ['time', 'operation', 'target', 'prev', 'curr'],
search: false,
render: (_, row) => {
return (
<div>
{'于 ' +
moment(row.time).format('lll') +
' ' +
transInfo(row.operation, 'operation') +
'了 ' +
transInfo(row.target, 'target') +
'' +
row.prev.info +
' -> ' +
row.curr.info}
</div>
);
},
},
actions: {
render: (text, row) => [
<a href="" target="_blank" rel="noopener noreferrer" key="view">
</a>,
],
search: false,
},
// status: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '更改部分',
// valueType: 'select',
// valueEnum: {
// all: { text: '全部', status: 'Default' },
// open: {
// text: '未解决',
// status: 'Error',
// },
// closed: {
// text: '已解决',
// status: 'Success',
// },
// processing: {
// text: '解决中',
// status: 'Processing',
// },
// },
// },
}}
/>
</Card>
</PageContainer>
);

View File

@ -0,0 +1,37 @@
const operationMap: { [key: number]: string } = {
0: '增加',
1: '删除',
2: '修改',
};
const targetMap: { [key: number]: string } = {
0: '值班表',
1: '值班信息',
2: '值班总结',
};
export type LogsItem = {
op: string;
time: string;
operation: number;
target: number;
prev: {
id: number;
info: string;
};
curr: {
id: number;
info: string;
};
};
const transInfo = (num: number, type: string) => {
switch (type) {
case 'operation':
return operationMap[num];
case 'target':
return targetMap[num];
}
};
export default transInfo;

View File

@ -1,7 +1,8 @@
import Settings from '@/../config/defaultSettings';
import oidcLogo from '@/assets/oidc-logo.svg';
import { PageFooter } from '@/components';
import { login } from '@/services/ant-design-pro/api';
import { login } from '@/services/api';
import { API } from '@/services/typings';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import { LoginForm, ProFormCheckbox, ProFormText } from '@ant-design/pro-components';
import { Helmet, history, useModel } from '@umijs/max';

View File

@ -1,94 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
}>('/api/currentUser', {
method: 'GET',
...(options || {}),
});
}
/** 退出登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/login/account', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/notices */
export async function getNotices(options?: { [key: string]: any }) {
return request<API.NoticeIconList>('/api/notices', {
method: 'GET',
...(options || {}),
});
}
/** 获取规则列表 GET /api/rule */
export async function rule(
params: {
// query
/** 当前的页码 */
current?: number;
/** 页面的容量 */
pageSize?: number;
},
options?: { [key: string]: any },
) {
return request<API.RuleList>('/api/rule', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 更新规则 PUT /api/rule */
export async function updateRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
data: {
method: 'update',
...(options || {}),
},
});
}
/** 新建规则 POST /api/rule */
export async function addRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
data: {
method: 'post',
...(options || {}),
},
});
}
/** 删除规则 DELETE /api/rule */
export async function removeRule(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/rule', {
method: 'POST',
data: {
method: 'delete',
...(options || {}),
},
});
}

View File

@ -0,0 +1,34 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
import { API } from './typings';
/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
}>('/api/currentUser', {
method: 'GET',
...(options || {}),
});
}
/** 退出登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/login/account', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}

View File

@ -1,12 +0,0 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as pet from './pet';
import * as store from './store';
import * as user from './user';
export default {
pet,
store,
user,
};

View File

@ -1,153 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Update an existing pet PUT /pet */
export async function updatePet(body: API.Pet, options?: { [key: string]: any }) {
return request<any>('/pet', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Add a new pet to the store POST /pet */
export async function addPet(body: API.Pet, options?: { [key: string]: any }) {
return request<any>('/pet', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Find pet by ID Returns a single pet GET /pet/${param0} */
export async function getPetById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getPetByIdParams,
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
return request<API.Pet>(`/pet/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updates a pet in the store with form data POST /pet/${param0} */
export async function updatePetWithForm(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.updatePetWithFormParams,
body: { name?: string; status?: string },
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
const formData = new FormData();
Object.keys(body).forEach((ele) => {
const item = (body as any)[ele];
if (item !== undefined && item !== null) {
formData.append(
ele,
typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item,
);
}
});
return request<any>(`/pet/${param0}`, {
method: 'POST',
params: { ...queryParams },
data: formData,
...(options || {}),
});
}
/** Deletes a pet DELETE /pet/${param0} */
export async function deletePet(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deletePetParams & {
// header
api_key?: string;
},
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
return request<any>(`/pet/${param0}`, {
method: 'DELETE',
headers: {},
params: { ...queryParams },
...(options || {}),
});
}
/** uploads an image POST /pet/${param0}/uploadImage */
export async function uploadFile(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.uploadFileParams,
body: { additionalMetadata?: string; file?: string },
file?: File,
options?: { [key: string]: any },
) {
const { petId: param0, ...queryParams } = params;
const formData = new FormData();
if (file) {
formData.append('file', file);
}
Object.keys(body).forEach((ele) => {
const item = (body as any)[ele];
if (item !== undefined && item !== null) {
formData.append(
ele,
typeof item === 'object' && !(item instanceof File) ? JSON.stringify(item) : item,
);
}
});
return request<API.ApiResponse>(`/pet/${param0}/uploadImage`, {
method: 'POST',
params: { ...queryParams },
data: formData,
requestType: 'form',
...(options || {}),
});
}
/** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */
export async function findPetsByStatus(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.findPetsByStatusParams,
options?: { [key: string]: any },
) {
return request<API.Pet[]>('/pet/findByStatus', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Finds Pets by tags Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. GET /pet/findByTags */
export async function findPetsByTags(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.findPetsByTagsParams,
options?: { [key: string]: any },
) {
return request<API.Pet[]>('/pet/findByTags', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}

View File

@ -1,48 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
export async function getInventory(options?: { [key: string]: any }) {
return request<Record<string, any>>('/store/inventory', {
method: 'GET',
...(options || {}),
});
}
/** Place an order for a pet POST /store/order */
export async function placeOrder(body: API.Order, options?: { [key: string]: any }) {
return request<API.Order>('/store/order', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions GET /store/order/${param0} */
export async function getOrderById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getOrderByIdParams,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<API.Order>(`/store/order/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Delete purchase order by ID For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors DELETE /store/order/${param0} */
export async function deleteOrder(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteOrderParams,
options?: { [key: string]: any },
) {
const { orderId: param0, ...queryParams } = params;
return request<any>(`/store/order/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}

View File

@ -1,112 +0,0 @@
declare namespace API {
type ApiResponse = {
code?: number;
type?: string;
message?: string;
};
type Category = {
id?: number;
name?: string;
};
type deleteOrderParams = {
/** ID of the order that needs to be deleted */
orderId: number;
};
type deletePetParams = {
api_key?: string;
/** Pet id to delete */
petId: number;
};
type deleteUserParams = {
/** The name that needs to be deleted */
username: string;
};
type findPetsByStatusParams = {
/** Status values that need to be considered for filter */
status: ('available' | 'pending' | 'sold')[];
};
type findPetsByTagsParams = {
/** Tags to filter by */
tags: string[];
};
type getOrderByIdParams = {
/** ID of pet that needs to be fetched */
orderId: number;
};
type getPetByIdParams = {
/** ID of pet to return */
petId: number;
};
type getUserByNameParams = {
/** The name that needs to be fetched. Use user1 for testing. */
username: string;
};
type loginUserParams = {
/** The user name for login */
username: string;
/** The password for login in clear text */
password: string;
};
type Order = {
id?: number;
petId?: number;
quantity?: number;
shipDate?: string;
/** Order Status */
status?: 'placed' | 'approved' | 'delivered';
complete?: boolean;
};
type Pet = {
id?: number;
category?: Category;
name: string;
photoUrls: string[];
tags?: Tag[];
/** pet status in the store */
status?: 'available' | 'pending' | 'sold';
};
type Tag = {
id?: number;
name?: string;
};
type updatePetWithFormParams = {
/** ID of pet that needs to be updated */
petId: number;
};
type updateUserParams = {
/** name that need to be updated */
username: string;
};
type uploadFileParams = {
/** ID of pet to update */
petId: number;
};
type User = {
id?: number;
username?: string;
firstName?: string;
lastName?: string;
email?: string;
password?: string;
phone?: string;
/** User Status */
userStatus?: number;
};
}

View File

@ -1,100 +0,0 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** Create user This can only be done by the logged in user. POST /user */
export async function createUser(body: API.User, options?: { [key: string]: any }) {
return request<any>('/user', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Get user by user name GET /user/${param0} */
export async function getUserByName(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getUserByNameParams,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<API.User>(`/user/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updated user This can only be done by the logged in user. PUT /user/${param0} */
export async function updateUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.updateUserParams,
body: API.User,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<any>(`/user/${param0}`, {
method: 'PUT',
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** Delete user This can only be done by the logged in user. DELETE /user/${param0} */
export async function deleteUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deleteUserParams,
options?: { [key: string]: any },
) {
const { username: param0, ...queryParams } = params;
return request<any>(`/user/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** Creates list of users with given input array POST /user/createWithArray */
export async function createUsersWithArrayInput(
body: API.User[],
options?: { [key: string]: any },
) {
return request<any>('/user/createWithArray', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Creates list of users with given input array POST /user/createWithList */
export async function createUsersWithListInput(body: API.User[], options?: { [key: string]: any }) {
return request<any>('/user/createWithList', {
method: 'POST',
data: body,
...(options || {}),
});
}
/** Logs user into the system GET /user/login */
export async function loginUser(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.loginUserParams,
options?: { [key: string]: any },
) {
return request<string>('/user/login', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Logs out current logged in user session GET /user/logout */
export async function logoutUser(options?: { [key: string]: any }) {
return request<any>('/user/logout', {
method: 'GET',
...(options || {}),
});
}

View File

@ -1,5 +1,4 @@
// @ts-ignore
/* eslint-disable */
import { LogsItem } from '@/pages/Logs/logItem';
declare namespace API {
type CurrentUser = {
@ -34,33 +33,6 @@ declare namespace API {
pageSize?: number;
};
type RuleListItem = {
key?: number;
disabled?: boolean;
href?: string;
avatar?: string;
name?: string;
owner?: string;
desc?: string;
callNo?: number;
status?: number;
updatedAt?: string;
createdAt?: string;
progress?: number;
};
type RuleList = {
data?: RuleListItem[];
/** 列表的内容总数 */
total?: number;
success?: boolean;
};
type FakeCaptcha = {
code?: number;
status?: string;
};
type LoginParams = {
username?: string;
password?: string;
@ -76,26 +48,10 @@ declare namespace API {
/** 业务上的请求是否成功 */
success?: boolean;
};
type NoticeIconList = {
data?: NoticeIconItem[];
/** 列表的内容总数 */
total?: number;
success?: boolean;
};
type NoticeIconItemType = 'notification' | 'message' | 'event';
type NoticeIconItem = {
id?: string;
extra?: string;
key?: string;
read?: boolean;
avatar?: string;
title?: string;
status?: string;
datetime?: string;
description?: string;
type?: NoticeIconItemType;
type LogList = {
pageIndex: number;
pageCount: number;
size: number;
data: LogsItem[];
};
}