|
|
@@ -0,0 +1,525 @@
|
|
|
+<template>
|
|
|
+ <div class="box">
|
|
|
+ <div class="box_title">课程情况</div>
|
|
|
+
|
|
|
+ <!-- 课程情况信息区域 -->
|
|
|
+ <div class="box_info">
|
|
|
+ <div class="info_detail">
|
|
|
+ <div class="detail_title">课程名称</div>
|
|
|
+ <div class="detail_msg">Android开发基础</div>
|
|
|
+ <div class="detail_tip">第五章第三小节</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info_detail">
|
|
|
+ <div class="detail_title">授课老师</div>
|
|
|
+ <div class="detail_msg">张志华</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info_detail">
|
|
|
+ <div class="detail_title">上课班级</div>
|
|
|
+ <div class="detail_msg">计科2020</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info_detail">
|
|
|
+ <div class="detail_title">上课人数</div>
|
|
|
+ <div class="detail_msg" ref="peopleDom">{{ people }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 考勤统计区域 -->
|
|
|
+ <div class="stat">
|
|
|
+ <div class="stat_title">
|
|
|
+ <img src="@/assets/images/title-icon.png" />
|
|
|
+ <img class="icon" src="@/assets/images/title-icon2.png" />
|
|
|
+ 考勤统计
|
|
|
+ <span>(本节)</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="stat_chart" ref="statChart"></div>
|
|
|
+ <div class="chart_tip left">
|
|
|
+ <img class="icon" src="@/assets/images/on.png" />
|
|
|
+ 已到
|
|
|
+ <span ref="arrivedNumDom">{{ arrivedNum }} </span>
|
|
|
+ 人
|
|
|
+ </div>
|
|
|
+ <div class="chart_tip right">
|
|
|
+ <img class="icon" src="@/assets/images/off.png" />
|
|
|
+ 缺席
|
|
|
+ <span ref="absenceNumDom">{{ absenceNum }}</span>
|
|
|
+ 人
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 互动次数统计区域 -->
|
|
|
+ <div class="interact">
|
|
|
+ <div class="interact_title">
|
|
|
+ <img src="@/assets/images/title-icon.png" />
|
|
|
+ <img class="icon" src="@/assets/images/title-icon2.png" />
|
|
|
+ 互动次数统计
|
|
|
+ <span>(本节)</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="interact_chart" ref="interactChart"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 课件预习统计区域 -->
|
|
|
+ <div class="preview">
|
|
|
+ <div class="preview_title">
|
|
|
+ <img src="@/assets/images/title-icon.png" />
|
|
|
+ <img class="icon" src="@/assets/images/title-icon2.png" />
|
|
|
+ 课件预习统计
|
|
|
+ <span>(本节)</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="preview_chart" ref="previewChart"></div>
|
|
|
+ <div class="chart_tip2 left">已预习 28人</div>
|
|
|
+ <div class="chart_tip2 right">未预习 28人</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import * as Echarts from 'echarts'
|
|
|
+import { countUpNum } from '@/utils/countUpNum.js'
|
|
|
+
|
|
|
+// 上课人数
|
|
|
+const people = ref(56)
|
|
|
+const peopleDom = ref()
|
|
|
+
|
|
|
+// 考勤统计已到人数
|
|
|
+const arrivedNum = ref(54)
|
|
|
+const arrivedNumDom = ref()
|
|
|
+// 考勤统计缺席人数
|
|
|
+const absenceNum = ref(2)
|
|
|
+const absenceNumDom = ref()
|
|
|
+
|
|
|
+// 考勤率
|
|
|
+const salaryPCT = ref((arrivedNum.value / (arrivedNum.value + absenceNum.value)).toFixed(2) * 100)
|
|
|
+
|
|
|
+// 考勤统计图表实例
|
|
|
+let myStatChart
|
|
|
+// 考勤统计图表DOM
|
|
|
+const statChart = ref(null)
|
|
|
+
|
|
|
+// 互动次数统计图表实例
|
|
|
+let myInteractChart
|
|
|
+// 互动次数统计图表DOM
|
|
|
+const interactChart = ref(null)
|
|
|
+
|
|
|
+// 课件预习统计图表实例
|
|
|
+let myPreviewChart
|
|
|
+// 课件预习统计图表Dom
|
|
|
+const previewChart = ref(null)
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ countUpNum(peopleDom.value, people.value)
|
|
|
+ countUpNum(arrivedNumDom.value, arrivedNum.value)
|
|
|
+ countUpNum(absenceNumDom.value, absenceNum.value)
|
|
|
+
|
|
|
+ myStatChart = Echarts.init(statChart.value)
|
|
|
+ initStatChart()
|
|
|
+
|
|
|
+ myInteractChart = Echarts.init(interactChart.value)
|
|
|
+ initInteractChart()
|
|
|
+
|
|
|
+ myPreviewChart = Echarts.init(previewChart.value)
|
|
|
+ initPreviewChart()
|
|
|
+})
|
|
|
+
|
|
|
+// 初始化考勤统计图表
|
|
|
+const initStatChart = () => {
|
|
|
+ const options = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item'
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ text: '考勤率',
|
|
|
+ left: '40%',
|
|
|
+ top: '36%',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#fff'
|
|
|
+ },
|
|
|
+ subtext: '{a|' + salaryPCT.value + '%}',
|
|
|
+ subtextStyle: {
|
|
|
+ color: '#28E3E4',
|
|
|
+ rich: {
|
|
|
+ a: {
|
|
|
+ fontSize: 20,
|
|
|
+ padding: [0, 0, 0, -2]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ textVerticalAlign: 'top',
|
|
|
+ itemGap: 10
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['55%', '70%'],
|
|
|
+ center: ['45%', '48%'],
|
|
|
+ startAngle: 100,
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ { value: arrivedNum.value, name: '已到' },
|
|
|
+ { value: absenceNum.value, name: '缺席' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ color: [
|
|
|
+ {
|
|
|
+ type: 'linear',
|
|
|
+ x: 0,
|
|
|
+ y: 1,
|
|
|
+ x2: 0,
|
|
|
+ y2: 0,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: '#13F5E5FF' // 0% 处的颜色
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: '#13F5E533' // 100% 处的颜色
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ '#293F47'
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ myStatChart.setOption(options)
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化互动次数统计图表
|
|
|
+const initInteractChart = () => {
|
|
|
+ const options = {
|
|
|
+ title: {
|
|
|
+ text: 18,
|
|
|
+ left: '33%',
|
|
|
+ top: 'center',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 24,
|
|
|
+ color: '#99FFFF'
|
|
|
+ },
|
|
|
+ subtext: ' 次',
|
|
|
+ subtextStyle: {
|
|
|
+ fontSize: 14,
|
|
|
+ color: '#FFF',
|
|
|
+ align: 'center'
|
|
|
+ },
|
|
|
+ textVerticalAlign: 'top',
|
|
|
+ itemGap: 1
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item'
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ align: 'right',
|
|
|
+ orient: 'vertical',
|
|
|
+ right: '5%',
|
|
|
+ top: 'center',
|
|
|
+ icon: 'circle',
|
|
|
+ textStyle: {
|
|
|
+ color: '#fff'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ color: ['#5CDAF5', '#129BFF', '#4DD1FF', '#FFCF5F', '#4120E6', '#065DFF'],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '互动次数',
|
|
|
+ type: 'pie',
|
|
|
+ center: ['38%', '50%'],
|
|
|
+ radius: ['55%', '75%'],
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'outer',
|
|
|
+ alignTo: 'labelLine',
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 12,
|
|
|
+ lineHeight: 15,
|
|
|
+ formatter: (params) => {
|
|
|
+ return params.value + '次 ' + params.percent + '%'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ labelLayout: {
|
|
|
+ hideOverlap: false
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ { value: 5, name: '抢答' },
|
|
|
+ { value: 6, name: '提问' },
|
|
|
+ { value: 3, name: '点名' },
|
|
|
+ { value: 2, name: '讨论' },
|
|
|
+ { value: 1, name: '投票' },
|
|
|
+ { value: 5, name: '其他' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ myInteractChart.setOption(options)
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化课件预习统计图表
|
|
|
+const initPreviewChart = () => {
|
|
|
+ const options = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item'
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ text: '50%',
|
|
|
+ left: '39%',
|
|
|
+ top: '50%',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 20,
|
|
|
+ color: '#99FFFF'
|
|
|
+ },
|
|
|
+ subtext: '{a|课件预习率}',
|
|
|
+ subtextStyle: {
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#fff',
|
|
|
+ rich: {
|
|
|
+ a: {
|
|
|
+ padding: [0, 0, 0, -8]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ textVerticalAlign: 'top',
|
|
|
+ itemGap: 25
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['75%', '90%'],
|
|
|
+ center: ['45%', '75%'],
|
|
|
+ startAngle: 180,
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ { value: 28, name: '已预习' },
|
|
|
+ { value: 28, name: '未预习' },
|
|
|
+ {
|
|
|
+ value: 28 + 28,
|
|
|
+ itemStyle: {
|
|
|
+ color: 'none',
|
|
|
+ decal: {
|
|
|
+ symbol: 'none'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ color: [
|
|
|
+ {
|
|
|
+ type: 'linear',
|
|
|
+ x: 0,
|
|
|
+ y: 1,
|
|
|
+ x2: 0,
|
|
|
+ y2: 0,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: '#008CFF' // 0% 处的颜色
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: '#00FFF4' // 100% 处的颜色
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ '#113940'
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ myPreviewChart.setOption(options)
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.box {
|
|
|
+ margin-left: 27px;
|
|
|
+ width: 450px;
|
|
|
+ height: 934px;
|
|
|
+ color: #fff;
|
|
|
+ background-image: url(@/assets/images/box.png);
|
|
|
+ background-size: 100% 100%;
|
|
|
+
|
|
|
+ .box_title {
|
|
|
+ margin-top: 12px;
|
|
|
+ margin-left: 42px;
|
|
|
+ height: 55px;
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .box_info {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: space-evenly;
|
|
|
+ align-content: space-evenly;
|
|
|
+ height: 250px;
|
|
|
+
|
|
|
+ .info_detail {
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 18px;
|
|
|
+ width: 176px;
|
|
|
+ height: 96px;
|
|
|
+ background-image: url(@/assets/images/border-green.png);
|
|
|
+ background-size: 100% 100%;
|
|
|
+
|
|
|
+ .detail_title {
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail_msg {
|
|
|
+ margin: 8px 0 5px 0;
|
|
|
+ color: #70ecff;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail_tip {
|
|
|
+ color: #70ecff;
|
|
|
+ font-size: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat {
|
|
|
+ position: relative;
|
|
|
+ margin-left: 35px;
|
|
|
+ .stat_title {
|
|
|
+ height: 21px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ img {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ margin-left: -5px;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat_chart {
|
|
|
+ margin-top: 2px;
|
|
|
+ width: 415px;
|
|
|
+ height: 160px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart_tip {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ position: absolute;
|
|
|
+ top: 90px;
|
|
|
+ font-size: 12px;
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ margin-top: -1px;
|
|
|
+ margin-right: 8px;
|
|
|
+ width: 17px;
|
|
|
+ height: 17px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .left {
|
|
|
+ left: 35px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .right {
|
|
|
+ left: 275px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .interact {
|
|
|
+ margin-left: 35px;
|
|
|
+ .interact_title {
|
|
|
+ height: 21px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ img {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ margin-left: -5px;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .interact_chart {
|
|
|
+ margin: 22px 0 30px 0;
|
|
|
+ width: 415px;
|
|
|
+ height: 150px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .preview {
|
|
|
+ position: relative;
|
|
|
+ margin-left: 35px;
|
|
|
+ .preview_title {
|
|
|
+ height: 21px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ img {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ margin-left: -5px;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .preview_chart {
|
|
|
+ margin-top: 2px;
|
|
|
+ width: 415px;
|
|
|
+ height: 179px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart_tip2 {
|
|
|
+ position: absolute;
|
|
|
+ top: 100px;
|
|
|
+ left: 15px;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .left {
|
|
|
+ left: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .right {
|
|
|
+ left: 290px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|