!1 feat: 日志管理模块

Merge pull request !1 from liangxinyu/feature-logSys
This commit is contained in:
郝先瑞
2024-11-13 23:38:20 +00:00
committed by Gitee
4 changed files with 400 additions and 0 deletions

124
src/api/system/log.ts Normal file
View File

@@ -0,0 +1,124 @@
import request from "@/utils/request";
const LOG_BASE_URL = "/api/v1/logs";
class LogAPI {
/**
* 获取日志分页列表
*
* @param queryParams 查询参数
*/
static getPage(queryParams: LogPageQuery) {
return request<PageResult<LogPageVO[]>>({
url: `${LOG_BASE_URL}/page`,
method: "GET",
data: queryParams,
});
}
/**
* 获取访问趋势
*
* @param queryParams
* @returns
*/
static getVisitTrend(queryParams: VisitTrendQuery) {
return request<VisitTrendVO>({
url: `${LOG_BASE_URL}/visit-trend`,
method: "GET",
data: queryParams,
});
}
/**
* 获取访问趋势
*
* @param queryParams
* @returns
*/
static getVisitStats() {
return request<VisitStatsVO[]>({
url: `${LOG_BASE_URL}/visit-stats`,
method: "GET",
});
}
}
export default LogAPI;
/**
* 日志分页查询对象
*/
export interface LogPageQuery extends PageQuery {
/** 搜索关键字 */
keywords: string;
/** 操作时间 */
createTime: [string, string];
}
/**
* 系统日志分页VO
*/
export interface LogPageVO {
/** 主键 */
id?: number;
/** 日志模块 */
module?: string;
/** 日志内容 */
content?: string;
/** 请求路径 */
requestUri?: string;
/** 请求方法 */
method?: string;
/** IP 地址 */
ip?: string;
/** 地区 */
region?: string;
/** 浏览器 */
browser?: string;
/** 终端系统 */
os?: string;
/** 执行时间(毫秒) */
executionTime?: number;
/** 操作人 */
operator?: string;
/** 操作时间 */
createTime?: string;
}
/** 访问趋势视图对象 */
export interface VisitTrendVO {
/** 日期列表 */
dates: string[];
/** 浏览量(PV) */
pvList: number[];
/** 访客数(UV) */
uvList: number[];
/** IP数 */
ipList: number[];
}
/** 访问趋势查询参数 */
export interface VisitTrendQuery {
/** 开始日期 */
startDate: string;
/** 结束日期 */
endDate: string;
}
/** 访问统计 */
export interface VisitStatsVO {
/** 标题 */
title: string;
/** 类型 */
type: "pv" | "uv" | "ip";
/** 今日访问量 */
todayCount: number;
/** 总访问量 */
totalCount: number;
/** 同比增长率(相对于昨天同一时间段的增长率) */
growthRate: number;
totalCountOutput: number;
}

View File

