feat:教师咨询数据统计模块
This commit is contained in:
parent
0b1dbf4d39
commit
cf671344a7
|
@ -27,7 +27,7 @@ const props = withDefaults(
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
$item-title-height: 33px;
|
$item-title-height: 33px;
|
||||||
$item_title_content-height: calc(100% - 33px);
|
$item_title_content-height: calc(100% - 33px - 20px);
|
||||||
|
|
||||||
.item_wrap {
|
.item_wrap {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
|
@ -2,16 +2,23 @@
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import { teacherConsultStats } from "@/api";
|
import { teacherConsultStats } from "@/api";
|
||||||
|
|
||||||
|
interface TeacherStats {
|
||||||
|
consultCount: number;
|
||||||
|
replyCount: number;
|
||||||
|
messageCount: number;
|
||||||
|
[key: string]: number; // 添加索引签名
|
||||||
|
}
|
||||||
|
|
||||||
// 教师咨询数据
|
// 教师咨询数据
|
||||||
const teacherStats = ref({
|
const teacherStats = ref<TeacherStats>({
|
||||||
consultCount: 0,
|
consultCount: 0,
|
||||||
replyCount: 0,
|
replyCount: 0,
|
||||||
messageCount: 0
|
messageCount: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取教师咨询数据
|
// 获取教师咨询数据
|
||||||
const getTeacherStats = () => {
|
const getTeacherStats = () => {
|
||||||
teacherConsultStats().then(res => {
|
teacherConsultStats().then((res) => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
teacherStats.value = res.data;
|
teacherStats.value = res.data;
|
||||||
}
|
}
|
||||||
|
@ -25,31 +32,33 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="stats-container">
|
<div class="stats-container">
|
||||||
<div class="stat-item">
|
<div class="stat-item blue-card">
|
||||||
<div class="stat-icon blue-bg">
|
<div class="stat-icon">
|
||||||
<img src="@/assets/img/zheke/蓝色.png" alt="咨询次数">
|
<img src="@/assets/img/zheke/ai-stats1.png" alt="咨询次数" />
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ teacherStats.consultCount }}</div>
|
|
||||||
<div class="stat-label">咨询次数</div>
|
<div class="stat-label">咨询次数</div>
|
||||||
|
<div class="stat-value">
|
||||||
|
{{ teacherStats.consultCount }}<span class="unit">次</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-item">
|
|
||||||
<div class="stat-icon orange-bg">
|
<div class="stat-item orange-card">
|
||||||
<img src="@/assets/img/zheke/橙色.png" alt="回复数">
|
<div class="stat-icon">
|
||||||
|
<img src="@/assets/img/zheke/ai-stats2.png" alt="回复数" />
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ teacherStats.replyCount }}</div>
|
|
||||||
<div class="stat-label">回复数</div>
|
<div class="stat-label">回复数</div>
|
||||||
|
<div class="stat-value">
|
||||||
|
{{ teacherStats.replyCount }}<span class="unit">次</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-item">
|
|
||||||
<div class="stat-icon cyan-bg">
|
<div class="stat-item cyan-card">
|
||||||
<img src="@/assets/img/zheke/浅蓝色.png" alt="留言数">
|
<div class="stat-icon">
|
||||||
|
<img src="@/assets/img/zheke/ai-stats4.png" alt="留言数" />
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ teacherStats.messageCount }}</div>
|
|
||||||
<div class="stat-label">留言数</div>
|
<div class="stat-label">留言数</div>
|
||||||
|
<div class="stat-value">
|
||||||
|
{{ teacherStats.messageCount }}<span class="unit">条</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -58,55 +67,62 @@ onMounted(() => {
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.stats-container {
|
.stats-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
gap: 6px;
|
||||||
gap: 20px;
|
height: 100%;
|
||||||
padding: 15px 0;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-item {
|
.stat-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex: 1;
|
||||||
width: 100%;
|
flex-direction: column;
|
||||||
margin-bottom: 10px;
|
align-items: flex-start;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 9px 0 0 14px;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
|
&.blue-card {
|
||||||
|
background-image: url("@/assets/img/zheke/蓝色.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
&.orange-card {
|
||||||
|
background-image: url("@/assets/img/zheke/橙色.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cyan-card {
|
||||||
|
background-image: url("@/assets/img/zheke/浅蓝色.png");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-icon {
|
.stat-icon {
|
||||||
width: 50px;
|
width: 40px;
|
||||||
height: 50px;
|
height: 40px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-right: 15px;
|
margin-bottom: 8px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 30px;
|
width: 100%;
|
||||||
height: 30px;
|
height: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
&.blue-bg {
|
|
||||||
background-color: rgba(75, 150, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.orange-bg {
|
|
||||||
background-color: rgba(250, 140, 22, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cyan-bg {
|
|
||||||
background-color: rgba(24, 144, 255, 0.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-info {
|
.stat-value {
|
||||||
.stat-value {
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #333;
|
color: #fff;
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
.unit {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,132 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
import { teacherConsultStats } from "@/api";
|
|
||||||
|
|
||||||
interface TeacherStats {
|
|
||||||
consultCount: number;
|
|
||||||
replyCount: number;
|
|
||||||
messageCount: number;
|
|
||||||
[key: string]: number; // 添加索引签名
|
|
||||||
}
|
|
||||||
|
|
||||||
// 教师咨询数据
|
|
||||||
const teacherStats = ref<TeacherStats>({
|
|
||||||
consultCount: 0,
|
|
||||||
replyCount: 0,
|
|
||||||
messageCount: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取教师咨询数据
|
|
||||||
const getTeacherStats = () => {
|
|
||||||
teacherConsultStats().then((res) => {
|
|
||||||
if (res.success) {
|
|
||||||
teacherStats.value = res.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getTeacherStats();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="stats-container">
|
|
||||||
<div class="stat-item blue-card">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<img src="@/assets/img/zheke/ai-stats1.png" alt="咨询次数" />
|
|
||||||
</div>
|
|
||||||
<div class="stat-label">咨询次数</div>
|
|
||||||
<div class="stat-value">
|
|
||||||
{{ teacherStats.consultCount }}<span class="unit">次</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-item orange-card">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<img src="@/assets/img/zheke/ai-stats2.png" alt="回复数" />
|
|
||||||
</div>
|
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">
|
|
||||||
{{ teacherStats.replyCount }}<span class="unit">次</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-label">回复数</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-item cyan-card">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<img src="@/assets/img/zheke/ai-stats4.png" alt="留言数" />
|
|
||||||
</div>
|
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">
|
|
||||||
{{ teacherStats.messageCount }}<span class="unit">条</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-label">留言数</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.stats-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 6px;
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-item {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 9px 0 0 14px;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
|
|
||||||
&.blue-card {
|
|
||||||
background-image: url("@/assets/img/zheke/蓝色.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
&.orange-card {
|
|
||||||
background-image: url("@/assets/img/zheke/橙色.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cyan-card {
|
|
||||||
background-image: url("@/assets/img/zheke/浅蓝色.png");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
.unit {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #fff;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -4,7 +4,7 @@ import ItemWrap from "@/components/item-wrap";
|
||||||
const ContentHeader = defineAsyncComponent(() => import("./content-header.vue"));
|
const ContentHeader = defineAsyncComponent(() => import("./content-header.vue"));
|
||||||
|
|
||||||
// 导入左侧组件
|
// 导入左侧组件
|
||||||
const LeftTop = defineAsyncComponent(() => import("./components/LeftTop.vue"));
|
const LeftTop = defineAsyncComponent(() => import("./LeftTop.vue"));
|
||||||
const LeftCenter = defineAsyncComponent(() => import("./LeftCenter.vue"));
|
const LeftCenter = defineAsyncComponent(() => import("./LeftCenter.vue"));
|
||||||
const AverageDuration = defineAsyncComponent(() => import("./average-duration.vue"));
|
const AverageDuration = defineAsyncComponent(() => import("./average-duration.vue"));
|
||||||
const LeftBottom = defineAsyncComponent(() => import("./components/LeftBottom.vue"));
|
const LeftBottom = defineAsyncComponent(() => import("./components/LeftBottom.vue"));
|
||||||
|
|
Loading…
Reference in New Issue