2025-08-23 23:45:48 +08:00

460 lines
13 KiB
Vue

<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import dayjs from 'dayjs'
import type { ChildrenType } from '@/pages/mine/interface'
import { storeToRefs } from 'pinia'
import { useBadgeStore } from '@/store/badge'
import { useChildStore } from '@/store/child'
import hud from '@/utils/hud'
import { useStudyDataStore } from '@/store/study-data'
import { secondsToHours } from '@/utils'
const childStore = useChildStore()
const { getChildren } = childStore
const { children } = storeToRefs(childStore)
const { refreshBadge } = useBadgeStore()
const { getStudentStudyData } = useStudyDataStore()
const showChild = ref<ChildrenType>() // 展示的孩子
const showChildData = ref({} as any)
const OSS_URL = import.meta.env.VITE_OSS_HOST
const arrow = `${OSS_URL}/iconfont/down_arrow.png`
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const showAllChildren = ref(false)
const checkedId = ref()
function handleShowChild(i: ChildrenType) {
checkedId.value = i.child?.id
showChild.value = i
}
const otherChildrenList = computed(() =>
children.value.filter(i => i.child?.id !== checkedId.value),
)
// 数据类型
const dataTypeSum = 1
const dataTypeWord = 2
const dataTypeSubject = 3
const dataTypeOptions = [
{
label: '综合',
value: dataTypeSum,
},
{
label: '单词句子',
value: dataTypeWord,
},
{
label: '学科',
value: dataTypeSubject,
},
]
const dataType = ref(dataTypeOptions[0].value)
// 时间类型
const timeTypeAll = 1
const timeTypeDay = 2
const timeTypeOptions = [
{
label: '总计',
value: timeTypeAll,
},
{
label: '每日',
value: timeTypeDay,
},
]
const timeType = ref(timeTypeOptions[0].value)
const timeDay = ref(dayjs().format('YYYY-MM-DD'))
const timeDayRef = ref()
// 学科
const english_subject_id = 4
const chinese_subject_id = 2
const math_subject_id = 3
const subjectOptions = [
{
label: '英语',
value: english_subject_id,
},
{
label: '数学',
value: math_subject_id,
},
{
label: '语文',
value: chinese_subject_id,
},
]
const subject = ref(subjectOptions[0].value)
watch(
[
() => dataType.value,
() => timeType.value,
() => timeDay.value,
() => subject.value,
() => checkedId.value,
],
() => {
const params = {
queryType: dataType.value,
queryRangeFlag: timeType.value,
} as any
// 每日
if (timeType.value === timeTypeDay) {
params.queryDate = timeDay.value
}
// 学科
if (dataType.value === dataTypeSubject) {
params.subjectId = subject.value
}
getStudentStudyData(params).then(map => {
showChildData.value = map[checkedId.value] || {}
})
},
{ immediate: true },
)
// 选择日期
function selectDate(val: any) {
timeDay.value = val.result
}
onShow(() => {
Promise.all([getChildren(), refreshBadge()])
.then(() => {
if (!children.value?.length) return
showChild.value = children.value[0]
checkedId.value = children.value[0].child?.id
})
.finally(() => {
hud.hide()
})
})
onMounted(() => {
hud.loading()
})
</script>
<template>
<mj-page class="container">
<view class="children-box">
<view class="children">
<view class="left">
<image
:src="showChild?.child?.avatar || defaultAvatar"
mode=""
class="children_avatar"
></image>
<view>
<view class="name_vip">
<text class="name">{{ showChild?.child?.name || '未绑定账号' }}</text>
<image
v-if="showChild?.child?.currentLevel"
:src="`${OSS_URL}/iconfont/VIP/VIP_${showChild?.child?.currentLevel}.png`"
class="vip"
/>
</view>
<view class="time">
<template v-if="showChild?.child?.vipEndTime">
有效期至:{{
showChild?.child?.vipEndTime
? dayjs(showChild?.child?.vipEndTime).format('YYYY.MM.DD')
: '-'
}}
</template>
<template v-else>请先绑定孩子账号</template>
</view>
</view>
</view>
<view v-if="children.length > 1">
<image
:class="{ icon: true, rotate: showAllChildren }"
:src="arrow"
@click="showAllChildren = !showAllChildren"
/>
</view>
</view>
<template v-if="showAllChildren">
<view
v-for="(i, idx) in otherChildrenList"
:key="idx"
class="children"
@click="handleShowChild(i)"
>
<view class="left">
<image :src="i.child?.avatar || defaultAvatar" mode="" class="children_avatar"></image>
<view>
<view class="name_vip">
<text class="name">{{ i.child?.name || '未绑定账号' }}</text>
<image
v-if="i.child?.currentLevel"
:src="`${OSS_URL}/iconfont/VIP/VIP_${i.child?.currentLevel}.png`"
class="vip"
/>
</view>
<view class="time">
有效期至:{{
i.child?.vipEndTime ? dayjs(i.child?.vipEndTime).format('YYYY.MM.DD') : '-'
}}
</view>
</view>
</view>
<image
class="icon checked_icon"
:src="
checkedId === i.child?.id
? `${OSS_URL}/iconfont/checked.png`
: `${OSS_URL}/iconfont/unchecked.png`
"
/>
</view>
</template>
<view class="children_info">
<view class="item">
乐贝:<text class="level">{{ showChild?.child?.currency || '-' }}</text>
</view>
<view class="item">
钻石:<text class="level">{{ showChild?.child?.diamond || '-' }}</text>
</view>
</view>
</view>
<view v-if="checkedId" class="study-data">
<view class="time-type-box">
<mj-segment class="time-type" v-model="timeType" :options="timeTypeOptions" />
<view class="time-type-text" v-if="timeType === timeTypeDay" @click="timeDayRef.show()">{{
timeDay
}}</view>
</view>
<mj-segment v-model="dataType" :options="dataTypeOptions" />
<mj-segment v-if="dataType === dataTypeSubject" v-model="subject" :options="subjectOptions" />
<tui-grid v-if="dataType === dataTypeSum" class="data-grid">
<tui-grid-item :cell="2">
<view class="value">{{ secondsToHours(showChildData.learnTime) }}</view>
<text class="label">有效学习时长</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.knowledgeCount || 0 }}</view>
<text class="label">知识点</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.errorCount || 0 }}</view>
<text class="label">错题</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.correctCount || 0 }}</view>
<text class="label">订正</text>
</tui-grid-item>
</tui-grid>
<tui-grid v-else-if="dataType === dataTypeWord" class="data-grid">
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.wordStrangerCount || 0 }}</view>
<text class="label">单词陌生</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.wordKnowCount || 0 }}</view>
<text class="label">单词认识</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.wordKnowWellCount || 0 }}</view>
<text class="label">单词熟悉</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.wordGraspCount || 0 }}</view>
<text class="label">单词掌握</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.wordCount || 0 }}</view>
<text class="label">单词总数</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.starCount || 0 }}</view>
<text class="label">单词闯关星星</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.sentenceCount || 0 }}</view>
<text class="label">语感训练句子</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ secondsToHours(showChildData.learnTime) }}</view>
<text class="label">有效学习时长</text>
</tui-grid-item>
</tui-grid>
<tui-grid v-else-if="dataType === dataTypeSubject" class="data-grid">
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.successTestCount || 0 }}</view>
<text class="label">答题正确</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.errorTestCount || 0 }}</view>
<text class="label">答题错误</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.allKnowledgeCount || 0 }}</view>
<text class="label">知识点总数</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.allKnowledgeGraspCount || 0 }}</view>
<text class="label">知识点掌握</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.allReviewCount || 0 }}</view>
<text class="label">订正总数</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ showChildData.successReviewCount || 0 }}</view>
<text class="label">订正正确</text>
</tui-grid-item>
<tui-grid-item :cell="2">
<view class="value">{{ secondsToHours(showChildData.learnTime) }}</view>
<text class="label">有效学习时长</text>
</tui-grid-item>
</tui-grid>
</view>
<tui-datetime ref="timeDayRef" :type="2" :setDateTime="timeDay" @confirm="selectDate" />
</mj-page>
</template>
<style scoped lang="scss">
.container {
// padding-bottom: 186rpx;
padding: 30rpx;
.study-data {
margin-top: 30rpx;
display: flex;
flex-direction: column;
gap: 30rpx;
.time-type-box {
display: flex;
align-items: center;
gap: 30rpx;
.time-type-text {
width: 36%;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #333;
height: 50rpx;
border-radius: 10rpx;
}
.time-type {
flex: 1;
}
}
.data-grid {
.value {
margin: 0 auto;
text-align: center;
vertical-align: middle;
}
.label {
display: block;
text-align: center;
font-weight: 400;
color: #333;
font-size: 28rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-top: 10rpx;
}
}
}
.children-box {
background-color: #fff;
padding: 0 30rpx 30rpx;
border-radius: 20rpx;
.children {
display: flex;
justify-content: space-between;
padding: 30rpx 0 30rpx 0;
border-bottom: 1rpx solid $border-color;
.left {
display: flex;
align-items: center;
.children_avatar {
margin-right: 20rpx;
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
.name_vip {
display: flex;
align-items: center;
margin-bottom: 6rpx;
.name {
display: inline-block;
max-width: 210rpx;
font-weight: 500;
font-size: 32rpx;
line-height: 48rpx;
color: $font-color;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.vip {
margin-left: 10rpx;
width: 85rpx;
height: 32rpx;
}
}
.time {
font-size: 24rpx;
line-height: 34rpx;
color: $font-aux-color;
}
}
.icon {
width: 30rpx;
height: 30rpx;
}
.checked_icon {
margin: auto 0;
}
.rotate {
transform: rotate(-180deg);
}
}
.children_info {
display: flex;
padding: 30rpx 0 0 0;
.item {
width: 50%;
font-size: 28rpx;
line-height: 40rpx;
color: $font-aux-color;
.level {
color: $font-color;
}
}
}
}
}
</style>