feat(预期):学习预期闭环 + 权重配置 UI

- StartTask:新会话强制填写学习预期(不可跳过),页面顶部常驻展示可修改
- 结束会话弹窗:展示本次预期供对照,有残片时自动拉取 AI 聚合草稿作为编辑起点
- Study:常用操作增加权重配置——五维度滑块、合计校验 100%、保存后重算并刷新
- api:expectation / report-draft / priority-weights 接口
This commit is contained in:
2026-07-03 23:56:52 +08:00
parent b24483b03b
commit 6346120805
4 changed files with 299 additions and 4 deletions
+125
View File
@@ -5,8 +5,11 @@ import router from "@/router";
import { ElMessage } from "element-plus";
import { getReviewTaskStatsByTask } from "@/api/review";
import {
getPriorityWeights,
getTaskApplications,
savePriorityWeights,
updateTaskApplication,
type PriorityWeights,
type TaskApplication,
} from "@/api/tasks";
@@ -190,6 +193,62 @@ const removeTask = async () => {
}
};
// ============ 优先级权重配置 ============
const weightsDialogVisible = ref(false);
const savingWeights = ref(false);
const weightItems = ref([
{ key: "urgencyWeight", label: "紧急性", value: 35 },
{ key: "importanceWeight", label: "重要性", value: 25 },
{ key: "contentDifficultyWeight", label: "内容难度", value: 20 },
{ key: "futureValueWeight", label: "未来价值", value: 10 },
{ key: "subjectivePriorityWeight", label: "主观优先级", value: 10 },
]);
const weightsSum = computed(() =>
weightItems.value.reduce((acc, item) => acc + item.value, 0)
);
const openWeightsDialog = async () => {
try {
const res = await getPriorityWeights();
const data = res?.data;
if (data) {
for (const item of weightItems.value) {
const v = data[item.key];
if (typeof v === "number") item.value = Math.round(v * 100);
}
}
} catch {
// 读取失败时保持默认值
}
weightsDialogVisible.value = true;
};
const saveWeights = async () => {
if (weightsSum.value !== 100) {
ElMessage.warning(`五项权重之和需为 100%,当前 ${weightsSum.value}%`);
return;
}
savingWeights.value = true;
try {
const payload = Object.fromEntries(
weightItems.value.map((item) => [item.key, item.value / 100])
) as unknown as PriorityWeights;
const res = await savePriorityWeights(payload);
if (res?.code === 200) {
weightsDialogVisible.value = false;
ElMessage.success("权重已保存,任务优先级已重算");
await fetchTasks();
} else {
ElMessage.error(res?.message || "保存失败");
}
} catch (e: any) {
ElMessage.error(e.message || "请求失败");
} finally {
savingWeights.value = false;
}
};
onMounted(() => {
fetchTasks();
});
@@ -320,11 +379,32 @@ onMounted(() => {
<el-button type="success" size="large" @click="startTask">开始任务</el-button>
<el-button size="large" @click="addTask">添加任务</el-button>
<el-button size="large" @click="changeTask">更新任务</el-button>
<el-button size="large" @click="openWeightsDialog">权重配置</el-button>
<el-button type="danger" size="large" @click="removeTask">删除任务</el-button>
</aside>
</main>
</div>
</section>
<el-dialog v-model="weightsDialogVisible" title="优先级权重配置" width="560px">
<p class="weights-hint">
调整五个维度在优先级计算中的占比保存后全部任务将按新权重重新排序
</p>
<div v-for="item in weightItems" :key="item.key" class="weight-row">
<span class="weight-label">{{ item.label }}</span>
<el-slider v-model="item.value" :min="0" :max="100" :step="5" class="weight-slider" />
<span class="weight-value">{{ item.value }}%</span>
</div>
<div class="weights-sum" :class="{ 'sum-error': weightsSum !== 100 }">
合计{{ weightsSum }}%需为 100%
</div>
<template #footer>
<el-button @click="weightsDialogVisible = false">取消</el-button>
<el-button type="success" :loading="savingWeights" :disabled="weightsSum !== 100" @click="saveWeights">
保存并重算
</el-button>
</template>
</el-dialog>
</template>
<style scoped>
@@ -334,6 +414,51 @@ onMounted(() => {
gap: 14px;
}
.weights-hint {
margin: 0 0 14px;
font-size: 13px;
color: var(--text-secondary);
}
.weight-row {
display: flex;
align-items: center;
gap: 14px;
margin-bottom: 6px;
}
.weight-label {
flex-shrink: 0;
width: 80px;
font-size: 14px;
color: var(--text-primary);
}
.weight-slider {
flex: 1;
}
.weight-value {
flex-shrink: 0;
width: 44px;
text-align: right;
font-size: 13px;
color: var(--green-800);
font-weight: 600;
}
.weights-sum {
margin-top: 8px;
text-align: right;
font-size: 13px;
color: var(--green-800);
font-weight: 600;
}
.weights-sum.sum-error {
color: #c62828;
}
.layout-grid {
display: grid;
grid-template-columns: 280px 1fr;