mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-11 06:57:12 +08:00
新增:个人中心新增查询操作日志功能,优化日志表结构,并支持关闭记录内网 IP 操作
This commit is contained in:
34
continew-admin-ui/src/api/monitor/operation-log.ts
Normal file
34
continew-admin-ui/src/api/monitor/operation-log.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import axios from 'axios';
|
||||
import qs from 'query-string';
|
||||
|
||||
export interface OperationLogRecord {
|
||||
logId: string;
|
||||
description: string;
|
||||
result: number,
|
||||
requestIp: string,
|
||||
location: string,
|
||||
browser: string,
|
||||
createUserString: string;
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
export interface OperationLogParams extends Partial<OperationLogRecord> {
|
||||
page: number;
|
||||
size: number;
|
||||
sort: Array<string>;
|
||||
uid: string;
|
||||
}
|
||||
|
||||
export interface OperationLogListRes {
|
||||
list: OperationLogRecord[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export function queryOperationLogList(params: OperationLogParams) {
|
||||
return axios.get<OperationLogListRes>('/monitor/log/operation', {
|
||||
params,
|
||||
paramsSerializer: (obj) => {
|
||||
return qs.stringify(obj);
|
||||
},
|
||||
});
|
||||
}
|
@@ -90,5 +90,8 @@ body {
|
||||
&.pass {
|
||||
background-color: rgb(var(--green-6));
|
||||
}
|
||||
&.fail {
|
||||
background-color: rgb(var(--red-6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ import useAppStore from '../app';
|
||||
|
||||
const useLoginStore = defineStore('user', {
|
||||
state: (): UserState => ({
|
||||
userId: 1,
|
||||
userId: '',
|
||||
username: '',
|
||||
nickname: '',
|
||||
gender: 0,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
export type RoleType = '' | '*' | 'admin' | 'user';
|
||||
export interface UserState {
|
||||
userId: number;
|
||||
userId: string;
|
||||
username: string;
|
||||
nickname: string;
|
||||
gender: number;
|
||||
|
@@ -133,7 +133,7 @@
|
||||
captchaImgBase64.value = data.img
|
||||
}
|
||||
onMounted(() => {
|
||||
getCaptcha()
|
||||
getCaptcha();
|
||||
})
|
||||
|
||||
// 记住我
|
||||
|
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<a-table
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:columns="columns"
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
size="large"
|
||||
@page-change="onPageChange"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
|
||||
</template>
|
||||
<template #result="{ record }">
|
||||
<a-space v-if="record.result === 1">
|
||||
<a-tag color="green">
|
||||
<span class="circle pass"></span>
|
||||
成功
|
||||
</a-tag>
|
||||
</a-space>
|
||||
<a-space v-else>
|
||||
<a-tag color="red">
|
||||
<span class="circle fail"></span>
|
||||
失败
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #pagination-left>
|
||||
<a-tooltip content="刷新">
|
||||
<div class="action-icon" @click="onRefresh">
|
||||
<icon-refresh size="18" />
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, reactive } from "vue";
|
||||
import { useLoginStore } from '@/store';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { queryOperationLogList, OperationLogRecord, OperationLogParams } from '@/api/monitor/operation-log';
|
||||
import { Pagination } from '@/types/global';
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const loginStore = useLoginStore();
|
||||
const renderData = ref<OperationLogRecord[]>([]);
|
||||
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
const pagination = reactive({
|
||||
...basePagination,
|
||||
});
|
||||
const columns = computed<TableColumnData[]>(() => [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
slotName: 'index',
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
dataIndex: 'createTime',
|
||||
},
|
||||
{
|
||||
title: '操作内容',
|
||||
dataIndex: 'description',
|
||||
},
|
||||
{
|
||||
title: '操作结果',
|
||||
dataIndex: 'result',
|
||||
slotName: 'result',
|
||||
},
|
||||
{
|
||||
title: '操作IP',
|
||||
dataIndex: 'requestIp',
|
||||
},
|
||||
{
|
||||
title: '操作地点',
|
||||
dataIndex: 'location',
|
||||
},
|
||||
{
|
||||
title: '浏览器',
|
||||
dataIndex: 'browser',
|
||||
},
|
||||
]);
|
||||
const fetchData = async (
|
||||
params: OperationLogParams = { uid: loginStore.userId, page: 1, size: 10, sort: ['createTime,desc'] }
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await queryOperationLogList(params);
|
||||
renderData.value = data.list;
|
||||
pagination.current = params.page;
|
||||
pagination.total = data.total;
|
||||
} catch (err) {
|
||||
// you can report use errorHandler or other
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ uid: loginStore.userId, page: current, size: pagination.pageSize, sort: ['createTime,desc'] });
|
||||
};
|
||||
|
||||
const onRefresh = () => {
|
||||
fetchData({
|
||||
uid: loginStore.userId,
|
||||
page: pagination.current,
|
||||
size: pagination.pageSize,
|
||||
sort: ['createTime,desc'],
|
||||
} as unknown as OperationLogParams);
|
||||
};
|
||||
|
||||
fetchData();
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.container {
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
:deep(.arco-table-th) {
|
||||
&:last-child {
|
||||
.arco-table-th-item-title {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.action-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-icon:hover {
|
||||
color: #0960bd;
|
||||
}
|
||||
</style>
|
@@ -15,6 +15,9 @@
|
||||
<a-tab-pane key="2" :title="$t('userCenter.tab.securitySettings')">
|
||||
<SecuritySettings />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" :title="$t('userCenter.tab.operationLog')">
|
||||
<OperationLog />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -25,6 +28,7 @@
|
||||
import UserPanel from './components/user-panel.vue';
|
||||
import BasicInfo from './components/basic-info.vue';
|
||||
import SecuritySettings from './components/security-settings.vue';
|
||||
import OperationLog from './components/operation-log.vue';
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
@@ -2,6 +2,7 @@ export default {
|
||||
'menu.user.center': 'User Center',
|
||||
'userCenter.tab.basicInfo': 'Basic Information',
|
||||
'userCenter.tab.securitySettings': 'Security Settings',
|
||||
'userCenter.tab.operationLog': 'Operation Log',
|
||||
|
||||
// user-panel
|
||||
'userCenter.panel.avatar': 'Avatar',
|
||||
|
@@ -2,6 +2,7 @@ export default {
|
||||
'menu.user.center': '个人中心',
|
||||
'userCenter.tab.basicInfo': '基础信息',
|
||||
'userCenter.tab.securitySettings': '安全设置',
|
||||
'userCenter.tab.operationLog': '操作日志',
|
||||
|
||||
// user-panel
|
||||
'userCenter.panel.avatar': '头像',
|
||||
|
Reference in New Issue
Block a user