修改:生图失败文案提示和用户头像调整
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/prod Build is passing

This commit is contained in:
Linzm committed 2026-11-10 10:44:41 +08:00
1 parent 02d926e91e
commit 31754ef398
4 files changed
+72 -19

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

+7 -1
View File
@@ -1,5 +1,6 @@
import logoAvatar from '@/assets/jingdong/logo-mark.png' import logoAvatar from '@/assets/jingdong/logo-mark.png'
import logoIcon from '@/assets/jingdong/logo_1.png' import logoIcon from '@/assets/jingdong/logo_1.png'
import userAvatar from '@/assets/jingdong/jingdong.png'
import caseOriginal from '@/assets/jingdong/原图.png' import caseOriginal from '@/assets/jingdong/原图.png'
import caseEffect from '@/assets/jingdong/效果图.png' import caseEffect from '@/assets/jingdong/效果图.png'
import caseScene from '@/assets/jingdong/场景图.png' import caseScene from '@/assets/jingdong/场景图.png'
@@ -19,9 +20,11 @@ export const jingdongConfig = {
background: '#F5F5F5', background: '#F5F5F5',
images: { images: {
/** 顶栏 / 对话头像 */ /** 顶栏 / Agent 对话头像 */
avatar: logoAvatar, avatar: logoAvatar,
logo: logoAvatar, logo: logoAvatar,
/** 用户侧对话头像 */
userAvatar,
/** 浏览器标签 favicon */ /** 浏览器标签 favicon */
logoIcon, logoIcon,
caseOriginal, caseOriginal,
@@ -74,5 +77,8 @@ export const jingdongConfig = {
effectPreparing: '效果图准备中,请稍后再试', effectPreparing: '效果图准备中,请稍后再试',
generateFail: '这次没生成成功,请换个描述或照片再试', generateFail: '这次没生成成功,请换个描述或照片再试',
editFail: '这次调整没成功,请换个描述再试', editFail: '这次调整没成功,请换个描述再试',
/** 内容安全策略拒绝(未成年 / 公众人物等) */
contentPolicyFail:
'当前照片不符合内容规范,可能涉及未成年或公众人物,请换一张照片再试',
}, },
} }
+54 -6
View File
@@ -1,5 +1,7 @@
/** 将后端 / 网络 / 前端技术错误转成用户可读提示 */ /** 将后端 / 网络 / 前端技术错误转成用户可读提示 */
import { jingdongConfig } from '@/config/jingdong'
const KNOWN: Record<string, string> = { const KNOWN: Record<string, string> = {
未登录: '登录已失效,请关闭后重新进入再试', 未登录: '登录已失效,请关闭后重新进入再试',
请求失败: '服务繁忙,请稍后重试', 请求失败: '服务繁忙,请稍后重试',
@@ -17,7 +19,7 @@ const KNOWN: Record<string, string> = {
'签发上传地址失败:缺少 upload_url': '照片上传失败,请稍后重试', '签发上传地址失败:缺少 upload_url': '照片上传失败,请稍后重试',
'获取 upload_id 失败': '照片上传失败,请稍后重试', '获取 upload_id 失败': '照片上传失败,请稍后重试',
'upload/url 响应无法解析': '照片上传失败,请稍后重试', 'upload/url 响应无法解析': '照片上传失败,请稍后重试',
生成失败: '这次没生成成功,请换个描述或照片再试', 生成失败: jingdongConfig.messages.generateFail,
提交生成失败: '提交失败了,请稍后重试', 提交生成失败: '提交失败了,请稍后重试',
没有生成结果: '这次没有生成出效果图,请再试一次', 没有生成结果: '这次没有生成出效果图,请再试一次',
生成超时: '生成时间有点久,请稍后重试', 生成超时: '生成时间有点久,请稍后重试',
@@ -32,6 +34,32 @@ const KNOWN: Record<string, string> = {
'product_id不在Agent开放分类': '当前产品暂不支持在线生图,请联系客服', 'product_id不在Agent开放分类': '当前产品暂不支持在线生图,请联系客服',
} }
/** 生图 / 编辑:内容策略单独翻译;Processing/ApiError 走场景兜底文案 */
const GENERATE_EDIT_RULES: Array<{ test: RegExp; tipKey: 'contentPolicyFail' | 'processingFail' }> = [
{
test: /content\s*policy|minor|public\s*figure|recognizable\s*public/i,
tipKey: 'contentPolicyFail',
},
{
test: /processing\s*failed|ApiError/i,
tipKey: 'processingFail',
},
]
/** 前端自抛、可原样映射的短文案(生图场景仍保留) */
const GENERATE_EDIT_KEEP = new Set([
'已取消生成',
'生成超时',
'生成超时,请稍后重试',
'提交生成失败',
'没有生成结果',
'请先上传照片',
'缺少可编辑的效果图',
'缺少会话信息,请刷新后重试',
'缺少产品信息,请刷新后重试',
'product_id不在Agent开放分类',
])
const PATTERN_RULES: Array<{ test: RegExp; tip: string }> = [ const PATTERN_RULES: Array<{ test: RegExp; tip: string }> = [
{ test: /timeout|超时|ETIMEDOUT|ECONNABORTED/i, tip: '等待超时,请稍后重试' }, { test: /timeout|超时|ETIMEDOUT|ECONNABORTED/i, tip: '等待超时,请稍后重试' },
{ test: /network|fetch failed|ERR_NETWORK|断网|网络/i, tip: '网络异常,请检查网络后重试' }, { test: /network|fetch failed|ERR_NETWORK|断网|网络/i, tip: '网络异常,请检查网络后重试' },
@@ -49,8 +77,8 @@ const PATTERN_RULES: Array<{ test: RegExp; tip: string }> = [
export type FriendlyErrorScene = 'generate' | 'edit' | 'upload' | 'inspect' | 'download' | 'common' export type FriendlyErrorScene = 'generate' | 'edit' | 'upload' | 'inspect' | 'download' | 'common'
const SCENE_FALLBACK: Record<FriendlyErrorScene, string> = { const SCENE_FALLBACK: Record<FriendlyErrorScene, string> = {
generate: '这次没生成成功,请换个描述或照片再试', generate: jingdongConfig.messages.generateFail,
edit: '这次调整没成功,请换个描述再试', edit: jingdongConfig.messages.editFail,
upload: '照片上传失败,请换一张或稍后重试', upload: '照片上传失败,请换一张或稍后重试',
inspect: '照片识别失败,请换一张或稍后重试', inspect: '照片识别失败,请换一张或稍后重试',
download: '下载失败,请换用其他浏览器,或长按效果图保存', download: '下载失败,请换用其他浏览器,或长按效果图保存',
@@ -86,11 +114,27 @@ function looksTechnical(text: string) {
return false return false
} }
function mapGenerateEditError(text: string, tip: string): string {
for (const rule of GENERATE_EDIT_RULES) {
if (!rule.test.test(text)) continue
// 内容策略用专用文案;Processing/ApiError 与其它失败一样走场景兜底
if (rule.tipKey === 'contentPolicyFail') {
return jingdongConfig.messages.contentPolicyFail
}
return tip
}
if (GENERATE_EDIT_KEEP.has(text) && KNOWN[text]) return KNOWN[text]
for (const key of GENERATE_EDIT_KEEP) {
if (key.length >= 4 && text.includes(key) && KNOWN[key]) return KNOWN[key]
}
// 生图/编辑:未识别的后端英文或其它错误,统一兜底
return tip
}
/** /**
* 任意错误 → 友好中文提示。 * 任意错误 → 友好中文提示。
* - 优先命中已知文案 / 规则 * - 生图/编辑:仅内容策略、Processing/ApiError 单独翻译,其余走 generateFail / editFail
* - 短中文业务提示可原样展示 * - 其它场景:已知文案 / 规则优先,技术性内容回落默认文案
* - 技术性内容回落场景默认文案
*/ */
export function friendlyError( export function friendlyError(
error: unknown, error: unknown,
@@ -101,6 +145,10 @@ export function friendlyError(
const text = rawMessage(error) const text = rawMessage(error)
if (!text) return tip if (!text) return tip
if (scene === 'generate' || scene === 'edit') {
return mapGenerateEditError(text, tip)
}
if (KNOWN[text]) return KNOWN[text] if (KNOWN[text]) return KNOWN[text]
for (const [key, value] of Object.entries(KNOWN)) { for (const [key, value] of Object.entries(KNOWN)) {
+11 -12
View File
@@ -17,7 +17,9 @@
<div v-if="msg.role === 'agent'" class="msg__avatar" aria-hidden="true"> <div v-if="msg.role === 'agent'" class="msg__avatar" aria-hidden="true">
<img :src="config.images.avatar" alt="" /> <img :src="config.images.avatar" alt="" />
</div> </div>
<div v-else class="msg__avatar msg__avatar--user" aria-hidden="true">柚</div> <div v-else class="msg__avatar msg__avatar--user" aria-hidden="true">
<img :src="config.images.userAvatar" alt="" />
</div>
<div class="msg__body"> <div class="msg__body">
<div v-if="msg.type === 'text'" class="msg__bubble"> <div v-if="msg.type === 'text'" class="msg__bubble">
@@ -1143,15 +1145,12 @@ onBeforeUnmount(() => {
} }
.msg__avatar--user { .msg__avatar--user {
display: inline-flex; background: #ffffff;
align-items: center;
justify-content: center; img {
background: #3a8e4d; object-fit: cover;
border: 0; object-position: center;
color: #fff; }
font-size: 13px;
font-weight: 600;
line-height: 1;
} }
.msg__body { .msg__body {
@@ -1182,7 +1181,7 @@ onBeforeUnmount(() => {
} }
.msg.is-user .msg__bubble { .msg.is-user .msg__bubble {
border-radius: 16px 16px 4px 16px; border-radius: 16px 4px 16px 16px;
} }
.msg:not(.is-user) .msg__bubble { .msg:not(.is-user) .msg__bubble {
@@ -1197,7 +1196,7 @@ onBeforeUnmount(() => {
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
padding: 10px; padding: 10px;
background: #f0f1f3; background: #e9e9eb;
box-shadow: none; box-shadow: none;
color: #222; color: #222;