mental-health-web/src/views/index.vue

499 lines
12 KiB
Vue
Raw Normal View History

2024-03-15 03:07:18 +00:00
<template>
2024-04-28 02:34:21 +00:00
<div class="app-container">
2024-05-20 00:57:45 +00:00
<el-card>
2024-05-27 02:45:03 +00:00
<el-row justify="space-around">
2024-05-20 00:57:45 +00:00
<el-col :span="12">
<img class="avater" :src="userStore.avatar" />{{ getGreeting() }}
</el-col>
<el-col :span="12" class="screen">
<el-button round>
<router-link target="_blank" to="/bigScreen">
<el-icon>
<FullScreen />
</el-icon><span></span>
</router-link>
</el-button>
</el-col>
</el-row>
</el-card>
2024-06-06 09:02:19 +00:00
<el-row :gutter="10">
2024-05-20 00:57:45 +00:00
<el-col :span="6">
<el-card>
<el-row justify="space-between">
<el-col :span="12">
<el-icon :size="60" color="#40C9C6">
<Avatar />
</el-icon>
</el-col>
<el-col :span="12" class="right">
<el-statistic title="总用户数" :value="userNum" :value-style="{ color: '#000', fontSize: '30px' }">
<template #title>
<div class="stats-title">
总用户数
</div>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<el-row justify="space-between">
<el-col :span="12">
<el-icon :size="60" color="#36A3F7">
<Operation />
</el-icon>
</el-col>
<el-col :span="12" class="right">
<el-statistic :value="evaluationNum" :value-style="{ color: '#000', fontSize: '30px' }">
<template #title>
<div class="stats-title">
总测评数
</div>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<el-row justify="space-between">
<el-col :span="12">
<el-icon :size="60" color="#F4516C">
<Histogram />
</el-icon>
</el-col>
<el-col :span="12" class="right">
<el-statistic :value="warnNum" :value-style="{ color: '#000', fontSize: '30px' }">
<template #title>
<div class="stats-title">
总预警数
</div>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<el-row justify="space-between">
<el-col :span="12">
<el-icon :size="60" color="#34BFA3">
<HelpFilled />
</el-icon>
</el-col>
<el-col :span="12" class="right">
<el-statistic :value="interveneNum" :value-style="{ color: '#000', fontSize: '30px' }">
<template #title>
<div class="stats-title">
总干预数
</div>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
2024-06-06 09:02:19 +00:00
<el-row :gutter="10">
2024-05-20 00:57:45 +00:00
<el-col :span="10">
<el-card>
<v-chart style="height: 300px;" :option="leftPieOption" autoresize />
</el-card>
</el-col>
<el-col :span="14">
<el-card>
<v-chart style="height: 300px;" :option="centerBarOption" autoresize />
</el-card>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-card>
<v-chart style="height: 350px;" :option="rightBarOption" autoresize />
</el-card>
</el-col>
</el-row>
2024-03-15 03:07:18 +00:00
</div>
</template>
<script setup name="Index" lang="ts">
2024-05-08 09:11:11 +00:00
import { getUserNum, getEvaluationNum, getWarnNum, getInterveneNum, getWarn4All, getPublishNum, getGrade } from '@/api/index'
2024-04-30 07:51:19 +00:00
import * as echarts from 'echarts';
import { use } from 'echarts/core'
import { CanvasRenderer } from "echarts/renderers";
import { PieChart, BarChart, LineChart } from "echarts/charts";
2024-05-08 09:11:11 +00:00
import { TitleComponent, TooltipComponent, LegendComponent, ToolboxComponent, GridComponent, VisualMapComponent } from "echarts/components";
2024-04-30 07:51:19 +00:00
import VChart from 'vue-echarts'
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
use([
CanvasRenderer,
PieChart,
BarChart,
LineChart,
TitleComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
2024-05-08 09:11:11 +00:00
GridComponent,
VisualMapComponent
2024-04-30 07:51:19 +00:00
]);
2024-05-08 06:00:09 +00:00
function getGreeting() {
// 获取当前时间
let timeNow = new Date();
// 获取当前小时
let hours = timeNow.getHours();
// 设置默认文字
let state = ``;
// 判断当前时间段
if (hours >= 0 && hours <= 10) {
state = `早上好, ${userStore.nickname}`;
} else if (hours > 10 && hours <= 14) {
state = `中午好, ${userStore.nickname}`;
} else if (hours > 14 && hours <= 18) {
state = `下午好, ${userStore.nickname}`;
} else if (hours > 18 && hours <= 24) {
state = `晚上好, ${userStore.nickname}`;
}
return state;
}
2024-03-15 03:07:18 +00:00
2024-05-08 06:00:09 +00:00
const leftPieOption = ref({
2024-04-30 07:51:19 +00:00
title: {
2024-05-27 03:17:38 +00:00
text: '风险统计',
2024-05-08 06:00:09 +00:00
subtext: '严重度',
x: 'center',
y: '40%',
textStyle: {
fontSize: 20,
2024-05-23 01:58:30 +00:00
fontWeight: 'normal',
2024-05-08 06:00:09 +00:00
lineHeight: 10,
},
subtextStyle: {
fontSize: 16,
lineHeight: 10,
},
2024-04-30 07:51:19 +00:00
},
tooltip: {
2024-05-08 06:00:09 +00:00
trigger: 'item',
formatter: "{b} : {c} ({d}%)"
2024-04-30 07:51:19 +00:00
},
2024-05-08 06:00:09 +00:00
visualMap: {
show: false,
min: 500,
max: 600,
inRange: {
//colorLightness: [0, 1]
}
},
series: [{
2024-06-06 09:02:19 +00:00
name: '风险统计',
2024-05-08 06:00:09 +00:00
type: 'pie',
radius: ['50%', '70%'],
center: ['50%', '50%'],
2024-06-06 09:02:19 +00:00
color: ['#AED88F', '#91ACE0', '#FED961', '#FC7100', '#FF0000'],
2024-05-08 09:11:11 +00:00
data: [],
2024-05-08 06:00:09 +00:00
roseType: 'radius',
label: {
2024-05-27 02:45:03 +00:00
formatter: ['{c|{c}}', '{b|{b}}'].join('\n'),
rich: {
c: {
fontSize: 20,
lineHeight: 5
2024-05-08 06:00:09 +00:00
},
2024-05-27 02:45:03 +00:00
b: {
fontSize: 14,
height: 44
},
},
2024-05-08 06:00:09 +00:00
},
labelLine: {
2024-05-27 02:45:03 +00:00
lineStyle: {
color: 'rgb(98,137,169)',
},
smooth: 0.2,
length: 10,
length2: 20,
2024-05-08 06:00:09 +00:00
}
}]
})
2024-05-08 09:11:11 +00:00
async function getWarn4AllData() {
const res = await getWarn4All()
const data = [
{ name: '未见异常', value: res.data.noneNum },
{ name: '低风险', value: res.data.lowNum },
{ name: '中风险', value: res.data.middleNum },
{ name: '高风险', value: res.data.highNum },
{ name: '重大风险', value: res.data.majorNum }
]
leftPieOption.value.series[0].data = data
}
2024-05-08 06:00:09 +00:00
const centerBarOption = ref({
title: {
text: '年级统计',
x: 'right',
y: '1%',
textStyle: {
fontSize: 20,
2024-05-23 01:58:30 +00:00
fontWeight: 'normal',
2024-05-08 06:00:09 +00:00
lineHeight: 10,
}
},
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
2024-05-27 02:45:03 +00:00
data: [],
2024-05-08 06:00:09 +00:00
right: 'center',
top: 0,
itemWidth: 12,
itemHeight: 10,
// itemGap: 35
},
grid: {
left: '0',
right: '20',
bottom: '0',
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
2024-05-08 09:11:11 +00:00
data: [],
2024-05-08 06:00:09 +00:00
axisLabel: {
formatter: function (value: any) { return value.split("").join("\n"); },
2024-05-27 02:45:03 +00:00
fontSize: 14,
2024-04-30 07:51:19 +00:00
}
2024-05-08 06:00:09 +00:00
},
yAxis: {
type: 'value',
axisTick: { show: false },
splitLine: {
2024-05-20 00:57:45 +00:00
show: false,
2024-05-08 06:00:09 +00:00
lineStyle: {
color: '#95989D'
}
},
axisLabel: {
2024-05-27 02:45:03 +00:00
color: '#95989D',
fontSize: 14,
2024-05-08 06:00:09 +00:00
},
axisLine: { show: false },
},
2024-05-08 09:11:11 +00:00
series: [
2024-04-30 07:51:19 +00:00
]
})
2024-05-08 06:00:09 +00:00
2024-05-08 09:11:11 +00:00
async function getGradeData() {
const res = await getGrade()
let xAxisData: any[] = []
let seriesPublishData: any[] = []
let seriesEvaluationData: any[] = []
res.data.forEach((v: any) => {
xAxisData.push(v.name)
seriesPublishData.push(v.value)
seriesEvaluationData.push(v.spareValue)
});
const seriesData = [{ name: '发布数', data: seriesPublishData, type: 'bar' }, { name: '测评数', data: seriesEvaluationData, type: 'bar' }]
2024-05-27 02:45:03 +00:00
centerBarOption.value.legend.data = ['发布数', '测评数']
2024-05-08 09:11:11 +00:00
centerBarOption.value.xAxis.data = xAxisData
centerBarOption.value.series = seriesData
}
2024-05-08 06:00:09 +00:00
const rightBarOption = ref({
title: {
2024-05-08 09:11:11 +00:00
text: '量表使用统计',
x: 'right',
2024-05-08 06:00:09 +00:00
y: '1%',
textStyle: {
fontSize: 20,
2024-05-23 01:58:30 +00:00
fontWeight: 'normal',
2024-05-08 06:00:09 +00:00
lineHeight: 10,
}
},
2024-05-09 06:01:15 +00:00
color: ['#99E4DC'],
2024-05-08 09:11:11 +00:00
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
2024-05-08 06:00:09 +00:00
grid: {
2024-05-08 09:11:11 +00:00
left: '3%',
right: '4%',
2024-06-06 09:02:19 +00:00
bottom: '1%',
2024-05-08 06:00:09 +00:00
containLabel: true
},
2024-05-08 09:11:11 +00:00
xAxis: {
type: 'category',
2024-05-20 00:57:45 +00:00
data: [],
splitLine: {
show: false,
},
2024-06-06 09:02:19 +00:00
axisTick: {
alignWithLabel: false
},
axisLabel: {
interval: 0,
rotate: '90',
color: '#95989D',
fontSize: 14,
formatter: function (value: any) {
if (value.length > 6) {
return `${value.slice(0, 6)}...`
}
return value
}
}
},
yAxis: {
type: 'value',
axisTick: { show: false },
splitLine: {
show: false,
lineStyle: {
color: '#95989D'
}
},
axisLabel: {
color: '#95989D',
fontSize: 14,
},
axisLine: { show: false },
2024-05-08 09:11:11 +00:00
},
series: [
2024-05-08 09:21:45 +00:00
2024-05-08 09:11:11 +00:00
]
})
2024-05-08 06:00:09 +00:00
2024-05-08 09:11:11 +00:00
async function getPublishNumData() {
const res = await getPublishNum()
2024-06-06 09:02:19 +00:00
let xAxisData: any[] = []
2024-05-08 09:11:11 +00:00
let data: any[] = []
2024-06-06 09:02:19 +00:00
const newArr = [...res.data.map((item: any) => item.value)]
let one: number = Math.max(...newArr);
let two: number = Math.max(...newArr.filter(item => item !== one));
let three: number = Math.max(...newArr.filter(item => item !== one && item !== two));
2024-05-08 09:11:11 +00:00
res.data.forEach((v: any) => {
2024-06-06 09:02:19 +00:00
xAxisData.push(v.name)
if (v.value == one) {
data.push({ value: v.value, itemStyle: { color: '#FFEDA8' } })
} else if (v.value == two) {
data.push({ value: v.value, itemStyle: { color: '#CDCDCD' } })
} else if (v.value == three) {
data.push({ value: v.value, itemStyle: { color: '#FF9F57' } })
} else {
data.push({ value: v.value, itemStyle: { color: '#99E4DC' } })
}
2024-05-08 09:11:11 +00:00
});
const seriesData = [{ name: '量表使用次数', data: data, type: 'bar' }]
2024-06-06 09:02:19 +00:00
rightBarOption.value.xAxis.data = xAxisData
2024-05-08 09:11:11 +00:00
rightBarOption.value.series = seriesData
}
2024-05-08 06:00:09 +00:00
2024-05-21 06:50:01 +00:00
function initChart() {
getPublishNumData()
getWarn4AllData()
getGradeData()
}
2024-05-08 09:11:11 +00:00
const userNum = ref(0)
async function getUserNumData() {
const res = await getUserNum()
userNum.value = res.data
}
const evaluationNum = ref(0)
async function getEvaluationNumData() {
const res = await getEvaluationNum()
evaluationNum.value = res.data
}
const warnNum = ref(0)
async function getWarnNumData() {
const res = await getWarnNum()
warnNum.value = res.data
}
const interveneNum = ref(0)
async function getInterveneNumData() {
const res = await getInterveneNum()
interveneNum.value = res.data
}
onMounted(() => {
getUserNumData()
getEvaluationNumData()
getWarnNumData()
getInterveneNumData()
2024-05-21 06:50:01 +00:00
initChart()
})
2024-05-08 06:00:09 +00:00
2024-05-27 07:53:00 +00:00
2024-05-08 06:00:09 +00:00
// import { initWebSocket } from '@/utils/websocket';
// onMounted(() => {
// let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'
// initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + "/resource/websocket");
// });
2024-03-15 03:07:18 +00:00
</script>
<style scoped lang="scss">
2024-04-28 02:34:21 +00:00
.app-container {
2024-05-20 00:57:45 +00:00
padding: 10px;
2024-04-30 07:51:19 +00:00
2024-05-20 00:57:45 +00:00
.el-card {
margin-bottom: 5px;
2024-04-30 07:51:19 +00:00
}
2024-05-20 00:57:45 +00:00
.avater {
height: 80px;
border-radius: 50%;
margin-right: 20px;
vertical-align: middle;
2024-04-30 07:51:19 +00:00
}
2024-05-20 00:57:45 +00:00
.screen {
line-height: 80px;
text-align: right;
}
2024-04-30 07:51:19 +00:00
2024-05-20 00:57:45 +00:00
.stats-title {
font-size: 18px;
padding-bottom: 10px;
}
2024-04-30 07:51:19 +00:00
2024-05-20 00:57:45 +00:00
.right {
text-align: right;
2024-04-30 07:51:19 +00:00
}
2024-03-15 03:07:18 +00:00
}
</style>