import { isWriteOutcomeUnknown } from '@/utils/request-outcome.js' const messages = { submitted: "反馈已提交。以下内容为本次提交记录;修改任一项后可提交新反馈。", submittedWithEdits: "上一份反馈已提交,当前修改尚未提交。", uncertain: "暂时无法确认是否提交成功,请不要重复提交相同内容。你可以修改内容后再提交一份反馈。", uncertainWithEdits: "上一份反馈暂未确认,当前修改尚未提交。", }; const normalizeFeedback = (form) => ({ feedbackType: String(form?.feedbackType || "").trim(), feedbackContent: String(form?.feedbackContent || "").trim(), contactInfo: String(form?.contactInfo || "").trim(), }); // 字段顺序固定的快照既用于脏数据判断,也用于阻止非幂等 POST 重复提交。 // 不能改成对象引用比较,否则 Vue 表单原地修改时无法识别同一份内容。 const snapshotOf = (form) => JSON.stringify(normalizeFeedback(form)); const errorMessage = (error) => { if (error?.httpStatus === 401) { return "登录状态已失效,请重新登录后再提交。"; } return "提交未完成,请稍后再试。"; }; const submitLabelFor = (phase) => { if (phase === "submitting") return "正在提交"; if (phase === "success") return "反馈已提交"; if (phase === "uncertain") return "暂未确认"; if (phase === "error") return "重新提交"; return "提交反馈"; }; export const createFeedbackSubmissionSession = (initialForm) => { let baselineSnapshot = snapshotOf(initialForm); let lastSubmittedSnapshot = ""; let lastUncertainSnapshot = ""; let phase = "ready"; let message = ""; let tone = ""; const view = (currentForm) => { const currentSnapshot = snapshotOf(currentForm); const isRepeatedSubmission = currentSnapshot === lastSubmittedSnapshot || currentSnapshot === lastUncertainSnapshot; return { phase, message, tone, isDirty: currentSnapshot !== baselineSnapshot, isSubmitDisabled: phase === "submitting" || isRepeatedSubmission, submitLabel: submitLabelFor(phase), }; }; const begin = (currentForm) => { const currentSnapshot = snapshotOf(currentForm); if ( phase === "submitting" || currentSnapshot === lastSubmittedSnapshot || currentSnapshot === lastUncertainSnapshot ) { return null; } phase = "submitting"; message = ""; tone = ""; return { snapshot: currentSnapshot, payload: normalizeFeedback(currentForm), }; }; const succeed = (submission, currentForm) => { baselineSnapshot = submission.snapshot; lastSubmittedSnapshot = submission.snapshot; tone = "success"; if (snapshotOf(currentForm) === submission.snapshot) { phase = "success"; message = messages.submitted; } else { phase = "ready"; message = messages.submittedWithEdits; } }; const fail = (submission, error, currentForm) => { if (!isWriteOutcomeUnknown(error)) { phase = "error"; message = errorMessage(error); tone = "error"; return; } // 超时或异常 2xx 可能已经被后端写入。记录原快照并禁用原样重试, // 避免用户在网络恢复后生成两条内容完全相同的反馈。 lastUncertainSnapshot = submission.snapshot; tone = "uncertain"; if (snapshotOf(currentForm) === submission.snapshot) { phase = "uncertain"; message = messages.uncertain; } else { phase = "ready"; message = messages.uncertainWithEdits; } }; const reconcile = (currentForm) => { if (phase === "submitting") return; const currentSnapshot = snapshotOf(currentForm); if (lastSubmittedSnapshot && currentSnapshot === lastSubmittedSnapshot) { phase = "success"; message = messages.submitted; tone = "success"; return; } if (lastUncertainSnapshot && currentSnapshot === lastUncertainSnapshot) { phase = "uncertain"; message = messages.uncertain; tone = "uncertain"; return; } phase = "ready"; if (lastUncertainSnapshot) { message = messages.uncertainWithEdits; tone = "uncertain"; } else if (lastSubmittedSnapshot) { message = messages.submittedWithEdits; tone = "success"; } else { message = ""; tone = ""; } }; return { begin, succeed, fail, reconcile, view }; };