124
src/api/system/log.ts
Normal file
124
src/api/system/log.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -48,6 +48,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "编辑用户"
|
"navigationBarTitleText": "编辑用户"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/work/log/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "日志管理"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const gridList = reactive([
|
|||||||
{
|
{
|
||||||
icon: "/static/icons/log.png",
|
icon: "/static/icons/log.png",
|
||||||
title: "日志管理",
|
title: "日志管理",
|
||||||
|
url: "/pages/work/log/index",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "/static/icons/performance.png",
|
icon: "/static/icons/performance.png",
|
||||||
|
|||||||
269
src/pages/work/log/index.vue
Normal file
269
src/pages/work/log/index.vue
Normal 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>
|
||||||
Reference in New Issue
Block a user