460 lines
13 KiB
Vue
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>
|