2025-08-07 17:44:13 +08:00

213 lines
5.5 KiB
Vue

<template>
<!-- 视频学习统计 -->
<view class="single_box video_learning">
<view class="title">视频学习统计</view>
<isp-data-load :loading="loading" :empty="empty" emptyText="暂无数据">
<view class="date_filter_box">
<DateFilter :dateType="dateType" @filter="i => handleFilterDate(i)" />
</view>
<view class="study_situation2">
<view class="item">
<text class="item_label">已学视频</text>
<view
:class="{
item_date: true,
up: showData.videoCount > showData.videoCountRatio,
down: showData.videoCount < showData.videoCountRatio,
keep: showData.videoCount === showData.videoCountRatio,
}"
>{{ showData?.videoCount }} <text style="color: #333">&nbsp;</text
><image
class="trend_icon"
:src="
showData.videoCount > showData.videoCountRatio
? `${OSS_URL}/iconfont/learning_progress_${1}.png`
: showData.videoCount === showData.videoCountRatio
? `${OSS_URL}/iconfont/learning_progress_${2}.png`
: `${OSS_URL}/iconfont/learning_progress_${3}.png`
"
/></view>
</view>
<view class="item">
<text class="item_label">观看视频时长</text>
<view
:class="{
item_date: true,
up: showData.videoTime > showData.videoTimeRatio,
down: showData.videoTime < showData.videoTimeRatio,
keep: showData.videoTime === showData.videoTimeRatio,
}"
>
{{ timeTool(showData.videoTime) }}<text style="color: #333">&nbsp;&nbsp;</text>
{{ timeTool(showData.videoTime, true) }}<text style="color: #333">&nbsp;&nbsp;</text>
<image
class="trend_icon"
:src="
showData.videoTime > showData.videoTimeRatio
? `${OSS_URL}/iconfont/learning_progress_${1}.png`
: showData.videoTime === showData.videoTimeRatio
? `${OSS_URL}/iconfont/learning_progress_${2}.png`
: `${OSS_URL}/iconfont/learning_progress_${3}.png`
"
/>
</view>
</view>
</view>
<template v-if="dateType !== 0">
<view class="title2">观看视频时长</view>
<view class="charts_box">
<qiun-data-charts
type="line"
canvas2d
:opts="opts"
:chartData="videoLearning"
tooltip-format="videoTooltipFormat"
ontouch
/>
</view>
</template>
</isp-data-load>
</view>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from 'vue'
import DateFilter from './dateFilter.vue'
import '../index.scss'
import { videoStudyStatApi } from '@/api'
import dayjs from 'dayjs'
const props = withDefaults(
defineProps<{
subjectId: number | string
userId: string
}>(),
{
subjectId: 0,
userId: '',
},
)
const emits = defineEmits(['change'])
const OSS_URL = import.meta.env.VITE_OSS_HOST
const empty = ref(false)
const dateType = ref(0)
const loading = ref(false)
const opts = ref({
padding: [15, 20, 0, 15],
enableScroll: false,
dataLabel: false,
dataPointShape: false,
legend: { position: 'top', padding: 2 },
xAxis: {
disableGrid: true,
labelCount: 3, // 标签数
format: 'xAixsHoursMin',
},
yAxis: {
gridType: 'dash',
dashLength: 2,
},
extra: {
line: {
type: 'curve',
width: 2,
activeType: 'none',
},
tooltip: {
bgColor: '#21D17A',
fontColor: '#fff',
bgOpacity: 1,
borderRadius: 8,
gridColor: '#21D17A',
labelFontColor: '#333',
legendShow: false,
borderOpacity: 1,
labelBgOpacity: 1,
},
},
})
const showData = ref({
videoCount: '',
videoCountRatio: '',
videoTime: '',
videoTimeRatio: '',
videoRecordVoList: [
{
studyDate: '',
videoCount: '0',
videoTime: '0',
},
],
})
const videoLearning = ref({
categories: [],
series: [
{
name: '时长统计',
data: [],
color: '#9789ff',
},
],
})
async function fetchChartData() {
if (props.subjectId === 0) {
empty.value = true
return
}
empty.value = false
try {
loading.value = true
const data = await videoStudyStatApi({
dateType: dateType.value,
subjectId: props.subjectId,
userId: props.userId,
})
showData.value = data
videoLearning.value.categories = []
let chartData = []
for (let i in data.videoRecordVoList) {
videoLearning.value.categories[i] = dayjs(data.videoRecordVoList[i].studyDate).format(
'YYYY/MM/DD',
)
chartData[i] = data.videoRecordVoList[i].videoTime
}
videoLearning.value.series[0].data = chartData
} finally {
loading.value = false
}
}
async function handleFilterDate(i) {
dateType.value = i.value
fetchChartData()
}
function timeTool(second: string | number, isminute = false) {
const seconds = Number(second)
let h: number | string = Math.floor(seconds / 3600)
let m: number | string = Math.floor((seconds % 3600) / 60)
// 补零
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
return isminute ? m : h
}
watch(
() => props.subjectId,
val => {
dateType.value = 0
fetchChartData()
},
)
</script>
<style lang="scss" scoped>
.title2 {
margin-bottom: -20rpx !important;
}
.charts_box {
height: 420rpx;
width: 100%;
}
</style>