提交 4365eecc authored 作者: 王鹏飞's avatar 王鹏飞

chore: 新增实验监控

上级 27bd8efa
import httpRequest from '@/utils/axios'
// 获取实验列表
export function getExperimentList(params: { page: number; 'per-page': number }) {
return httpRequest.get('/api/resource/v1/backend/experiment/monitor-experiments', { params })
}
<script setup lang="ts">
import AppList from '@/components/base/AppList.vue'
import { getExperimentList } from '../api'
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
const appList = ref<InstanceType<typeof AppList> | null>(null)
const list = ref([])
async function fetchInfo() {
const res = await getExperimentList()
list.value = res.data.items
}
onMounted(() => {
fetchInfo()
})
const dmlURL = computed(() => {
return appConfig.dmlURL || import.meta.env.VITE_DML_URL
})
// 实验列表
const listOptions = computed(() => {
return {
remote: {
httpRequest: getExperimentList,
callback(data) {
return { total: data.total, list: data.items }
}
},
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '所属机构', prop: 'org.department_name' },
{ label: '实验课程名称', prop: 'course_name' },
{ label: '实验名称', prop: 'name' },
{
label: '指导老师',
prop: 'teachers',
computed({ row }) {
return row.teachers.map(item => item.name).join(',')
}
},
{
label: '班级名称',
prop: 'student.specialty_name',
computed({ row }) {
return row.classes.map(item => item.name).join(',')
}
},
{
label: '班级人数',
prop: 'student.class_name',
computed({ row }) {
return row.classes.map(item => item.student_total).join(',')
}
},
{ label: '使用人数', prop: 'current_use_user_count' },
{ label: '用户数据量', prop: 'current_member_count' },
{ label: '标签数据量', prop: 'current_tag_count' },
{ label: '群组数据量', prop: 'current_group_count' },
{ label: '实验使用时间', prop: 'time' },
{ label: '操作', slots: 'table-x' }
]
}
})
</script>
<template>
<AppCard>
<ul class="statistics">
<template v-for="(item, index) in list" :key="item.id">
<el-popover :width="340" trigger="hover" v-if="index < 5">
<el-form label-suffix=":" class="statistics-form">
<el-form-item label="实验名称">{{ item.name }}</el-form-item>
<el-form-item label="班级人数">{{ item.classes.map(item => item.student_total).join(',') }}</el-form-item>
<el-form-item label="使用人数">{{ item.current_use_user_count }}</el-form-item>
</el-form>
<template #reference>
<li>
<h6>
<span>Top{{ index + 1 }}</span>
</h6>
<p>{{ item.name }}</p>
</li>
</template>
</el-popover>
</template>
</ul>
<h2 class="h2-title">实验列表</h2>
<AppList border v-bind="listOptions" ref="appList">
<template #table-x="{ row }">
<el-button type="primary"><a :href="`${dmlURL}?experiment_id=${row.id}`" target="_blank">查看</a></el-button>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.statistics {
display: flex;
align-items: center;
justify-content: space-evenly;
margin: 90px 0;
li {
width: 212px;
height: 212px;
background-color: rgba(247, 247, 247, 1);
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
h6 {
color: rgba(178, 15, 60, 1);
span {
font-size: 18px;
}
}
p {
margin-top: 20px;
font-size: 18px;
color: rgba(96, 96, 96, 1);
text-align: center;
}
}
}
.statistics-form {
:deep(.el-form-item) {
margin-bottom: 0;
}
:deep(.el-form-item__content) {
font-size: 18px;
color: var(--main-color);
}
}
.h2-title {
padding-left: 5px;
font-size: 18px;
font-weight: 500;
line-height: 1;
margin: 20px 0;
border-left: 3px solid #aa1941;
}
</style>
<script setup lang="ts">
import AppList from '@/components/base/AppList.vue'
import { getExperimentList } from '../api'
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
const appList = ref<InstanceType<typeof AppList> | null>(null)
const list = ref([])
async function fetchInfo() {
const res = await getExperimentList()
list.value = res.data.items
}
let timer: null | number = null
onMounted(() => {
fetchInfo()
timer = setInterval(() => {
fetchInfo()
}, 5000)
})
onUnmounted(() => {
timer && clearInterval(timer)
})
const dmlURL = computed(() => {
return appConfig.dmlURL || import.meta.env.VITE_DML_URL
})
// 实验列表
const listOptions = computed(() => {
return {
data: list.value,
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '所属机构', prop: 'org.department_name' },
{ label: '实验课程名称', prop: 'course_name' },
{ label: '实验名称', prop: 'name' },
{
label: '指导老师',
prop: 'teachers',
computed({ row }) {
return row.teachers.map(item => item.name).join(',')
}
},
{
label: '班级名称',
prop: 'student.specialty_name',
computed({ row }) {
return row.classes.map(item => item.name).join(',')
}
},
{
label: '班级人数',
prop: 'student.class_name',
computed({ row }) {
return row.classes.map(item => item.student_total).join(',')
}
},
{ label: '正在使用人数', prop: 'current_use_user_count' },
{ label: '用户数据量', prop: 'current_member_count' },
{ label: '标签数据量', prop: 'current_tag_count' },
{ label: '群组数据量', prop: 'current_group_count' },
{ label: '实验使用时间', prop: 'time' },
{ label: '操作', slots: 'table-x' }
]
}
})
</script>
<template>
<AppCard>
<ul class="statistics">
<template v-for="(item, index) in list" :key="item.id">
<el-popover :width="340" trigger="hover" v-if="index < 5">
<el-form label-suffix=":" class="statistics-form">
<el-form-item label="实验名称">{{ item.name }}</el-form-item>
<el-form-item label="班级人数">{{ item.classes.map(item => item.student_total).join(',') }}</el-form-item>
<el-form-item label="正在使用人数">{{ item.current_use_user_count }}</el-form-item>
</el-form>
<template #reference>
<li>
<h6>
<span>Top{{ index + 1 }}</span>
</h6>
<p>{{ item.name }}</p>
</li>
</template>
</el-popover>
</template>
</ul>
<h2 class="h2-title">实验列表</h2>
<AppList border v-bind="listOptions" ref="appList">
<template #table-x="{ row }">
<el-button type="primary"><a :href="`${dmlURL}?experiment_id=${row.id}`" target="_blank">查看</a></el-button>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.statistics {
display: flex;
align-items: center;
justify-content: space-evenly;
margin: 90px 0;
li {
width: 212px;
height: 212px;
background-color: rgba(247, 247, 247, 1);
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
h6 {
color: rgba(178, 15, 60, 1);
span {
font-size: 18px;
}
}
p {
margin-top: 20px;
font-size: 18px;
color: rgba(96, 96, 96, 1);
text-align: center;
}
}
}
.statistics-form {
:deep(.el-form-item) {
margin-bottom: 0;
}
:deep(.el-form-item__content) {
font-size: 18px;
color: var(--main-color);
}
}
.h2-title {
padding-left: 5px;
font-size: 18px;
font-weight: 500;
line-height: 1;
margin: 20px 0;
border-left: 3px solid #aa1941;
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/admin/lab/dashboard',
component: AppLayout,
children: [{ path: '', component: () => import('./views/Index.vue') }]
}
]
<script setup lang="ts">
import Live from '../components/Live.vue'
import History from '../components/History.vue'
const activeRadio = ref('1')
</script>
<template>
<el-radio-group v-model="activeRadio" style="margin-bottom: 10px">
<el-radio-button label="1">实时监控</el-radio-button>
<el-radio-button label="2">历史监控</el-radio-button>
</el-radio-group>
<Live v-if="activeRadio === '1'"></Live>
<History v-else></History>
</template>
...@@ -29,7 +29,8 @@ const adminMenus: IMenuItem[] = [ ...@@ -29,7 +29,8 @@ const adminMenus: IMenuItem[] = [
{ name: '实验指导书管理', path: '/admin/lab/book', tag: 'v1-teacher-book' }, { name: '实验指导书管理', path: '/admin/lab/book', tag: 'v1-teacher-book' },
{ name: '实验操作视频管理', path: '/admin/lab/video', tag: 'v1-teacher-video' }, { name: '实验操作视频管理', path: '/admin/lab/video', tag: 'v1-teacher-video' },
{ name: '实验讨论交流', path: '/admin/lab/discuss', tag: 'v1-teacher-discussion' }, { name: '实验讨论交流', path: '/admin/lab/discuss', tag: 'v1-teacher-discussion' },
{ name: '实验成绩管理', path: '/admin/lab/score', tag: 'v1-teacher-record' } { name: '实验成绩管理', path: '/admin/lab/score', tag: 'v1-teacher-record' },
{ name: '实验监控', path: '/admin/lab/dashboard' }
] ]
}, },
{ {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论