fix: refine diagnosis validation feedback

bugfix/ai-assessment-evidence-rescore
chenyuan 1 month ago
parent 7fc110f288
commit f9031ad900

@ -450,6 +450,7 @@ export function validateProductDiagnosisIterationStepOne(payload) {
method: "post",
data: { channels: submittedChannels, conversionRates, funnelChartUrl: value.funnelChartUrl, anomalyRows },
headers: { repeatSubmit: false },
skipErrorMessage: true,
});
}
@ -493,7 +494,7 @@ export function validateProductDiagnosisIterationStepTwo(payload) {
return Promise.resolve({ code: 200, data: { valid: true, message: "情感评论占比计算校验通过" } });
} catch (error) { return Promise.reject(error); }
}
return request({ url: "/api/student-training-answers/product-diagnosis-iteration/step-2/validate", method: "post", data: value, headers: { repeatSubmit: false } });
return request({ url: "/api/student-training-answers/product-diagnosis-iteration/step-2/validate", method: "post", data: value, headers: { repeatSubmit: false }, skipErrorMessage: true });
}
export function validateProductDiagnosisIterationStepThree(payload) {
@ -509,7 +510,7 @@ export function validateProductDiagnosisIterationStepThree(payload) {
return Promise.resolve({ code: 200, data: { valid: true, message: "AB 测试方案、数据与对比图校验通过" } });
} catch (error) { return Promise.reject(error); }
}
return request({ url: "/api/student-training-answers/product-diagnosis-iteration/step-3/validate", method: "post", data: value, headers: { repeatSubmit: false } });
return request({ url: "/api/student-training-answers/product-diagnosis-iteration/step-3/validate", method: "post", data: value, headers: { repeatSubmit: false }, skipErrorMessage: true });
}
export function validatePromotionEffectOptimizationStepOne(payload) {

@ -56,14 +56,14 @@
<template v-else-if="currentStep === 2">
<p class="lead">漏斗只能定位“哪个环节出了问题”,要回答为什么出问题,需要分析用户最真实的反馈。本步骤通过词云分析和情感倾向分析,从用户评价中提取高频问题,判断整体口碑倾向,验证漏斗异常背后的真实根因。</p>
<section class="section-block"><div class="section-heading"><span>一</span><div><h3>词云分析</h3><p>导入数据,生成词云,基于案例评论数据自动生成高频问题词云。</p></div></div><input ref="commentInput" class="visually-hidden" type="file" accept=".csv,.txt,.xls,.xlsx,text/csv,text/plain,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" @change="handleCommentImport" /><div class="comment-import"><button type="button" class="upload-button" :disabled="analyzing" @click="commentInput?.click()">{{ analyzing ? '正在生成词云…' : '导入评论数据生成词云' }}</button><p>支持 CSV、TXT、XLS、XLSX,文件不超过 5MB。</p><div v-if="commentPreview.fileName" class="data-preview"><div><strong>{{ commentPreview.fileName }}</strong><span>已解析 {{ commentPreview.totalComments }} 条评论 · 数据预览</span></div><ul><li v-for="(comment, index) in commentPreview.comments" :key="index">{{ comment }}</li></ul></div></div><div v-if="wordCloud.length" class="word-cloud-card"><div class="word-cloud-title"><span>高频问题词云</span><small>基于导入评论自动生成</small></div><div ref="wordCloudRef" class="word-cloud" aria-label="评论高频问题词云"></div></div><div class="top-issues"><p>请根据词云图填写词云中出现频次最高的TOP3问题。</p><div><label v-for="(_, index) in topIssues" :key="index">TOP{{ index + 1 }}:<el-input v-model="topIssues[index]" :placeholder="`填写第 ${index + 1} 个高频问题`" /></label></div></div></section>
<section class="section-block"><div class="section-heading"><span>二</span><div><h3>情感倾向分析</h3></div></div><div class="sentiment-actions"><span>点击情感倾向分析后,系统会自动计算正面、中性、负面评论数量及占比,并按校验所需精度保留两位小数。</span><button type="button" class="upload-button" :disabled="!analysisResult" @click="runSentimentAnalysis">情感倾向分析</button></div><div class="table-wrap"><table class="sentiment-table"><thead><tr><th>情感类型</th><th>评论数量(条)</th><th>占比</th></tr></thead><tbody><tr v-for="row in sentiments" :key="row.type"><th>{{ row.type }}</th><td><span class="auto-count">{{ row.count ?? '—' }}</span></td><td><el-input-number v-model="row.percentage" :min="0" :max="100" :precision="2" :controls="false" disabled placeholder="系统自动计算" /><span class="unit">%</span></td></tr></tbody></table></div></section>
<section class="section-block"><div class="section-heading"><span>二</span><div><h3>情感倾向分析</h3></div></div><div class="sentiment-actions"><span>点击情感倾向分析后,系统会自动计算正面、中性、负面评论数量及占比,并按校验所需精度保留两位小数。</span><button type="button" class="upload-button" :disabled="!analysisResult" @click="runSentimentAnalysis">情感倾向分析</button></div><div class="table-wrap"><table class="sentiment-table"><thead><tr><th>情感类型</th><th>评论数量(条)</th><th>占比</th></tr></thead><tbody><tr v-for="row in sentiments" :key="row.type"><th>{{ row.type }}</th><td><span class="auto-count">{{ row.count ?? '—' }}</span></td><td><div class="rate-input"><el-input-number v-model="row.percentage" :min="0" :max="100" :precision="2" :controls="false" disabled placeholder="系统自动计算" /><span class="unit">%</span></div></td></tr></tbody></table></div></section>
<section class="section-block root-cause"><p>请结合词云TOP3与情感分析结果,说明本案例的核心问题根本原因;说明高频问题与情感数据是如何验证步骤一漏斗异常结论的</p><el-input v-model="rootCauseAnalysis" type="textarea" :rows="6" maxlength="1000" show-word-limit placeholder="请填写根因分析与对步骤一异常结论的验证说明" /></section>
</template>
<template v-else>
<p class="lead">找到根因后,还需验证“改进方案是否真的有效”,避免拍脑袋迭代。AB测试对照诊断法将用户随机分为对照组(维持原方案)和实验组(应用改进方案),对比两组的关键指标差异,用数据判断改进方案是否值得落地。</p>
<section class="section-block"><div class="section-heading"><span>(1)</span><div><h3>确定测试方案</h3><p>请基于案例资料,针对步骤一和步骤二分析结果,设计AB测试方案</p></div></div><el-input v-model="abTestPlan" type="textarea" :rows="6" maxlength="1000" show-word-limit placeholder="填写对照组与实验组设置、改进方案、随机分流方式、观察周期和成功判定标准" /></section>
<section class="section-block"><div class="section-heading"><span>(2)</span><div><h3>AB测试数据填报</h3><p>请从案例资料中获取AB测试两组数据,计算后填入下表并逐项判定:</p></div></div><div class="table-wrap"><table class="ab-table"><thead><tr><th>测试指标</th><th>对照组数据</th><th>实验组数据</th><th>判定与分析</th></tr></thead><tbody><tr v-for="row in abRows" :key="row.metric"><th>{{ row.metric }}</th><td><el-input-number v-model="row.controlValue" :min="0" :max="100" :precision="2" :controls="false" placeholder="示例:56%" /><span class="unit">%</span></td><td><el-input-number v-model="row.experimentValue" :min="0" :max="100" :precision="2" :controls="false" placeholder="示例:64%" /><span class="unit">%</span></td><td><el-input v-model="row.analysis" type="textarea" :rows="2" maxlength="300" show-word-limit placeholder="示例:提升8pp,显著提升,采纳" /></td></tr></tbody></table></div></section>
<section class="section-block"><div class="section-heading"><span>(2)</span><div><h3>AB测试数据填报</h3><p>请从案例资料中获取AB测试两组数据,计算后填入下表并逐项判定:</p></div></div><div class="table-wrap"><table class="ab-table"><thead><tr><th>测试指标</th><th>对照组数据</th><th>实验组数据</th><th>判定与分析</th></tr></thead><tbody><tr v-for="row in abRows" :key="row.metric"><th>{{ row.metric }}</th><td><div class="rate-input"><el-input-number v-model="row.controlValue" :min="0" :max="100" :precision="2" :controls="false" placeholder="示例:56%" /><span class="unit">%</span></div></td><td><div class="rate-input"><el-input-number v-model="row.experimentValue" :min="0" :max="100" :precision="2" :controls="false" placeholder="示例:64%" /><span class="unit">%</span></div></td><td><el-input v-model="row.analysis" type="textarea" :rows="2" maxlength="300" show-word-limit placeholder="示例:提升8pp,显著提升,采纳" /></td></tr></tbody></table></div></section>
<section class="section-block"><div class="section-heading"><span>(3)</span><div><h3>可视化呈现</h3><p>绘制AB测试结果对比图,参考方法及工具如下:</p></div></div><input ref="abChartInput" class="visually-hidden" type="file" accept="image/png,image/jpeg,image/webp" @change="handleAbChartUpload" /><div class="chart-upload-area"><template v-if="abChart.url"><div class="chart-preview"><el-image :src="abChart.url" :preview-src-list="[abChart.url]" fit="cover" preview-teleported /><div><strong>{{ abChart.name || 'AB 测试结果对比图' }}</strong><span>点击缩略图可放大预览</span><button type="button" @click="clearAbChart">移除图片</button></div></div><button type="button" class="secondary-button" :disabled="uploading" @click="abChartInput?.click()">{{ uploading ? '上传中…' : '更换对比图' }}</button></template><template v-else><button type="button" class="upload-button" :disabled="uploading" @click="abChartInput?.click()">{{ uploading ? '上传中…' : '上传AB测试结果对比图' }}</button><p>支持 PNG、JPG、WEBP 格式,图片不超过 5MB;上传后可点击预览。</p></template></div><div class="ab-materials"><div><ol><li>1.使用Excel/WPS绘图功能,自主完成AB测试结果对比图,参考《实训操作说明》。</li><li>2.下载Excel模版,填写关键信息,自动计算AB测试数据,并生成测试结果对比图。</li><li>3.导出数据表上传到通用AI大模型,通过AI大模型辅助完成,参考步骤及提示词如下:请根据表格数据,进行对照组和实验组数据对比,采用组合柱状图生成可视化图形。</li></ol></div><div class="ab-materials__actions"><button type="button" class="secondary-button" @click="downloadAbGuide">下载实训操作说明</button><button type="button" class="secondary-button" @click="downloadAbTemplate">下载Excel模板</button></div></div></section>
<section class="section-block"><div class="section-heading"><span>(4)</span><div><h3>诊断结论与迭代优化建议</h3><p>结合全链路数据漏斗诊断、售后评论分析法及AB测试对照诊断,分析产品存在的问题,并提出具体的迭代优化建议。</p></div></div><el-input v-model="iterationRecommendation" type="textarea" :rows="6" maxlength="1200" show-word-limit placeholder="请填写产品问题诊断结论及具体迭代优化建议" /></section>
</template>
@ -308,7 +308,6 @@ onMounted(async () => { try { taskConfig.value = (await getTrainingTaskByKey(TAS
.workbench .step-tabs .step-tab.complete .step-marker{border-color:#79eee4;color:#083342;background:#6deee1;box-shadow:none}
.workbench .step-tabs .step-connector{flex:0 0 30px;width:30px;height:1px;margin:0;background:rgba(94,193,229,.58)}
.workbench .step-tabs .step-connector::after{width:8px;height:8px;border-color:#73c8e7}
.sentiment-table td:last-child{white-space:nowrap}.sentiment-table td:last-child :deep(.el-input-number){display:inline-flex;width:calc(100% - 32px);vertical-align:middle}.sentiment-table td:last-child .unit{display:inline-flex;align-items:center;height:32px;margin-left:6px;vertical-align:middle}
@media(max-width:1100px){.diagnosis-page{grid-template-columns:1fr}}@media(max-width:720px){.diagnosis-page{padding:12px}.diagnosis-core{padding:16px;border-radius:20px}.workbench{padding:16px}.workbench-top,.table-toolbar,.sentiment-actions{align-items:stretch;flex-direction:column}.step-tabs{align-items:stretch;flex-direction:column}.step-tabs button{flex:0 0 auto;width:100%}.step-tabs i{flex:0 0 12px;width:2px;height:12px;margin-left:17px}.diagnosis-materials__item,.ab-materials{align-items:stretch;flex-direction:column}.top-issues>div{grid-template-columns:1fr}.chart-preview{align-items:flex-start;flex-direction:column}.chart-preview :deep(.el-image){width:100%;height:170px}}
.diagnosis-toolbar{align-self:center;justify-content:flex-end;max-width:100%}
@media(max-width:720px){.diagnosis-toolbar{width:100%;justify-content:flex-start}}

@ -27,3 +27,19 @@ test("动态渠道随第一步答案提交并用于校验", () => {
assert.match(api, /data: \{ channels: submittedChannels, conversionRates/);
assert.match(api, /source\.channelRates\[channel\.id\]/);
});
test("三个步骤的百分比输入全部将百分号固定在输入框同行", () => {
const units = [...page.matchAll(/<span class="unit">%<\/span>/g)];
assert.equal(units.length, 7);
units.forEach(({ index }) => {
assert.ok(page.lastIndexOf('<div class="rate-input">', index) > page.lastIndexOf("<td", index));
});
});
test("三个步骤的后端校验错误均交由页面显示单条中文提示", () => {
const validationBlock = api.slice(
api.indexOf("export function validateProductDiagnosisIterationStepOne"),
api.indexOf("export function validatePromotionEffectOptimizationStepOne")
);
assert.equal((validationBlock.match(/skipErrorMessage:\s*true/g) || []).length, 3);
});

Loading…
Cancel
Save