203 lines
4.5 KiB
Vue
203 lines
4.5 KiB
Vue
<script setup lang="ts">
|
|
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
|
|
import {useToast} from "vue-toastification";
|
|
|
|
const toast = useToast()
|
|
const mainLayoutStore = useMainLayoutStore()
|
|
const userList = ref<UserListItem[]>([])
|
|
type UserListItem = {
|
|
"name": string,
|
|
"isOnline": boolean,
|
|
"lastLoginTime": string,
|
|
"address": string,
|
|
"port": string,
|
|
}
|
|
const GetServerUserList = () => {
|
|
$fetch('/Api/Server/GetServerUserList', {
|
|
method: 'GET',
|
|
params: {
|
|
ServerId: mainLayoutStore.SelectServer.value
|
|
},
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': "Bearer " + useCookie('token').value
|
|
},
|
|
baseURL: useRuntimeConfig().public.baseUrl
|
|
}).then(res => {
|
|
userList.value=res as UserListItem[];
|
|
}).catch(err => {
|
|
toast.error(err)
|
|
})
|
|
}
|
|
onMounted(() => {
|
|
GetServerUserList()
|
|
})
|
|
const refresh = () => {
|
|
userList.value=[]
|
|
GetServerUserList()
|
|
}
|
|
const page=ref<number>(1)
|
|
const filterPage=computed(()=>{
|
|
if(userList.value.length<=10){
|
|
return userList.value
|
|
}
|
|
return userList.value.slice((page.value-1)*14,page.value*14)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="user-list-layout">
|
|
<div class="user-list-header">
|
|
<Icon name="ArrowDownUp" :size="24" :stroke-width="1.5"></Icon>
|
|
<h3>用户列表</h3>
|
|
<Icon name="Repeat2" :size="24" :stroke-width="1.5" @click="refresh"/>
|
|
</div>
|
|
<div class="user-list-body">
|
|
<div class="user-list-item" @click="navigateTo(`/serverUser/all`)">
|
|
<div class="avatar">
|
|
<n-avatar
|
|
:size="48"> 全部 </n-avatar>
|
|
</div>
|
|
<div class="info">
|
|
<div class="top">
|
|
<h3>全部</h3>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div :class="{'user-list-item':true,'user-list-item-active':$route.params.id===item.name}" v-for="item in filterPage" @click="navigateTo(`/serverUser/${item.name.split(':')[0]}`)">
|
|
<div class="avatar">
|
|
<n-avatar
|
|
:size="48">
|
|
{{item.name.slice(0,3).toUpperCase()}}
|
|
</n-avatar>
|
|
</div>
|
|
<div class="info">
|
|
<div class="top">
|
|
<h3>{{ item.name.split(':')[0] }}</h3>
|
|
<div class="tags">
|
|
<n-tag type="info" :bordered="false">UID:{{item.name.split(':')[1]}}</n-tag>
|
|
<n-Tag v-if="item.isOnline">在线</n-Tag>
|
|
<n-Tag v-if="item.isOnline">{{item.port}}</n-Tag>
|
|
<n-Tag v-if="item.isOnline">{{item.address}}</n-Tag>
|
|
</div>
|
|
</div>
|
|
<p>{{item.lastLoginTime}}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="pages">
|
|
<n-pagination v-model:page="page" :page-count="Math.floor(userList.length/13)" size="medium"/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import "base";
|
|
|
|
.user-list-layout {
|
|
background: $light-bg-color;
|
|
border-radius: $radius;
|
|
border: $border;
|
|
padding: $padding 0;
|
|
grid-row: 1/3;
|
|
display: flex;
|
|
flex-direction: column;
|
|
*{
|
|
@include SC_Font;
|
|
}
|
|
.dark-mode &{
|
|
background: $dark-bg-color;
|
|
}
|
|
}
|
|
|
|
.user-list-header {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 $padding;
|
|
justify-content: space-between;
|
|
h3{
|
|
color: $light-text-color;
|
|
}
|
|
svg {
|
|
color: rgba(51, 51, 51, 0.34);
|
|
stroke: rgba(51, 51, 51, 0.44);
|
|
cursor: pointer;
|
|
&:hover {
|
|
stroke: rgba(51, 51, 51, 0.64);
|
|
}
|
|
}
|
|
.dark-mode &{
|
|
h3{
|
|
color: $dark-text-color;
|
|
}
|
|
svg{
|
|
color: rgba(255, 255, 255, 0.34);
|
|
stroke: rgba(255, 255, 255, 0.44);
|
|
&:hover {
|
|
stroke: rgba(255, 255, 255, 0.64);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.pages{
|
|
padding: $padding;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.user-list-body{
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
gap: $gap;
|
|
padding: $padding*2 $padding;
|
|
}
|
|
.user-list-item{
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $gap*4;
|
|
padding: 8px;
|
|
border-radius: $radius;
|
|
cursor: pointer;
|
|
.avatar{
|
|
display: flex;
|
|
}
|
|
h3,p{
|
|
color: $light-text-color;
|
|
}
|
|
.dark-mode &{
|
|
h3,p{
|
|
color: $dark-text-color;
|
|
}
|
|
}
|
|
&:hover{
|
|
background: rgba(51, 51, 51, 0.06);
|
|
}
|
|
.dark-mode &{
|
|
&:hover{
|
|
background: rgba(255, 255, 255, 0.06);
|
|
}
|
|
}
|
|
.info{
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex:1;
|
|
gap: $gap;
|
|
.top{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
.tags{
|
|
display: flex;
|
|
gap: $gap;
|
|
}
|
|
}
|
|
}
|
|
.user-list-item-active{
|
|
background: rgba(51, 51, 51, 0.2);
|
|
|
|
.dark-mode &{
|
|
background: rgba(255, 255, 255, 0.2);
|
|
}
|
|
}
|
|
</style> |