diff --git a/src/components/StartTask.vue b/src/components/StartTask.vue index 3adbc0d..2ae328a 100644 --- a/src/components/StartTask.vue +++ b/src/components/StartTask.vue @@ -2,6 +2,7 @@ import { computed, onMounted, onUnmounted, ref, watch } from "vue"; import { useRoute } from "vue-router"; import { ElMessage, ElMessageBox } from "element-plus"; +import request from "@/utils/request"; import { useTimer } from "@/components/composables/useTimer"; import { continueSession, @@ -133,6 +134,8 @@ const taskInfo = ref({ sessionState: "--", taskName: "", taskNum, + taskId: 0, + materialUrl: "", startTime: "", endTime: "", lastStartTime: "", @@ -143,6 +146,65 @@ const taskInfo = ref({ systemMessage: "", }); +// 学习材料展示/编辑 +const editingMaterial = ref(false); +const editMaterialContent = ref(""); +const savingMaterial = ref(false); +const materialHtml = computed(() => { + const raw = taskInfo.value.materialUrl || ""; + if (!raw.trim()) return ""; + let html = raw; + const links: string[] = []; + html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m: string, text: string, url: string) => { + const tag = `${text}`; + links.push(tag); + return `__LINK_${links.length - 1}__`; + }); + html = html.replace(/https?:\/\/[^\s)\u3001\uFF09\u300D\u300B<>]+/g, (url) => { + const clean = url.replace(/[.。,,;;!!??)】」』\]]+$/, ""); + const tag = `${clean}`; + links.push(tag); + return `__LINK_${links.length - 1}__`; + }); + html = html.replace(/\n/g, "
"); + for (let i = 0; i < links.length; i++) { + html = html.replace(`__LINK_${i}__`, links[i]); + } + return html; +}); + +function startEditMaterial() { + editMaterialContent.value = taskInfo.value.materialUrl; + editingMaterial.value = true; +} + +async function saveMaterial() { + savingMaterial.value = true; + try { + // 先拉取完整任务数据,只改 materialUrl,其他字段保持不变 + const res = await request.get(`/tasks/${taskInfo.value.taskId}`); + const current = res?.data || {}; + await request.put(`/tasks/${taskInfo.value.taskId}`, { + id: taskInfo.value.taskId, + taskName: current.taskName, + taskDescription: current.taskDescription || "", + materialUrl: editMaterialContent.value, + urgency: current.urgency ?? 0, + importance: current.importance ?? 0, + contentDifficulty: current.contentDifficulty ?? 0, + futureValue: current.futureValue ?? 0, + subjectivePriority: current.subjectivePriority ?? 0, + }); + taskInfo.value.materialUrl = editMaterialContent.value; + editingMaterial.value = false; + ElMessage.success("学习材料已更新"); + } catch (e: any) { + ElMessage.error(e?.message || "更新失败"); + } finally { + savingMaterial.value = false; + } +} + const { timerMinutes, timerSeconds, @@ -550,6 +612,30 @@ onUnmounted(() => { 状态:{{ statusText }} + +
+
+ 学习材料 + 编辑 +
+
+

暂未填写材料地址

+ + +

[链接文字](url) 或直接粘贴链接,保存时自动获取标题

+ +
+
+
本次预期 @@ -804,6 +890,50 @@ onUnmounted(() => { word-break: break-word; } +.material-session-card { + padding: 12px 16px; +} + +.material-session-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 6px; +} + +.material-session-label { + font-size: 12px; + font-weight: 700; + color: var(--green-700); + background: #e8f5e9; + padding: 2px 8px; + border-radius: 4px; +} + +.material-session-content { + font-size: 14px; + line-height: 1.7; + word-break: break-word; + color: var(--text-primary); +} + +.material-session-content :deep(a) { + color: var(--green-600); + text-decoration: none; + border-bottom: 1px dashed var(--green-400); +} + +.material-session-content :deep(a:hover) { + color: var(--green-800); + border-bottom-style: solid; +} + +.edit-hint { + margin: 6px 0 0; + font-size: 12px; + color: var(--text-secondary); +} + .dialog-hint { margin: 0 0 10px; font-size: 13px;