298 lines
5.9 KiB
Vue
298 lines
5.9 KiB
Vue
<template>
|
||
<AppPage :show-footer="true">
|
||
<div class="flex">
|
||
<n-card class="w-30%">
|
||
<div class="flex items-center">
|
||
<n-avatar round :size="60" :src="userStore.avatar" />
|
||
<div class="ml-20 flex-col">
|
||
<span class="text-20 opacity-80">Hello, {{ userStore.nickname }}</span>
|
||
<span class="mt-4 opacity-50">今日事,今日毕。</span>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="mt-40 text-14 opacity-60">{{ dailyPoetry.content || '莫向外求,但从心觅,行有不得,反求诸己。' }}</p>
|
||
<p class="mt-32 text-right text-12 opacity-40">—— {{ dailyPoetry.author || '佚名' }}</p>
|
||
</n-card>
|
||
<n-card class="ml-12 w-70%">
|
||
<n-data-table
|
||
remote
|
||
:columns="tableColumns"
|
||
:data="tableData.data"
|
||
:pagination="paginate"
|
||
/>
|
||
</n-card>
|
||
</div>
|
||
<n-card>
|
||
<n-data-table
|
||
remote
|
||
:columns="connectionsColumns"
|
||
:data="connectionsData.data"
|
||
:row-props="rowProps"
|
||
/>
|
||
<n-dropdown
|
||
placement="bottom-start"
|
||
trigger="manual"
|
||
size="small"
|
||
:x="xRef"
|
||
:y="yRef"
|
||
:options="rightMenuOpts"
|
||
@select="rowSelect"
|
||
@clickoutside="rowClick"
|
||
:show="showDropdownRef"
|
||
/>
|
||
</n-card>
|
||
</AppPage>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { useUserStore } from '@/store'
|
||
import api from '@/views/workbench/api'
|
||
import { debounce, renderIcon } from '@/utils'
|
||
import { NTag } from 'naive-ui'
|
||
const userStore = useUserStore()
|
||
|
||
// 表格表头
|
||
const tableColumns = [
|
||
{
|
||
title: '用户名称',
|
||
key: 'username',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '客户端IP',
|
||
key: 'clientIP',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '请求方法',
|
||
key: 'method',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '请求主机',
|
||
key: 'host',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '请求地址',
|
||
key: 'uri',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '状态码',
|
||
key: 'statusCode',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '请求时间',
|
||
key: 'createdAt',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
]
|
||
// 链接信息列表
|
||
const connectionsColumns = [
|
||
{
|
||
title: '客户端名称',
|
||
key: 'name',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '联系邮箱',
|
||
key: 'email',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '客户端IP',
|
||
key: 'ipAllocation',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '端点',
|
||
key: 'connectEndpoint',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '是否在线',
|
||
key: 'online',
|
||
align: 'center',
|
||
titleAlign: 'center',
|
||
render: (row) => {
|
||
switch (row.online) {
|
||
case true:
|
||
return h(NTag,{
|
||
type: 'info',
|
||
},{
|
||
default: () => '在线'
|
||
})
|
||
case false:
|
||
return h(NTag,{
|
||
type: 'warning',
|
||
},{
|
||
default: () => '离线'
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
title: '接受流量',
|
||
key: 'receiveBytes',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '传输流量',
|
||
key: 'transmitBytes',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
},
|
||
{
|
||
title: '最后握手时间',
|
||
key: 'lastHandAt',
|
||
align: 'center',
|
||
titleAlign: 'center'
|
||
}
|
||
]
|
||
|
||
// 链接列表邮件刷新菜单
|
||
const rightMenuOpts = [
|
||
{
|
||
label: () => h('span',{ style: { color: 'green' }}, '刷新'),
|
||
key: "refresh",
|
||
icon: renderIcon('tabler:refresh',{ size: 14 })
|
||
}
|
||
]
|
||
|
||
// 右键菜单的设置
|
||
const showDropdownRef = ref(false);
|
||
const xRef = ref(0);
|
||
const yRef = ref(0);
|
||
|
||
// 右键菜单的基本位置逻辑
|
||
function rowProps(row) {
|
||
return {
|
||
onContextmenu: (e) => {
|
||
// $message.info(JSON.stringify(row, null, 2));
|
||
e.preventDefault();
|
||
showDropdownRef.value = false;
|
||
nextTick().then(() => {
|
||
showDropdownRef.value = true;
|
||
xRef.value = e.clientX;
|
||
yRef.value = e.clientY;
|
||
});
|
||
}
|
||
};
|
||
}
|
||
|
||
// 右键菜单的逻辑
|
||
function rowSelect(row) {
|
||
switch (row) {
|
||
case "refresh":
|
||
getClientConnections()
|
||
showDropdownRef.value = false
|
||
}
|
||
}
|
||
|
||
function rowClick() {
|
||
showDropdownRef.value = false
|
||
}
|
||
|
||
// 表格数据
|
||
const tableData = ref({
|
||
data: []
|
||
})
|
||
|
||
// 链接数据
|
||
const connectionsData = ref({
|
||
data: []
|
||
})
|
||
|
||
const dailyPoetry = ref({
|
||
author: '',
|
||
content: ''
|
||
})
|
||
|
||
// 页码控件
|
||
const paginate = reactive({
|
||
page: 1,
|
||
pageSize: 2,
|
||
itemCount: 0,
|
||
pageCount: 0,
|
||
onChange: (page) => {
|
||
paginate.page = page;
|
||
getLogsList()
|
||
}
|
||
})
|
||
|
||
// 获取操作日志列表
|
||
async function getLogsList() {
|
||
try {
|
||
const res = await api.logsList({
|
||
current: paginate.page,
|
||
size: paginate.pageSize,
|
||
})
|
||
if (res.data.code === 200) {
|
||
tableData.value.data = res.data.data.records;
|
||
paginate.itemCount = res.data.data.total;
|
||
paginate.pageCount = res.data.data.totalPage;
|
||
}
|
||
}catch (error) {
|
||
return error
|
||
}
|
||
}
|
||
|
||
// 每日诗词
|
||
const dailyPoe = debounce(() => {
|
||
getDailyPoetry()
|
||
},800)
|
||
|
||
// 获取每日诗词
|
||
function getDailyPoetry() {
|
||
try {
|
||
api.dailyPoetry().then(res => {
|
||
if (res.data.code === 200) {
|
||
dailyPoetry.value.author = res.data.data.author;
|
||
dailyPoetry.value.content = res.data.data.content;
|
||
}
|
||
})
|
||
}catch (error) {
|
||
return error
|
||
}
|
||
}
|
||
|
||
const connectionList = debounce(() => {
|
||
getClientConnections()
|
||
},300)
|
||
|
||
// 获取客户端链接列表
|
||
async function getClientConnections() {
|
||
try {
|
||
const res = await api.clientConnections()
|
||
if (res.data.code === 200) {
|
||
connectionsData.value.data = res.data.data;
|
||
}
|
||
}catch (e) {
|
||
return e
|
||
}
|
||
}
|
||
|
||
const initFunc = debounce(() => {
|
||
getClientConnections()
|
||
// dailyPoe()
|
||
// connectionList()
|
||
},500)
|
||
|
||
getLogsList()
|
||
initFunc()
|
||
</script>
|