From 86b87eeb9d3c176824dcc4a30789d2e659721286 Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Thu, 24 Sep 2026 10:30:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(ai-chat):=20=E8=81=8A=E5=A4=A9=20UI=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=20V3=20=E2=80=94=20=E5=90=8D=E7=A7=B0/?= =?UTF-8?q?=E5=A4=B4=E5=83=8F/=E6=97=B6=E9=97=B4=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E9=A1=B9=E6=B6=88=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CHAT_UI_DEFAULTS 同步后端 4 新键 (show_name/show_avatar/avatar/time_format/time_humanize) - 标题与 AI 头像按开关显隐, 自定义头像 (素材库 pic_path / URL) 优先于内置 - formatTime 支持 auto(智能分段)/full(完整) 与 humanizeTime 相对时间优先 (刚刚/N分钟前/N小时前/昨天/前天/M月D日/Y年M月D日) - i18n 中英各+5 键 --- common/js/ai-service.js | 11 +++- lang/en-us/ai-chat/index.js | 6 ++ lang/zh-cn/ai-chat/index.js | 6 ++ pages_tool/ai-chat/ai-chat-message.vue | 79 ++++++++++++++++++++++++-- 4 files changed, 96 insertions(+), 6 deletions(-) diff --git a/common/js/ai-service.js b/common/js/ai-service.js index 372c131..d0d21d7 100644 --- a/common/js/ai-service.js +++ b/common/js/ai-service.js @@ -451,7 +451,16 @@ const CHAT_UI_DEFAULTS = { ui_enable_attachment_types: ['image', 'file', 'audio', 'video'], ui_input_max_length: 500, ui_available_models: ['Auto'], - ui_enable_feedback: true + ui_enable_feedback: true, + // PR-CHAT-UI-CONFIG-V2 (2026-09-24): 与后端 Config::DEFAULT_UI_CONFIG 同步 + ui_assistant_name: '', + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 与后端 Config::DEFAULT_UI_CONFIG 同步 + ui_show_assistant_name: true, + ui_show_assistant_avatar: true, + ui_assistant_avatar: '', + ui_show_message_time: true, + ui_time_format: 'auto', + ui_time_humanize: false }; // chat_ui_config 自带短 TTL 缓存(60s, 与 service_config 同步); diff --git a/lang/en-us/ai-chat/index.js b/lang/en-us/ai-chat/index.js index e880b56..d24ad50 100644 --- a/lang/en-us/ai-chat/index.js +++ b/lang/en-us/ai-chat/index.js @@ -12,6 +12,12 @@ export const lang = { timeFormatToday: 'Today', timeFormatYesterday: 'Yesterday', timeFormatBeforeYesterday: 'Day before yesterday', + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): Humanized relative time (ui_time_humanize) + timeJustNow: 'Just now', + timeMinutesAgo: '{n} min ago', + timeHoursAgo: '{n} h ago', + timeMonthDay: '{m}/{d}', + timeYearMonthDay: '{y}/{m}/{d}', // ====== ai-chat-message ====== aiNickname: 'AI Assistant', diff --git a/lang/zh-cn/ai-chat/index.js b/lang/zh-cn/ai-chat/index.js index f5bda06..3668e11 100644 --- a/lang/zh-cn/ai-chat/index.js +++ b/lang/zh-cn/ai-chat/index.js @@ -12,6 +12,12 @@ export const lang = { timeFormatToday: '今天', timeFormatYesterday: '昨天', timeFormatBeforeYesterday: '前天', + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 人性化相对时间 (ui_time_humanize) + timeJustNow: '刚刚', + timeMinutesAgo: '{n}分钟前', + timeHoursAgo: '{n}小时前', + timeMonthDay: '{m}月{d}日', + timeYearMonthDay: '{y}年{m}月{d}日', // ====== ai-chat-message ====== aiNickname: '智能助手', diff --git a/pages_tool/ai-chat/ai-chat-message.vue b/pages_tool/ai-chat/ai-chat-message.vue index 9c8add5..cc87ba1 100644 --- a/pages_tool/ai-chat/ai-chat-message.vue +++ b/pages_tool/ai-chat/ai-chat-message.vue @@ -13,7 +13,9 @@ - {{ $lang('ai-chat.index.aiNickname') }} + + {{ chatUiConfig.ui_assistant_name || $lang('ai-chat.index.aiNickname') }} @@ -137,7 +139,8 @@ - + + - + {{ formatTime(message.timestamp) }} @@ -737,7 +740,16 @@ export default { ui_enable_attachment_types: ['image', 'file', 'audio', 'video'], ui_input_max_length: 500, ui_available_models: ['Auto'], - ui_enable_feedback: true + ui_enable_feedback: true, + // PR-CHAT-UI-CONFIG-V2 (2026-09-24): 与后端 Config::DEFAULT_UI_CONFIG 同步 + ui_assistant_name: '', + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 与后端 Config::DEFAULT_UI_CONFIG 同步 + ui_show_assistant_name: true, + ui_show_assistant_avatar: true, + ui_assistant_avatar: '', + ui_show_message_time: true, + ui_time_format: 'auto', + ui_time_humanize: false }, chatUiConfigLoaded: false, @@ -768,13 +780,18 @@ export default { } }, computed: { + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 后台配置了自定义头像则优先 ($util.img 兼容 pic_path 与完整 URL) aiAvatar() { + const custom = this.chatUiConfig && this.chatUiConfig.ui_assistant_avatar; + if (custom) return this.$util.img(custom); return this.$util.img(IMAGE_CONFIG.aiAvatar); }, defaultAvatar() { return this.$util.img(IMAGE_CONFIG.userAvatar); }, aiAvatarUrl() { + const custom = this.chatUiConfig && this.chatUiConfig.ui_assistant_avatar; + if (custom) return this.$util.img(custom); return this.$util.img(IMAGE_CONFIG.aiAvatar); }, chatMessagesStyle() { @@ -2316,7 +2333,10 @@ _handleStreamError(msg) { return html }, - // 格式化时间(人性化显示) + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 时间格式化支持后端配置 + // ui_time_format = 'auto' 智能分段(默认, 与历史行为一致): 今天 HH:mm / 昨天 / 前天 / 本年 M/D / 跨年 Y/M/D + // ui_time_format = 'full' 始终完整 YYYY-MM-DD HH:mm + // ui_time_humanize = true 微信式相对时间(优先于 format): 刚刚 / N分钟前 / N小时前 / 昨天 / 前天 / M月D日 / Y年M月D日 formatTime(timestamp) { if (!timestamp) return ''; @@ -2352,6 +2372,19 @@ _handleStreamError(msg) { const minutes = date.getMinutes().toString().padStart(2, '0'); const timeStr = `${hours}:${minutes}`; + // 人性化相对时间 (开启后优先于 ui_time_format) + if (this.chatUiConfig && this.chatUiConfig.ui_time_humanize) { + return this.humanizeTime(date, msgDate, today, timeStr); + } + + // 完整时间格式: 始终 YYYY-MM-DD HH:mm + if (this.chatUiConfig && this.chatUiConfig.ui_time_format === 'full') { + const mm = (date.getMonth() + 1).toString().padStart(2, '0'); + const dd = date.getDate().toString().padStart(2, '0'); + return `${date.getFullYear()}-${mm}-${dd} ${timeStr}`; + } + + // auto: 智能分段 (原有逻辑) if (msgDate.getTime() === today.getTime()) { return timeStr; } @@ -2373,6 +2406,42 @@ _handleStreamError(msg) { const yearStr = date.getFullYear().toString(); return `${yearStr}/${monthStr}/${dayStr} ${timeStr}`; }, + + // PR-CHAT-UI-CONFIG-V3 (2026-09-24): 微信式人性化相对时间 + // 刚刚 / N分钟前 / 今天内N小时前 / 昨天 HH:mm / 前天 HH:mm / 本年 M月D日 HH:mm / 跨年 Y年M月D日 HH:mm + humanizeTime(date, msgDate, today, timeStr) { + const diff = Date.now() - date.getTime(); + const oneMin = 60 * 1000; + const oneHour = 60 * oneMin; + + if (diff >= 0 && diff < oneMin) { + return this.$lang('ai-chat.index.timeJustNow'); + } + if (diff >= 0 && diff < oneHour) { + return this.$lang('ai-chat.index.timeMinutesAgo', { n: Math.floor(diff / oneMin) }); + } + // 今天内且已超过 1 小时 + if (msgDate.getTime() === today.getTime()) { + if (diff < 24 * oneHour) { + return this.$lang('ai-chat.index.timeHoursAgo', { n: Math.floor(diff / oneHour) }); + } + return timeStr; // 兜底(理论不可达: 同一天 diff 不可能 >= 24h) + } + const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000); + if (msgDate.getTime() === yesterday.getTime()) { + return `${this.$lang('ai-chat.index.timeFormatYesterday')} ${timeStr}`; + } + const beforeYesterday = new Date(today.getTime() - 2 * 24 * 60 * 60 * 1000); + if (msgDate.getTime() === beforeYesterday.getTime()) { + return `${this.$lang('ai-chat.index.timeFormatBeforeYesterday')} ${timeStr}`; + } + const m = date.getMonth() + 1; + const d = date.getDate(); + if (date.getFullYear() === new Date().getFullYear()) { + return `${this.$lang('ai-chat.index.timeMonthDay', { m, d })} ${timeStr}`; + } + return `${this.$lang('ai-chat.index.timeYearMonthDay', { y: date.getFullYear(), m, d })} ${timeStr}`; + }, // 格式化文件大小 formatFileSize(bytes) {