思维导图
@@ -467,6 +328,9 @@ watch(
>
上传导图文件
+
+ 回忆复习
+
{{ mindMap.fileFormat }}
@@ -605,7 +469,7 @@ watch(
.review-extension-grid {
display: grid;
- grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+ grid-template-columns: minmax(0, 1fr);
gap: 14px;
}
@@ -627,48 +491,6 @@ watch(
font-size: 16px;
}
-.application-list {
- display: flex;
- flex-direction: column;
- gap: 10px;
- margin-bottom: 14px;
-}
-
-.application-item {
- padding: 12px;
- border: 1px solid var(--border-soft);
- border-radius: 8px;
- background: #fbfefc;
-}
-
-.application-main {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 10px;
-}
-
-.application-main strong {
- min-width: 0;
- color: var(--text-primary);
- word-break: break-word;
-}
-
-.application-item p {
- margin: 8px 0 0;
- color: var(--text-secondary);
- font-size: 13px;
- word-break: break-word;
-}
-
-.item-actions {
- display: flex;
- justify-content: flex-end;
- gap: 4px;
- margin-top: 8px;
-}
-
-.application-form,
.mind-map-form {
display: flex;
flex-direction: column;
@@ -740,12 +562,6 @@ watch(
color: var(--text-primary);
}
-.form-row {
- display: flex;
- align-items: center;
- gap: 10px;
-}
-
/* 历史记录卡片 */
.history-card {
padding: 20px 22px;
diff --git a/src/components/ReviewRecall.vue b/src/components/ReviewRecall.vue
new file mode 100644
index 0000000..b9e7b29
--- /dev/null
+++ b/src/components/ReviewRecall.vue
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+
+
+
+
+ 回忆覆盖率
+ {{ ratioPercent }}
+
+
+ ✅ 回忆命中
+ {{ lastResult.matchedCount }}
+
+
+ ❌ 遗漏
+ {{ lastResult.missedCount }}
+
+
+ ➕ 额外
+
+
+
+
+
+
+ 回忆历史
+
+
+ {{ record.createdTime?.replace("T", " ")?.substring(0, 16) }}
+ 覆盖率 {{ (record.recallRatio * 100).toFixed(1) }}%
+ ✅{{ record.matchedCount }} ❌{{ record.missedCount }} ➕{{ record.extraCount }}
+
+
+
+
+
+
+
+
+
+ 🧠 你的回忆
+
+ 凭记忆写下该任务的知识点大纲(缩进表示层级),写完后点击"提交对比"。
+
+
+
+
+ 提交对比
+
+
+ 清空重写
+
+
+
+
+
+
📊 对比结果
+
{{ resultText }}
+
+
+
+
+
+
+
📖 标准思维导图
+
+
+ {{ standardExpanded ? "折叠" : "展开" }}
+
+
+ 重新生成
+
+
+ 编辑
+
+
+
+
+
+
+
+ 生成
+
+
+
+
+
+
编辑大纲文本,保存后标准导图将被更新。
+
+
{{ standard.summary }}
+
+ 取消
+
+ 保存更新
+
+
+
+
+
+
+ 来源:{{ standard.generator }}
+ 参考:{{ standard.sourceReportCount }} 份报告 + {{ standard.sourceFragmentCount }} 份残片
+
+
{{ standard.outline || standard.content }}
+
{{ standard.summary }}
+
+
+
+
标准导图已生成。展开后可查看或编辑。建议先凭记忆写回忆大纲再对照。
+
+
+
+
+
+
+
+
+ ❌ 遗漏的知识点
+
+
+ {{ item.title }}
+
+ 查看原文
+
+
+
+
+
+
+
+ ➕ 你额外回忆到的知识点
+
+
+
+
+
+
+
diff --git a/src/components/Study.vue b/src/components/Study.vue
index c83a656..aa5fdc3 100644
--- a/src/components/Study.vue
+++ b/src/components/Study.vue
@@ -4,6 +4,11 @@ import request from "@/utils/request";
import router from "@/router";
import { ElMessage } from "element-plus";
import { getReviewTaskStatsByTask } from "@/api/review";
+import {
+ getTaskApplications,
+ updateTaskApplication,
+ type TaskApplication,
+} from "@/api/tasks";
interface TaskItem {
title: string;
@@ -27,6 +32,14 @@ interface TaskItem {
const tasks = ref
([]);
const selectedTaskId = ref(null);
const loading = ref(false);
+const taskApplications = ref([]);
+const applicationsLoading = ref(false);
+
+const applicationStatusOptions: { label: string; value: TaskApplication["status"] }[] = [
+ { label: "待应用", value: "TODO" },
+ { label: "进行中", value: "DOING" },
+ { label: "已完成", value: "DONE" },
+];
const selectedTask = computed(() =>
tasks.value.find((item) => item.taskId === selectedTaskId.value) || null
@@ -62,6 +75,36 @@ async function loadTaskStats(taskNum: string) {
}
}
+async function loadTaskApplications(taskNum: string) {
+ applicationsLoading.value = true;
+ try {
+ const res = await getTaskApplications(taskNum);
+ taskApplications.value = res?.data || [];
+ } catch (error: any) {
+ taskApplications.value = [];
+ ElMessage.error(error?.message || "应用场景加载失败");
+ } finally {
+ applicationsLoading.value = false;
+ }
+}
+
+const changeApplicationStatus = async (item: TaskApplication) => {
+ try {
+ await updateTaskApplication(item.id, {
+ title: item.title,
+ description: item.description,
+ resourceUrl: item.resourceUrl,
+ status: item.status,
+ });
+ ElMessage.success("应用场景状态已更新");
+ } catch (error: any) {
+ ElMessage.error(error?.message || "状态更新失败");
+ if (selectedTask.value) {
+ await loadTaskApplications(selectedTask.value.taskNum);
+ }
+ }
+};
+
const fetchTasks = async () => {
loading.value = true;
try {
@@ -91,10 +134,12 @@ const fetchTasks = async () => {
selectedTaskId.value = nextSelectedTaskId;
if (targetTask && shouldLoadStats) {
await loadTaskStats(targetTask.taskNum);
+ await loadTaskApplications(targetTask.taskNum);
}
} catch (error: any) {
tasks.value = [];
selectedTaskId.value = null;
+ taskApplications.value = [];
ElMessage.error(error?.message || "任务列表加载失败,请重试");
} finally {
loading.value = false;
@@ -105,6 +150,9 @@ watch(selectedTaskId, (newId) => {
const task = tasks.value.find(t => t.taskId === newId);
if (task) {
loadTaskStats(task.taskNum);
+ loadTaskApplications(task.taskNum);
+ } else {
+ taskApplications.value = [];
}
});
@@ -229,6 +277,39 @@ onMounted(() => {
+
+