重构(学习页): 前端仅展示并修复运行稳定性问题
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
<!-- src/views/StudyTimer.vue -->
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
import { useTimer } from '@/components/composables/useTimer';
|
||||
import { continueSession, pauseSession, endSession, startOrContinueStudySession } from '@/api/studySessions';
|
||||
import { useStudyFragment } from '@/components/composables/fragment';
|
||||
import {routes} from "vue-router/auto-routes";
|
||||
import router from "@/router";
|
||||
|
||||
const {
|
||||
@@ -49,27 +48,6 @@ const {
|
||||
requestAudioPermission
|
||||
} = useTimer();
|
||||
|
||||
const globalTimer = ref(Date.now());
|
||||
|
||||
const currentCycle = computed(() =>
|
||||
Math.floor(taskInfo.value.effectiveTime / 60 / 25) + 1
|
||||
);
|
||||
|
||||
const elapsedTime = computed(() => {
|
||||
if (!taskInfo.value.startTime || !timerRunning.value) return { hours: 0, minutes: 0, seconds: 0 };
|
||||
const start = new Date(taskInfo.value.startTime).getTime();
|
||||
const now = globalTimer.value;
|
||||
const diff = Math.max(Math.floor((now - start) / 1000), 0);
|
||||
return {
|
||||
hours: Math.floor(diff / 3600),
|
||||
minutes: Math.floor((diff % 3600) / 60),
|
||||
seconds: diff % 60,
|
||||
};
|
||||
});
|
||||
|
||||
const formatTime = (t: { hours: number; minutes: number; seconds: number }) =>
|
||||
`${t.hours}时${t.minutes}分${t.seconds}秒`;
|
||||
|
||||
const progress = computed(() =>
|
||||
((timerMinutes.value * 60 + timerSeconds.value) / (25 * 60)) * 100
|
||||
);
|
||||
@@ -152,24 +130,33 @@ const initPage = async () => {
|
||||
}
|
||||
}
|
||||
await loadTaskSession();
|
||||
|
||||
setInterval(() => {
|
||||
globalTimer.value = Date.now();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initPage();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clear();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="task-container">
|
||||
<el-alert
|
||||
v-if="taskInfo.systemMessage"
|
||||
:title="taskInfo.systemMessage"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
class="session-alert"
|
||||
/>
|
||||
<div class="task-info">
|
||||
<p>当前任务【{{ taskInfo.taskName }}】</p>
|
||||
<p>当前循环:{{ currentCycle }}</p>
|
||||
<p>有效时间:{{ taskInfo.effectiveTime / 60 }}分钟</p>
|
||||
<p>本次运行时间:{{ formatTime(elapsedTime) }}</p>
|
||||
<p>会话状态:{{ taskInfo.sessionState }}</p>
|
||||
<p>实际用时:{{ taskInfo.actualTime }}</p>
|
||||
<p>有效学习时长:{{ taskInfo.effectiveTime }}</p>
|
||||
<p>有效时间比:{{ taskInfo.effectivenessRatio }}</p>
|
||||
</div>
|
||||
<div class="timer-section">
|
||||
<el-progress type="circle" :percentage="progress" :width="200">
|
||||
@@ -225,6 +212,10 @@ onMounted(() => {
|
||||
justify-content: center;
|
||||
margin: 20px;
|
||||
}
|
||||
.session-alert {
|
||||
margin-bottom: 16px;
|
||||
max-width: 500px;
|
||||
}
|
||||
.task-info {
|
||||
font-size: 18px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
+26
-11
@@ -15,8 +15,9 @@ const fetchTasks = () => {
|
||||
tasks.splice(0, tasks.length, ...res.data.records.map((record: any) => ({
|
||||
title: record.taskName,
|
||||
description: record.taskDescription || '',
|
||||
materialURL: record.materialURL || record.materialUrl || "",
|
||||
lastLearningStatus: record.lastLearningStatus || '未开始',
|
||||
priority: Math.round(record.taskPriority),
|
||||
priority: Number.isFinite(record.taskPriority) ? Math.round(record.taskPriority) : "-",
|
||||
taskNum: record.taskNum,
|
||||
taskId: record.id,
|
||||
})));
|
||||
@@ -25,8 +26,11 @@ const fetchTasks = () => {
|
||||
};
|
||||
|
||||
const startTask = () => {
|
||||
if (!selectedTask.value) {
|
||||
ElMessage.warning("请先选择一个任务");
|
||||
return;
|
||||
}
|
||||
router.push({name:'start-task',params:{taskNum:selectedTask.value.taskNum}});
|
||||
console.log('任务已开始:', selectedTask.value);
|
||||
};
|
||||
|
||||
const addTask = () => {
|
||||
@@ -34,21 +38,28 @@ const addTask = () => {
|
||||
};
|
||||
|
||||
const changeTask = () =>{
|
||||
if (!selectedTask.value) {
|
||||
ElMessage.warning("请先选择一个任务");
|
||||
return;
|
||||
}
|
||||
router.push({name:"update-task",params:{"taskId":selectedTask.value.taskId}})
|
||||
};
|
||||
|
||||
const removeTask = () => {
|
||||
request.del(`/tasks/${selectedTask.value.taskId}`,{}).then(res=>{
|
||||
if (res.code == '200'){
|
||||
ElMessage.success(`任务${selectedTask.value.title}删除成功`)
|
||||
if (!selectedTask.value) {
|
||||
ElMessage.warning("请先选择一个任务");
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
request.del(`/tasks/${selectedTask.value.taskId}`,{}).then(res=>{
|
||||
if (res.code === 200){
|
||||
ElMessage.success(`任务${selectedTask.value.title}删除成功`)
|
||||
const index = tasks.indexOf(selectedTask.value);
|
||||
if (index > -1) {
|
||||
tasks.splice(index, 1);
|
||||
selectedTask.value = tasks[0] || null;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const selectTask = (task: any) => {
|
||||
@@ -84,12 +95,16 @@ onMounted(() => {
|
||||
<el-card class="task-card">
|
||||
<div v-if="selectedTask">
|
||||
<h3>任务描述</h3>
|
||||
<el-input type="textarea" v-model="selectedTask.description" :rows="4" />
|
||||
<el-input type="textarea" :model-value="selectedTask.description" :rows="4" readonly />
|
||||
|
||||
<h3 class="section-title">学习材料</h3>
|
||||
<el-link v-if="selectedTask.materialURL" :href="selectedTask.materialURL" type="primary" target="_blank">
|
||||
{{ selectedTask.materialURL }}
|
||||
</el-link>
|
||||
<span v-else>未填写材料地址</span>
|
||||
|
||||
<h3 class="section-title">任务优先级</h3>
|
||||
<el-radio-group v-model="selectedTask.priority">
|
||||
<el-radio-button v-for="i in 6" :label="i - 1" :key="i">{{ i - 1 }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-tag type="info">综合优先级:{{ selectedTask.priority }}</el-tag>
|
||||
|
||||
<h3 class="section-title">上次该任务学习情况</h3>
|
||||
<el-descriptions border column="1">
|
||||
|
||||
+11
-2
@@ -11,10 +11,19 @@ const axiosInstance = axios.create({
|
||||
|
||||
const handleError = (error: any) => {
|
||||
console.log(error);
|
||||
|
||||
// 业务异常由 validateResponse 负责提示,这里透传,避免被网络错误文案覆盖。
|
||||
if (error && typeof error === "object" && "code" in error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
if (error.response) {
|
||||
ElMessage.error(`请求失败,服务器返回: ${error.response.data}`);
|
||||
const backendMessage = error.response?.data?.message || JSON.stringify(error.response?.data);
|
||||
ElMessage.error(`请求失败,服务器返回: ${backendMessage}`);
|
||||
} else if (error.request) {
|
||||
ElMessage.error("请求未收到响应,请检查接口运行状态");
|
||||
} else {
|
||||
ElMessage.error(error.message || "请求失败");
|
||||
}
|
||||
throw new Error("网络不通畅,请检查您的网络连接或服务器状态");
|
||||
};
|
||||
@@ -61,7 +70,7 @@ const put = (url: string, data: any, config: any = {}) => {
|
||||
.catch(handleError);
|
||||
};
|
||||
|
||||
const del = (url: string, params: {}, config: any = {}) => {
|
||||
const del = (url: string, params: Record<string, any> = {}, config: any = {}) => {
|
||||
console.log("开始DELETE请求", basic_url + url, "参数:", params);
|
||||
return axiosInstance.delete(url, { params, ...config })
|
||||
.then(validateResponse)
|
||||
|
||||
Reference in New Issue
Block a user