Files
lpt-fe/src/components/TaskForm.vue
T
cat-shark fce4ba194b fix: 完善任务导航与结束会话错误处理
- 结束会话 API 异常时显示错误,不导航(可重试)
- 结束会话硬跳转改为软导航 router.push
- TaskForm 创建/更新/取消后跳转任务列表页
- 移除 TaskForm 页面内大标题
2026-05-23 22:55:03 +08:00

231 lines
5.9 KiB
Vue

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from "vue";
import request from "@/utils/request";
import { ElMessage } from "element-plus";
import { useRoute, useRouter } from "vue-router";
const router = useRouter();
const route = useRoute();
const taskId = route.params.taskId ? Number(route.params.taskId) : null;
const buttonName = route.meta.buttonText as string;
const taskName = ref("");
const taskDescription = ref("");
const materialURL = ref("");
const priority = ref({
urgency: 0,
importance: 0,
contentDifficulty: 0,
futureValue: 0,
subjectivePriority: 0,
});
const priorityOptions = [0, 1, 2, 3, 4, 5];
const createTask = () => {
request
.post("/tasks", {
taskName: taskName.value,
taskDescription: taskDescription.value,
materialURL: materialURL.value,
...priority.value,
})
.then((result) => {
if (result.code === 200) {
ElMessage.success("创建任务成功");
router.push({ name: "study" });
} else {
ElMessage.error("任务创建失败:" + result.message);
}
});
};
const loadTask = () => {
if (taskId !== null) {
request.get(`/tasks/${taskId}`, {}).then((result) => {
if (result.code === 200) {
const data = result.data;
taskName.value = data.taskName;
taskDescription.value = data.taskDescription;
materialURL.value = data.materialURL || data.materialUrl || "";
priority.value = {
urgency: data.urgency,
importance: data.importance,
contentDifficulty: data.contentDifficulty,
futureValue: data.futureValue,
subjectivePriority: data.subjectivePriority,
};
} else {
ElMessage.error(`任务加载失败:${result.message}`);
}
});
}
};
const updateTask = () => {
request
.put("/tasks/" + taskId, {
id: taskId,
taskName: taskName.value,
taskDescription: taskDescription.value,
materialURL: materialURL.value,
...priority.value,
})
.then((result) => {
if (result.code === 200) {
ElMessage.success("更新任务成功");
router.push({ name: "study" });
} else {
ElMessage.error("任务更新失败:" + result.message);
}
});
};
const cancelTask = () => {
ElMessage.info("已取消操作");
router.push({ name: "study" });
};
const submitTask = () => {
switch (route.name) {
case "add-task":
createTask();
break;
case "update-task":
updateTask();
break;
default:
ElMessage.error("未知操作类型");
}
};
const screenWidth = ref(window.innerWidth);
const updateWidth = () => {
screenWidth.value = window.innerWidth;
};
onMounted(() => {
window.addEventListener("resize", updateWidth);
if (route.meta.action === "update" && taskId !== null) {
loadTask();
}
});
onUnmounted(() => window.removeEventListener("resize", updateWidth));
const isMobile = computed(() => screenWidth.value <= 900);
</script>
<template>
<section class="task-form-page">
<el-form label-position="top" class="surface-card form-shell">
<div class="group">
<h3>基础信息</h3>
<el-form-item label="任务名称">
<el-input v-model="taskName" placeholder="例如:Vue3 组件通信实践" />
</el-form-item>
<el-form-item label="任务描述">
<el-input v-model="taskDescription" type="textarea" :rows="5" placeholder="请输入任务描述" />
</el-form-item>
<el-form-item label="学习材料地址">
<el-input v-model="materialURL" placeholder="例如:https://..." />
</el-form-item>
</div>
<div class="group">
<h3>优先级维度</h3>
<div class="priority-grid" :class="{ mobile: isMobile }">
<el-form-item label="急迫性">
<el-select v-model="priority.urgency">
<el-option v-for="item in priorityOptions" :key="'u' + item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="重要性">
<el-select v-model="priority.importance">
<el-option v-for="item in priorityOptions" :key="'i' + item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="内容难度">
<el-select v-model="priority.contentDifficulty">
<el-option v-for="item in priorityOptions" :key="'d' + item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="未来价值">
<el-select v-model="priority.futureValue">
<el-option v-for="item in priorityOptions" :key="'f' + item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="主观优先级">
<el-select v-model="priority.subjectivePriority">
<el-option v-for="item in priorityOptions" :key="'s' + item" :label="item" :value="item" />
</el-select>
</el-form-item>
</div>
</div>
<div class="action-row">
<el-button type="success" size="large" @click="submitTask">{{ buttonName }}</el-button>
<el-button size="large" @click="cancelTask">取消</el-button>
</div>
</el-form>
</section>
</template>
<style scoped>
.task-form-page {
display: flex;
flex-direction: column;
gap: 14px;
}
.form-shell {
padding: 22px;
}
.group + .group {
margin-top: 12px;
}
.group h3 {
margin: 0 0 12px;
color: var(--green-900);
}
.priority-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0 14px;
}
.priority-grid.mobile {
grid-template-columns: 1fr;
}
.action-row {
margin-top: 8px;
display: flex;
gap: 10px;
}
@media (max-width: 768px) {
.form-shell {
padding: 16px;
}
.action-row {
flex-direction: column;
}
.action-row .el-button {
width: 100%;
margin: 0;
}
}
</style>