300 lines
7.5 KiB
Vue
300 lines
7.5 KiB
Vue
<template>
|
||
<view class="item">
|
||
<view class="details_div">
|
||
<view class="img_div">
|
||
<image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview>
|
||
</view>
|
||
<view class="right_div">
|
||
<view class="title ellipsis-text">
|
||
{{ item.crsName }}
|
||
</view>
|
||
<view class="prompt_div">
|
||
<view class="prompt_div_left">
|
||
<view class="top">{{ secondsToHours(item.stdyTm) }}h</view>
|
||
<view class="bottom">学习时长</view>
|
||
</view>
|
||
<view class="prompt_div_line"></view>
|
||
<view class="prompt_div_right" @click="show_list_click">
|
||
<view class="click_text">
|
||
{{ item.stdyCnt || 0 }}
|
||
<uv-icon
|
||
class="click_text_icon"
|
||
:class="{ click_text_icon_action: show_list_state }"
|
||
name="arrow-right"
|
||
color="#0066FF"
|
||
size="12"
|
||
:bold="true"
|
||
></uv-icon>
|
||
</view>
|
||
<view class="bottom">学习记录</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="list_div" :style="{ height: list_div_height }">
|
||
<view class="list_item" v-for="item_list in data_list" @click="click_list_item(item_list)">
|
||
<view class="list_content">
|
||
<view class="list_small_item">
|
||
<image src="@/static/images/courseRecord/time.png" class="icon_img"></image>
|
||
<view class="prompt">学习时间:{{ item_list.startTm }}</view>
|
||
</view>
|
||
<view class="list_small_item">
|
||
<image src="@/static/images/courseRecord/duration.png" class="icon_img"></image>
|
||
<view class="prompt">学习时长:{{ formatDuration(item_list.startTm, item_list.endTm) }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="fl1"></view>
|
||
<uv-icon name="arrow-right" color="#979797" size="17" :bold="true"></uv-icon>
|
||
</view>
|
||
<uv-load-more
|
||
v-if="status === 'loading'"
|
||
:status="status"
|
||
loadmore-text="轻轻上拉加载"
|
||
:height="30"
|
||
></uv-load-more>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, ref, reactive } from 'vue';
|
||
import common from '@/common/common';
|
||
import { queryStdyBatchByCrsId } from '@/api/courseRecord.js';
|
||
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||
const props = defineProps({
|
||
item: {
|
||
type: Object,
|
||
default: () => {}
|
||
}
|
||
});
|
||
const item = computed(() => props.item);
|
||
const data_list = reactive([]);
|
||
const total = ref(-1);
|
||
const show_list_state = ref(false);
|
||
const list_div_height = computed(() => {
|
||
if (!show_list_state.value) {
|
||
return '0';
|
||
} else if (status.value === 'loading') {
|
||
return '100rpx';
|
||
} else {
|
||
return data_list.length * 136 + 'rpx';
|
||
}
|
||
});
|
||
const secondsToHours = (seconds) => {
|
||
if (typeof seconds === 'number') {
|
||
// 转换为小时并保留一位小数
|
||
return (seconds / 3600).toFixed(1);
|
||
}
|
||
return '0.0';
|
||
};
|
||
// 点击获取详情
|
||
const show_list_click = () => {
|
||
show_list_state.value = !show_list_state.value;
|
||
if (total.value === -1) {
|
||
//加载数据
|
||
status.value = 'loading';
|
||
data_list.length = 0;
|
||
queryStdyBatchByCrsId({ crsId: item.value.crsId }).then((res) => {
|
||
data_list.push(...res.body);
|
||
total.value = data_list.length;
|
||
status.value = 'loadmore';
|
||
});
|
||
}
|
||
};
|
||
// 跳转到详情
|
||
const click_list_item = (list_item) => {
|
||
common.navigateTo(
|
||
`/pages/courseRecord/courseStudyRecordDetail?stdyId=${list_item.stdyBatch}&crsName=${item.value.crsName || ''}`
|
||
);
|
||
};
|
||
|
||
// 计算两个标准时间的时间差值
|
||
const formatDuration = (startTm, endTm) => {
|
||
// 解析时间字符串为时间戳(毫秒)
|
||
const startTime = new Date(startTm).getTime();
|
||
const endTime = new Date(endTm).getTime();
|
||
|
||
// 计算时间差(秒),确保为正数
|
||
const seconds = Math.abs(Math.floor((endTime - startTime) / 1000));
|
||
|
||
// 计算时、分、秒
|
||
const hours = Math.floor(seconds / 3600);
|
||
const minutes = Math.floor((seconds % 3600) / 60);
|
||
const remainingSeconds = seconds % 60;
|
||
|
||
// 补零格式化函数(统一处理所有单位)
|
||
const formatNumber = (num) => num.toString().padStart(2, '0');
|
||
|
||
// 小时、分钟、秒均保持两位数格式
|
||
return `${formatNumber(hours)}:${formatNumber(minutes)}:${formatNumber(remainingSeconds)}`;
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.icon_img {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
}
|
||
|
||
.list_div {
|
||
overflow: hidden; /* 确保内容不会溢出容器 */
|
||
transition: height 0.3s ease-out; /* 高度动画 */
|
||
.list_item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 18rpx 32rpx 18rpx 28rpx;
|
||
background-color: #f9fbff;
|
||
border-radius: 8rpx;
|
||
margin: 20rpx 0 0 0;
|
||
.list_content {
|
||
.list_small_item {
|
||
display: flex;
|
||
align-items: center;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
|
||
.prompt {
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.item {
|
||
margin: 17rpx 20rpx;
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 32rpx 22rpx;
|
||
.details_div {
|
||
display: flex;
|
||
|
||
.img_div {
|
||
position: relative;
|
||
width: 226rpx;
|
||
height: 168rpx;
|
||
overflow: hidden;
|
||
border-radius: 22rpx;
|
||
|
||
.img {
|
||
width: 226rpx;
|
||
height: 168rpx;
|
||
}
|
||
|
||
.subscript {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 0;
|
||
width: 92rpx;
|
||
height: 46rpx;
|
||
border-radius: 0px 0px 0px 22rpx;
|
||
font-family: PingFangSC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
line-height: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
}
|
||
|
||
.right_div {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
margin-left: 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.title {
|
||
font-family: PingFangSC;
|
||
color: #333333;
|
||
text-align: left;
|
||
font-style: normal;
|
||
font-weight: 600;
|
||
font-size: 28rpx; /* 字体大小30rpx */
|
||
overflow: hidden; /* 超出部分隐藏 */
|
||
margin-bottom: 8rpx;
|
||
min-height: 40rpx;
|
||
}
|
||
|
||
.prompt_div {
|
||
font-family: PingFangSC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
color: #666;
|
||
line-height: 34rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
overflow: hidden;
|
||
height: 116rpx;
|
||
background-color: #f9fbff;
|
||
border-radius: 8rpx;
|
||
justify-content: space-around;
|
||
.prompt_div_line {
|
||
width: 4rpx;
|
||
height: 30rpx;
|
||
background: linear-gradient(
|
||
to bottom,
|
||
RGBA(242, 244, 248, 1) 0%,
|
||
RGBA(230, 232, 238, 1) 30%,
|
||
RGBA(230, 232, 238, 1) 70%,
|
||
RGBA(242, 244, 248, 1) 100%
|
||
);
|
||
}
|
||
.prompt_div_left,
|
||
.prompt_div_right {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
.top,
|
||
.click_text {
|
||
font-family: Arial;
|
||
font-weight: 700;
|
||
font-size: 30rpx;
|
||
color: #333333;
|
||
line-height: 34rpx;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
.bottom {
|
||
}
|
||
.click_text {
|
||
position: relative;
|
||
.click_text_icon {
|
||
position: absolute;
|
||
margin-left: 18rpx;
|
||
top: calc(50% - 12rpx);
|
||
left: calc(100% - 14rpx);
|
||
/* 添加过渡动画,包含延迟效果 */
|
||
transition: transform 0.2s ease;
|
||
}
|
||
.click_text_icon_action {
|
||
transform: rotate(90deg);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.people_progress_div {
|
||
display: flex;
|
||
font-family: PingFangSC;
|
||
font-weight: 400;
|
||
font-size: 23rpx;
|
||
color: #666;
|
||
margin-bottom: 23rpx;
|
||
|
||
line-height: 23rpx;
|
||
flex-wrap: nowrap;
|
||
height: 23rpx;
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|