diff --git a/client/src/dom.ts b/client/src/dom.ts index 0ae5860..5132366 100644 --- a/client/src/dom.ts +++ b/client/src/dom.ts @@ -8,7 +8,7 @@ * - 输入区采用圆角容器包裹文本框与发送按钮 */ import { ResolvedConfig, RagSource } from './types'; -import { debounce, formatTime } from './utils'; +import { debounce, formatTime, formatHistoryTime } from './utils'; import { t } from './i18n'; import { DialogPlugin } from 'tdesign-web-components/lib/dialog/index.js'; // omi 的 render/h 用于创建带 on* 函数回调的组件(见 createEventful 说明) @@ -915,8 +915,11 @@ function createChatAction(wrapper: HTMLElement, text: string, msgId?: string, fe const el = actionEl as unknown as { actionBar: string[]; handleAction: (action: string, data: { event?: Event; active?: boolean }) => void; + tooltipProps: Record; }; el.actionBar = ['replay', 'copy', 'good', 'bad']; + // 浮层 portal 到 body:zIndex 越过弹窗(9999)防遮挡,overlayClassName 加 SDK 私有类用于补样式 + el.tooltipProps = { overlayClassName: 'csk-tooltip', zIndex: 10000 }; // copyText/comment 为 String 简单类型,须用 setAttribute(property 赋值在 omi 下静默失效) actionEl.setAttribute('copyText', text); actionEl.setAttribute('comment', feedback === 'up' ? 'good' : feedback === 'down' ? 'bad' : ''); @@ -1160,8 +1163,9 @@ export function renderHistoryList( const metaParts: string[] = []; if (item.roleName) metaParts.push(item.roleName); if (item.messageCount !== undefined) metaParts.push(`${item.messageCount} 条消息`); - if (item.lastMessageTime) metaParts.push(item.lastMessageTime); - else if (item.createdAt) metaParts.push(item.createdAt); + const timeStr = item.lastMessageTime || item.createdAt; + const timeText = formatHistoryTime(timeStr); + if (timeText) metaParts.push(timeText); metaEl.textContent = metaParts.join(' · '); info.appendChild(idEl); diff --git a/client/src/styles.ts b/client/src/styles.ts index 051451a..38a30cc 100644 --- a/client/src/styles.ts +++ b/client/src/styles.ts @@ -624,6 +624,26 @@ function getStyles(config: ResolvedConfig): string { .csk-launcher, .csk-teaser { box-sizing: border-box; } .csk-launcher *, .csk-teaser * { box-sizing: border-box; } +/* ===== tooltip 浮层(t-popup portal 到 body,light DOM)样式补注入 ===== + * .t-tooltip 样式在 globalCSS(constructable stylesheet)里只对 shadow DOM 生效, + * 但浮层 portal 到 document.body 是 light DOM,故补注入;用 csk-tooltip 私有类避免污染宿主。 + * 来源:tdesign-web-components v1.2.10 的 _chunks/dep-a3fbe4be.js(css_248z)。 */ +.csk-tooltip .t-popup__content { + display: inline-block; + border: 0; + z-index: 5600; + margin-bottom: 1px; + max-width: 480px; + word-break: break-word; + box-sizing: border-box; + border-radius: var(--td-radius-medium); + color: var(--td-text-color-anti); + background: var(--td-gray-color-13); + box-shadow: inset 0 0.5px 0 var(--td-gray-color-9), inset 0.5px 0 0 var(--td-gray-color-9), inset 0 -0.5px 0 var(--td-gray-color-9), inset -0.5px 0 0 var(--td-gray-color-9); +} +.csk-tooltip .t-popup__arrow { background: inherit; height: auto; } +.csk-tooltip .t-popup__arrow::before { background: inherit; } + /* ===== t-tag(light DOM 组件)样式补注入 ===== * t-tag 是 tdesign-web-components 的 light DOM 组件(isLightDOM: true),其 .t-tag * 样式定义在 globalCSS 的 constructable stylesheet 里,但 globalCSS 只对 shadow DOM diff --git a/client/src/utils.ts b/client/src/utils.ts index 3d0d3d0..fb712a2 100644 --- a/client/src/utils.ts +++ b/client/src/utils.ts @@ -40,6 +40,27 @@ export function formatTime(timestamp: number): string { return `${hh}:${mm}`; } +/** 格式化历史会话时间:今天/昨天显示 HH:mm,同年显示 MM-DD HH:mm,跨年显示 YYYY-MM-DD HH:mm */ +export function formatHistoryTime(timeStr: string | undefined): string { + if (!timeStr) return ''; + const d = new Date(timeStr); + if (isNaN(d.getTime())) return timeStr; // 解析失败原样返回,避免破坏展示 + const pad = (n: number) => String(n).padStart(2, '0'); + const hh = pad(d.getHours()); + const mm = pad(d.getMinutes()); + const now = new Date(); + const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime(); + const yesterdayStart = todayStart - 86400000; + const ts = d.getTime(); + // 今天或昨天:只显示时分 + if (ts >= yesterdayStart) return `${hh}:${mm}`; + const md = `${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; + // 今年内:月-日 时分 + if (d.getFullYear() === now.getFullYear()) return `${md} ${hh}:${mm}`; + // 跨年:完整年月日 时分 + return `${d.getFullYear()}-${md} ${hh}:${mm}`; +} + /** 获取当前时间戳(毫秒) */ export function now(): number { return Date.now();