@@ -48,6 +48,12 @@
"style": {
"navigationBarTitleText": "编辑用户"
}
},
{
"path": "pages/work/log/index",
"style": {
"navigationBarTitleText": "日志管理"
}
}
],
"globalStyle": {

View File

@@ -72,6 +72,7 @@ const gridList = reactive([
{
icon: "/static/icons/log.png",
title: "日志管理",
url: "/pages/work/log/index",
},
{
icon: "/static/icons/performance.png",

View File

@@ -0,0 +1,269 @@
<template>
<view class="log">
<!-- 筛选 -->
<wd-drop-menu close-on-click-modal class="mb-20rpx">
<wd-drop-menu-item
ref="dropMenu"
title="筛选"
icon="filter"
icon-size="18px"
@opened="handleOpened"
>
<view>
<wd-input
v-model="queryParams.keywords"
label="关键字"
type="text"
placeholder="请输入关键字"
/>
<wd-calendar
v-model="timeStampArray"
label="日期选择"
type="daterange"
allow-same-day
@confirm="handleConfirm"
/>
<view class="flex flex-row items-center mb-20rpx">
<wd-button class="mt-20rpx mb-20rpx" size="medium" @click="search()">查询</wd-button>
<wd-button size="medium" type="info" @click="reset">重置</wd-button>
</view>
</view>
</wd-drop-menu-item>
</wd-drop-menu>
<!-- 卡片列表 -->
<view v-for="(item, index) in pageData" :key="index">
<wd-card :title="item.operator">
<wd-row>
<wd-col v-for="(rowItem, rowIndex) in listPageTypeArray" :key="rowIndex" :span="12">
<wd-col :span="rowItem.titleSpan">
<view>{{ rowItem.title }}</view>
</wd-col>
<wd-col :span="rowItem.keySpan">
<view>{{ item[rowItem.key] }}</view>
</wd-col>
</wd-col>
</wd-row>
<template #footer>
<wd-button size="small" plain @click="getDetail(item)">查看详情</wd-button>
</template>
</wd-card>
</view>
<!-- 查看详情 -->
<wd-action-sheet v-model="detailShow">
<view class="p-50rpx">
<wd-row v-for="(rowItem, rowIndex) in detailTypeArray" :key="rowIndex" class="mt-20rpx">
<wd-col :span="rowItem.titleSpan">
<view>{{ rowItem.title }}</view>
</wd-col>
<wd-col :span="rowItem.keySpan">
<view>{{ logDetail[rowItem.key] }}</view>
</wd-col>
</wd-row>
</view>
</wd-action-sheet>
<!-- 加载更多 -->
<wd-loadmore custom-class="loadmore" :state="loadMoreState" />
</view>
</template>
<script lang="ts" setup>
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log";
import { LoadMoreState } from "wot-design-uni/components/wd-loadmore/types";
import { DropMenuItemExpose } from "wot-design-uni/components/wd-drop-menu-item/types";
import { dayjs } from "wot-design-uni";
const loadMoreState = ref<LoadMoreState>("loading");
const queryParams = reactive<LogPageQuery>({
pageNum: 1,
pageSize: 10,
keywords: "",
createTime: ["", ""],
});
const timeStampArray = ref<number[]>([]);
/**
* 日期格式化
*/
function handleConfirm({ value }: Ref<number[]>) {
queryParams.createTime[0] = dayjs(value[0]).format("YYYY-MM-DD");
queryParams.createTime[1] = dayjs(value[1]).format("YYYY-MM-DD");
}
/**
* 搜索栏
*/
const dropMenu = ref<DropMenuItemExpose>();
function search() {
pageData.value = [];
dropMenu.value?.close();
handleQuery();
}
/**
* 重置搜索条件
*/
function reset() {
queryParams.pageNum = 1;
queryParams.keywords = "";
queryParams.createTime = ["", ""];
timeStampArray.value = [];
pageData.value = [];
dropMenu.value?.close();
handleQuery();
}
// 日志卡片列表数据
const pageData = ref<LogPageVO[]>([]);
onLoad(() => {
handleQuery();
});
/**
* 查询
*/
function handleQuery() {
loadMoreState.value = "loading";
LogAPI.getPage(queryParams)
.then((data) => {
pageData.value?.push(...data.list);
})
.catch((e) => {
console.log("系统异常", e);
})
.finally(() => {
loadMoreState.value = "finished";
});
}
/**
* 触底事件
*/
onReachBottom(() => {
queryParams.pageNum++;
handleQuery();
});
/**
* 卡片列表展示字段
*/
interface listPageType {
title: string;
key: keyof LogPageVO;
titleSpan: Number;
keySpan: Number;
}
const listPageTypeArray = ref<listPageType[]>([
{
title: "模块",
key: "module",
titleSpan: 8,
keySpan: 16,
},
{
title: "内容",
key: "content",
titleSpan: 8,
keySpan: 16,
},
{
title: "时间",
key: "createTime",
titleSpan: 8,
keySpan: 16,
},
{
title: "地区",
key: "region",
titleSpan: 8,
keySpan: 16,
},
]);
/**
* 卡片内容详情
*/
const logDetail = ref<LogPageVO>({});
const detailShow = ref<boolean>(false);
const detailTypeArray = ref<listPageType[]>([
{
title: "模块",
key: "module",
titleSpan: 6,
keySpan: 18,
},
{
title: "内容",
key: "content",
titleSpan: 6,
keySpan: 18,
},
{
title: "时间",
key: "createTime",
titleSpan: 6,
keySpan: 18,
},
{
title: "地区",
key: "region",
titleSpan: 6,
keySpan: 18,
},
{
title: "IP",
key: "ip",
titleSpan: 6,
keySpan: 18,
},
{
title: "浏览器",
key: "browser",
titleSpan: 6,
keySpan: 18,
},
{
title: "终端系统",
key: "os",
titleSpan: 6,
keySpan: 18,
},
{
title: "执行时间(ms)",
key: "executionTime",
titleSpan: 8,
keySpan: 16,
},
]);
function getDetail(item: LogPageVO) {
detailShow.value = true;
logDetail.value = item;
}
/**
* 返回
*/
function back() {
uni.navigateBack();
}
</script>
<style lang="scss" scoped>
.log {
background: #f8f8f8;
}
.wd-col {
margin-top: 10rpx;
}
::v-deep .wd-drop-menu__item {
display: flex;
justify-content: flex-end;
padding: 0 50rpx;
}
</style>