diff --git a/src/views/reviewer/ReviewerApplicationDetailView.vue b/src/views/reviewer/ReviewerApplicationDetailView.vue index d7cbdc0..cbfed28 100644 --- a/src/views/reviewer/ReviewerApplicationDetailView.vue +++ b/src/views/reviewer/ReviewerApplicationDetailView.vue @@ -134,23 +134,15 @@ function totalDraftText(): string { const SCORE_MAX = 100 const SCORE_DECIMALS = 2 -/** 文本输入绑定:仅 0~100,最多两位小数 */ +/** 文本输入绑定:保留用户输入以便校验提示,不做自动改写 */ const totalDraftModel = computed({ get: () => totalDraft.value, set: (v: string | number | null | undefined) => { const raw = v == null ? '' : String(v) - let cleaned = raw.replace(/[^\d.]/g, '').replace(/(\..*)\./g, '$1') - const m = cleaned.match(/^(\d*)(\.\d{0,2})?/) - cleaned = m ? `${m[1] ?? ''}${m[2] ?? ''}` : '' - if (cleaned === '' || cleaned === '.') { - totalDraft.value = cleaned === '.' ? '0.' : '' - return - } - const n = Number(cleaned) - if (Number.isFinite(n) && n > SCORE_MAX) { - totalDraft.value = String(SCORE_MAX) - return - } + // 仅过滤非法字符;允许负号、大于 100、超过两位小数,由校验提示拦截 + let cleaned = raw.replace(/[^\d.-]/g, '') + cleaned = cleaned.replace(/(?!^)-/g, '') + cleaned = cleaned.replace(/(\..*)\./g, '$1') totalDraft.value = cleaned }, }) @@ -231,30 +223,22 @@ function getTotalError(): string | null { if (scoreShowErrors.value || totalBlurred.value) return '请填写项目总分' return null } - if (hasMoreThanTwoDecimals(raw)) return '最多保留两位小数' + if (raw === '-' || raw === '.' || raw === '-.') return '须为数字' + if (hasMoreThanTwoDecimals(raw)) return '项目总分最多保留两位小数' const n = Number(raw) if (!Number.isFinite(n)) return '须为数字' - if (n < 0) return '不能小于 0' - if (n > SCORE_MAX) return '不得超过 100 分' + if (n < 0) return '项目总分不能为负数' + if (n > SCORE_MAX) return '项目总分不能大于 100' return null } function onTotalBlur(): void { totalBlurred.value = true - const raw = totalDraftText() - if (raw === '' || raw.endsWith('.')) return - const n = Number(raw) - if (!Number.isFinite(n)) return - const clamped = Math.min(SCORE_MAX, Math.max(0, n)) - totalDraft.value = rtrimZeros(clamped.toFixed(SCORE_DECIMALS)) } const canSubmitScore = computed(() => { if (!detail.value?.scoring_allowed || !scoringItems.value.length) return false - const raw = totalDraftText() - if (raw === '' || hasMoreThanTwoDecimals(raw)) return false - const n = Number(raw) - return Number.isFinite(n) && n >= 0 && n <= SCORE_MAX + return getTotalError() === null && totalDraftText() !== '' }) const scoreFormHint = computed(() => { @@ -387,9 +371,9 @@ async function downloadAttachment(f: FileItem) { } function buildSubmitPayload(): Record { + // 仅在 canSubmitScore 通过后调用;不做四舍五入/截断,原样提交校验过的数值 const n = Number(totalDraftText()) - const score = Number.isFinite(n) ? Math.round(n * 100) / 100 : 0 - return { line_total: score } + return { line_total: n } } function cleanupModalArtifacts(): void {