|
|
|
|
@ -171,8 +171,9 @@
|
|
|
|
|
</article>
|
|
|
|
|
|
|
|
|
|
<div class="task-actions">
|
|
|
|
|
<button type="button" class="btn-nav" :disabled="!isDocumentReady || saving || documentUploading" @click="saveStepThree">{{ saving ? '保存中…' : '保存文档' }}</button>
|
|
|
|
|
<button type="button" class="btn-nav" :disabled="!isDocumentReady || saving || submitting || documentUploading" @click="saveStepThree">{{ saving ? '保存中…' : '保存文档' }}</button>
|
|
|
|
|
<button type="button" class="btn-nav btn-submit" :disabled="!isDocumentReady || documentUploading" @click="showDocumentPreview = true"><el-icon><View /></el-icon>预览文档</button>
|
|
|
|
|
<button type="button" class="btn-nav btn-primary" :disabled="!canSubmitTask || saving || submitting || documentUploading" @click="submitTask">{{ submitting ? '提交中…' : '提交任务' }}</button>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
@ -293,6 +294,7 @@ const draggingPurposeId = ref("");
|
|
|
|
|
const dragOverModuleId = ref("");
|
|
|
|
|
const checking = ref(false);
|
|
|
|
|
const saving = ref(false);
|
|
|
|
|
const submitting = ref(false);
|
|
|
|
|
const stepOnePassed = ref(false);
|
|
|
|
|
const checkResult = ref(null);
|
|
|
|
|
|
|
|
|
|
@ -305,6 +307,7 @@ const progressItems = computed(() => trainingSteps.value.map((text, index) => ({
|
|
|
|
|
const unassignedPurposes = computed(() => PURPOSES.filter((purpose) => !Object.values(assignments.value).includes(purpose.id)));
|
|
|
|
|
const allAssigned = computed(() => MODULES.every((module) => Boolean(assignments.value[module.id])) && Object.keys(assignments.value).length === MODULES.length);
|
|
|
|
|
const isDocumentReady = computed(() => Boolean(stepThreeDocument.value.name && stepThreeDocument.value.url));
|
|
|
|
|
const canSubmitTask = computed(() => stepOnePassed.value && isDocumentReady.value);
|
|
|
|
|
const sidebarStudyTip = computed(() => currentStep.value === 3
|
|
|
|
|
? "先依据第 2 步的模块信息整理成完整 PRD,再上传 .docx 或 .pdf。上传完成后请打开在线预览,确认文档内容和版本无误。"
|
|
|
|
|
: currentStep.value === 2
|
|
|
|
|
@ -382,6 +385,7 @@ function buildStepThreeAnswer() { return { document: { ...stepThreeDocument.valu
|
|
|
|
|
function buildSavePayload(current = currentStep.value) {
|
|
|
|
|
return { currentStep: current, step1Answer: JSON.stringify(buildStepOneAnswer()), step2Answer: JSON.stringify(buildStepTwoAnswer()), step3Answer: JSON.stringify(buildStepThreeAnswer()), submitted: false, saveAction: "SAVE" };
|
|
|
|
|
}
|
|
|
|
|
function buildSubmitPayload() { return { ...buildSavePayload(3), submitted: true, saveAction: "SUBMIT" }; }
|
|
|
|
|
async function persist(current = currentStep.value) { await saveStudentTrainingAnswer(TASK_KEY, buildSavePayload(current)); }
|
|
|
|
|
async function saveCurrentMatching() {
|
|
|
|
|
if (saving.value) return;
|
|
|
|
|
@ -454,6 +458,13 @@ async function saveStepThree() {
|
|
|
|
|
saving.value = true;
|
|
|
|
|
try { await persist(3); proxy?.$modal?.msgSuccess("产品需求文档已保存"); } catch (error) { proxy?.$modal?.msgError(error?.message || "保存失败,请稍后重试"); } finally { saving.value = false; }
|
|
|
|
|
}
|
|
|
|
|
async function submitTask() {
|
|
|
|
|
if (!canSubmitTask.value || saving.value || submitting.value || documentUploading.value) return;
|
|
|
|
|
submitting.value = true;
|
|
|
|
|
try { await saveStudentTrainingAnswer(TASK_KEY, buildSubmitPayload()); proxy?.$modal?.msgSuccess("产品需求文档已提交"); }
|
|
|
|
|
catch (error) { proxy?.$modal?.msgError(error?.message || "提交失败,请稍后重试"); }
|
|
|
|
|
finally { submitting.value = false; }
|
|
|
|
|
}
|
|
|
|
|
async function exportStepTwoTable() {
|
|
|
|
|
try {
|
|
|
|
|
const XLSX = await import("xlsx");
|
|
|
|
|
|