chore: 完成系统监控-在线用户

This commit is contained in:
xiaoxian521 2024-03-02 21:36:16 +08:00
parent 341789a177
commit f1fbd897fd
6 changed files with 294 additions and 19 deletions

View File

@ -65,7 +65,7 @@ const systemMonitorRouter = {
children: [
{
path: "/monitor/online-user",
component: "monitor/online",
component: "monitor/online/index",
name: "OnlineUser",
meta: {
icon: "ri:user-voice-line",

View File

@ -688,7 +688,7 @@ export default defineFakeRoute([
title: "menus.hsOnlineUser",
name: "OnlineUser",
path: "/monitor/online-user",
component: "monitor/online",
component: "monitor/online/index",
rank: null,
redirect: "",
icon: "ri:user-voice-line",
@ -1011,5 +1011,42 @@ export default defineFakeRoute([
]
};
}
},
// 在线用户
{
url: "/online",
method: "post",
response: ({ body }) => {
let list = [
{
id: 1,
username: "admin",
ip: faker.internet.ipv4(),
address: "中国河南省信阳市",
system: "macOS",
browser: "Chrome",
loginTime: new Date()
},
{
id: 2,
username: "common",
ip: faker.internet.ipv4(),
address: "中国广东省深圳市",
system: "Windows",
browser: "Firefox",
loginTime: new Date()
}
];
list = list.filter(item => item.username.includes(body?.username));
return {
success: true,
data: {
list,
total: list.length, // 总条目数
pageSize: 10, // 每页显示条目个数
currentPage: 1 // 当前页数
}
};
}
}
]);

View File

@ -19,32 +19,37 @@ type ResultTable = {
};
};
/** 获取用户管理列表 */
/** 获取系统管理-用户管理列表 */
export const getUserList = (data?: object) => {
return http.request<ResultTable>("post", "/user", { data });
};
/** 用户管理-获取所有角色列表 */
/** 系统管理-用户管理-获取所有角色列表 */
export const getAllRoleList = () => {
return http.request<Result>("get", "/list-all-role");
};
/** 用户管理-根据userId获取对应角色id列表userId用户id */
/** 系统管理-用户管理-根据userId获取对应角色id列表userId用户id */
export const getRoleIds = (data?: object) => {
return http.request<Result>("post", "/list-role-ids", { data });
};
/** 获取角色管理列表 */
/** 获取系统管理-角色管理列表 */
export const getRoleList = (data?: object) => {
return http.request<ResultTable>("post", "/role", { data });
};
/** 获取部门管理列表 */
/** 获取系统管理-菜单管理列表 */
export const getMenuList = (data?: object) => {
return http.request<Result>("post", "/menu", { data });
};
/** 获取系统管理-部门管理列表 */
export const getDeptList = (data?: object) => {
return http.request<Result>("post", "/dept", { data });
};
/** 获取菜单管理列表 */
export const getMenuList = (data?: object) => {
return http.request<Result>("post", "/menu", { data });
/** 获取系统监控-在线用户列表 */
export const getOnlineList = (data?: object) => {
return http.request<ResultTable>("post", "/online", { data });
};

View File

@ -1,9 +0,0 @@
<script setup lang="ts">
defineOptions({
name: "OnlineUser"
});
</script>
<template>
<div>OnlineUser</div>
</template>

View File

@ -0,0 +1,117 @@
import dayjs from "dayjs";
import { message } from "@/utils/message";
import { getOnlineList } from "@/api/system";
import { reactive, ref, onMounted, toRaw } from "vue";
import type { PaginationProps } from "@pureadmin/table";
export function useRole() {
const form = reactive({
username: ""
});
const dataList = ref([]);
const loading = ref(true);
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
const columns: TableColumnList = [
{
label: "序号",
prop: "id",
minWidth: 60
},
{
label: "用户名",
prop: "username",
minWidth: 100
},
{
label: "登录 IP",
prop: "ip",
minWidth: 140
},
{
label: "登录地点",
prop: "address",
minWidth: 140
},
{
label: "操作系统",
prop: "system",
minWidth: 100
},
{
label: "浏览器类型",
prop: "browser",
minWidth: 100
},
{
label: "登录时间",
prop: "loginTime",
minWidth: 180,
formatter: ({ loginTime }) =>
dayjs(loginTime).format("YYYY-MM-DD HH:mm:ss")
},
{
label: "操作",
fixed: "right",
slot: "operation"
}
];
function handleSizeChange(val: number) {
console.log(`${val} items per page`);
}
function handleCurrentChange(val: number) {
console.log(`current page: ${val}`);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
function handleOffline(row) {
message(`${row.username}已被强制下线`, { type: "success" });
onSearch();
}
async function onSearch() {
loading.value = true;
const { data } = await getOnlineList(toRaw(form));
dataList.value = data.list;
pagination.total = data.total;
pagination.pageSize = data.pageSize;
pagination.currentPage = data.currentPage;
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = formEl => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
return {
form,
loading,
columns,
dataList,
pagination,
onSearch,
resetForm,
handleOffline,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
};
}

View File

@ -0,0 +1,125 @@
<script setup lang="ts">
import { ref } from "vue";
import { useRole } from "./hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Plane from "@iconify-icons/ri/plane-line";
import Refresh from "@iconify-icons/ep/refresh";
defineOptions({
name: "OnlineUser"
});
const formRef = ref();
const {
form,
loading,
columns,
dataList,
pagination,
onSearch,
resetForm,
handleOffline,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
} = useRole();
</script>
<template>
<div class="main">
<el-form
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
>
<el-form-item label="用户名" prop="username">
<el-input
v-model="form.username"
placeholder="请输入用户名"
clearable
class="!w-[180px]"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:icon="useRenderIcon('ri:search-line')"
:loading="loading"
@click="onSearch"
>
搜索
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
重置
</el-button>
</el-form-item>
</el-form>
<PureTableBar
title="在线用户(仅演示,操作后不生效)"
:columns="columns"
@refresh="onSearch"
>
<template v-slot="{ size, dynamicColumns }">
<pure-table
align-whole="center"
showOverflowTooltip
table-layout="auto"
:loading="loading"
:size="size"
adaptive
:adaptiveConfig="{ offsetBottom: 108 }"
:data="dataList"
:columns="dynamicColumns"
:pagination="pagination"
:paginationSmall="size === 'small' ? true : false"
:header-cell-style="{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@selection-change="handleSelectionChange"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
>
<template #operation="{ row }">
<el-popconfirm
:title="`是否强制下线${row.username}`"
@confirm="handleOffline(row)"
>
<template #reference>
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(Plane)"
>
强退
</el-button>
</template>
</el-popconfirm>
</template>
</pure-table>
</template>
</PureTableBar>
</div>
</template>
<style scoped lang="scss">
:deep(.el-dropdown-menu__item i) {
margin: 0;
}
.main-content {
margin: 24px 24px 0 !important;
}
.search-form {
:deep(.el-form-item) {
margin-bottom: 12px;
}
}
</style>