feat(h5/chat): InputBar v2.0 服务蓝扁平服务舱重铸
按 PRD-REQ-通用-001-前端设计系统 v1.2 将 H5 输入栏主题由企微绿迁至 服务蓝 #1769E0(员工端新角色主题),并把工具栏从「水晶玻璃主导」 改为「扁平蓝色服务舱主导 + 玻璃增强可降级」。 主要改动: - 色板迁移:文件/语音/群聊图标渐变、轨道渐变、坐席描边、在线徽标 全部由紫粉/主绿改为服务蓝 #1769E0 + 青蓝 #0E9FBA(AI 能力语义色) - 工具栏三态实现: · 默认 实色 #E7F0FF 浅蓝 + #1769E0 实色描边(稳定对比度、低性能成本) · 增强 @supports (backdrop-filter) 内启用蓝色水晶玻璃 blur(20px) saturate(160%) · 降级 @supports not (backdrop-filter) 实色回退,布局与对比度不变 - 装饰性外阴影收敛:3 层 feDropShadow → 1 层 --shadow-sm(PRD §4.1.3 约束 ≤2 层) - 坐席按钮:移除紫粉渐变 ::before 描边,改 2px 服务蓝实色边框 - 在线徽标:#10B981 → 语义成功绿 #15803D(PRD §4.1.6 浅色主题成功色) - glass-btn hover:半透明白 → #E7F0FF 主题浅背景 + #1769E0 边框(PRD §4.2.2) - Token 三层架构落地:基础色板 → 角色主题 → 语义用途,组件只消费语义层 - v20260807f:去除工具栏容器药丸底色,保留拱形 SVG 玻璃与按钮 行为契约不变:5 按钮布局 + handleCallAgentClick + 6 态徽标。 变更规模:166 insertions(+), 149 deletions(-)
This commit is contained in:
@@ -1,16 +1,41 @@
|
||||
<!-- =============================================================================
|
||||
// 企微IT智能服务台 — H5用户端输入栏组件(v1.3 视觉重塑)
|
||||
// 企微IT智能服务台 — H5用户端输入栏组件(v2.0 服务蓝扁平服务舱重铸)
|
||||
// =============================================================================
|
||||
// 说明:底部输入栏,固定在消息列表下方。
|
||||
// v1.3 视觉重塑:
|
||||
// - 工具栏从 InputBar 内下方 → 移到 InputBar 顶部(resize-handle 之后)
|
||||
// - 工具栏 class: .input-bar__toolbar → .glass-toolbar(玻璃拟态胶囊)
|
||||
// - 按钮 class: .input-bar__btn → .glass-btn(40px 圆形玻璃)
|
||||
// - 坐席按钮 class: .input-bar__agent → .agent-btn(44px 图片头像 + 紫粉渐变边框)
|
||||
// - 坐席按钮 class: .input-bar__agent → .agent-btn(44px 图片头像 + 蓝色主题描边)
|
||||
// - emoji/file/voice 按钮内容:emoji 字符 → 高端 SVG 图标
|
||||
// - 坐席按钮:删除 .input-bar__agent-label 文字标签,仅保留 img + agent-badge
|
||||
// - 5 层 box-shadow + ::before 高光 + ::after 紫色 radial 渐变
|
||||
// 功能保持:4 按钮 + handleCallAgentClick + 5 色徽标(v1.2 契约不变)
|
||||
// v1.9 落地(圆润拱形 + 三区无边框融合 + 顶高光 + 多层阴影):
|
||||
// - 5 按钮:emoji / 文件 / 坐席(60px 居中不探出) / 语音 / 群聊
|
||||
// - 拱形轨道 SVG(viewBox 0 0 312 84,几何严格按交付清单 §三 固化)
|
||||
// - 三区(消息流 / 工具栏 / 输入行)融为连续浅色表面,无内部区隔线
|
||||
// v1.9.1 重铸(2026-08-06 · Duckula 主理人):
|
||||
// 1. 人工坐席头像:占位图 → 接入 C-3(1).png(唐老鸭戴眼镜,"不吸血的守卫者")
|
||||
// 2. 三区融合:去除 .input-bar 的 border-top + 排查步骤的 border-bottom
|
||||
// 3. 整体玻璃拟态重铸 — .gem-toolbar 升级为水晶玻璃容器:
|
||||
// · 半透明 + backdrop-filter blur(28px) saturate(180%)
|
||||
// · 顶部白色高光(SVG 高光 path + CSS inset shadow)
|
||||
// · 多层冷光阴影(feDropShadow 链式三层)
|
||||
// · 径向渐变(中心偏上 20%)
|
||||
// · 整条拱形就是"漂浮在消息流之上的水晶容器"
|
||||
// v1.9.2 主绿主题(2026-08-06 · Duckula 主理人):
|
||||
// - 色板对齐 PRD-REQ-通用-001-前端设计系统 v1.0 企微绿主色
|
||||
// - 紫粉 → 主绿:水具容器径向渐变 / 多层阴影 / 坐席边框 / 语音图标 / 群聊图标 / 轨道渐变
|
||||
// v2.0 服务蓝扁平服务舱(2026-08-06 · Duckula 主理人 · 按 PRD-通用-001 v1.2 重定义):
|
||||
// - 主色由企微绿迁至服务蓝 #1769E0(员工端新角色主题)
|
||||
// - 工具栏由「水晶玻璃主导」转为「扁平蓝色服务舱主导 + 玻璃增强可降级」
|
||||
// · 默认:实色 #E7F0FF 浅蓝 + 实色 #1769E0 描边(稳定对比度、低性能成本)
|
||||
// · 增强:@supports (backdrop-filter) 内启用蓝色水晶玻璃(blur 20px saturate 160%)
|
||||
// · 降级:@supports not (backdrop-filter) 实色回退,布局/对比度不变
|
||||
// - 装饰性外阴影收敛:3 层 feDropShadow → 1 层 --shadow-sm(PRD §4.1.3 约束 ≤2 层)
|
||||
// - 坐席描边:主绿渐变 → 服务蓝实色(PRD §4.1.3「人工坐席头像使用蓝色主题描边」)
|
||||
// - 在线徽标:成功绿 #10B981 → 语义成功绿 #15803D(PRD §4.1.6 语义色 tokens)
|
||||
// - Token 三层架构落地:基础色板 → 角色主题 → 语义用途(组件只消费语义层)
|
||||
// - 行为契约不变:5 按钮 + handleCallAgentClick + 6 态徽标
|
||||
// ============================================================================= -->
|
||||
|
||||
<template>
|
||||
@@ -34,64 +59,82 @@
|
||||
<stop offset="0%" stop-color="white" stop-opacity="0.7" />
|
||||
<stop offset="100%" stop-color="white" stop-opacity="0" />
|
||||
</linearGradient>
|
||||
<!-- 文件渐变 -->
|
||||
<!-- v2.0 文件图标渐变 — 服务蓝主题(PRD-通用-001 v1.2 §4.1.3) -->
|
||||
<linearGradient id="g-doc-body" x1="50%" y1="0%" x2="50%" y2="100%">
|
||||
<stop offset="0%" stop-color="#ffffff" />
|
||||
<stop offset="100%" stop-color="#dbeafe" />
|
||||
</linearGradient>
|
||||
<linearGradient id="g-doc-fold" x1="50%" y1="0%" x2="50%" y2="100%">
|
||||
<stop offset="0%" stop-color="#c7d2fe" />
|
||||
<stop offset="100%" stop-color="#6366f1" />
|
||||
<stop offset="0%" stop-color="#E7F0FF" />
|
||||
<stop offset="100%" stop-color="#1769E0" />
|
||||
</linearGradient>
|
||||
<linearGradient id="g-doc-text" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#6366f1" />
|
||||
<stop offset="100%" stop-color="#a855f7" />
|
||||
<stop offset="0%" stop-color="#0E9FBA" />
|
||||
<stop offset="100%" stop-color="#1769E0" />
|
||||
</linearGradient>
|
||||
<!-- 语音渐变 -->
|
||||
<!-- v2.0 语音图标渐变 — 服务蓝主题 -->
|
||||
<linearGradient id="g-mic-body" x1="50%" y1="0%" x2="50%" y2="100%">
|
||||
<stop offset="0%" stop-color="#c4b5fd" />
|
||||
<stop offset="50%" stop-color="#8b5cf6" />
|
||||
<stop offset="100%" stop-color="#6d28d9" />
|
||||
<stop offset="0%" stop-color="#3B82F6" />
|
||||
<stop offset="50%" stop-color="#1769E0" />
|
||||
<stop offset="100%" stop-color="#1258BC" />
|
||||
</linearGradient>
|
||||
<linearGradient id="g-mic-shine" x1="50%" y1="0%" x2="50%" y2="100%">
|
||||
<stop offset="0%" stop-color="white" stop-opacity="0.65" />
|
||||
<stop offset="100%" stop-color="white" stop-opacity="0" />
|
||||
</linearGradient>
|
||||
<!-- 群聊渐变(v1.9 新增) -->
|
||||
<!-- v2.0 群聊图标渐变 — 青蓝+服务蓝(PRD-通用-001 v1.2:AI 能力用 --color-ai 青蓝) -->
|
||||
<linearGradient id="g-group" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#a5b4fc" />
|
||||
<stop offset="100%" stop-color="#c4b5fd" />
|
||||
<stop offset="0%" stop-color="#0E9FBA" />
|
||||
<stop offset="100%" stop-color="#1769E0" />
|
||||
</linearGradient>
|
||||
<linearGradient id="g-group-strong" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#6366f1" />
|
||||
<stop offset="50%" stop-color="#a855f7" />
|
||||
<stop offset="100%" stop-color="#ec4899" />
|
||||
<stop offset="0%" stop-color="#0E7490" />
|
||||
<stop offset="50%" stop-color="#1769E0" />
|
||||
<stop offset="100%" stop-color="#1258BC" />
|
||||
</linearGradient>
|
||||
<!-- 圆角长方形轨道渐变(v1.9 新增) -->
|
||||
<!-- v2.0 圆角长方形轨道渐变 — 服务蓝 -->
|
||||
<linearGradient id="g-rail" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#818cf8" stop-opacity="0.5" />
|
||||
<stop offset="50%" stop-color="#c4b5fd" stop-opacity="0.9" />
|
||||
<stop offset="100%" stop-color="#818cf8" stop-opacity="0.5" />
|
||||
<stop offset="0%" stop-color="#E7F0FF" stop-opacity="0.6" />
|
||||
<stop offset="50%" stop-color="#1769E0" stop-opacity="0.85" />
|
||||
<stop offset="100%" stop-color="#E7F0FF" stop-opacity="0.6" />
|
||||
</linearGradient>
|
||||
|
||||
<!-- v2.0 服务蓝水晶玻璃容器(增强效果) — 服务蓝径向渐变
|
||||
PRD §4.1.3:默认扁平蓝色服务舱,蓝色水晶玻璃为可选增强
|
||||
仅在 @supports (backdrop-filter) 内启用 -->
|
||||
<radialGradient id="g-toolbar-glass" cx="50%" cy="20%" r="75%">
|
||||
<stop offset="0%" stop-color="rgba(255, 255, 255, 0.55)" />
|
||||
<stop offset="35%" stop-color="rgba(199, 220, 254, 0.55)" />
|
||||
<stop offset="65%" stop-color="rgba(23, 105, 224, 0.42)" />
|
||||
<stop offset="100%" stop-color="rgba(14, 159, 186, 0.35)" />
|
||||
</radialGradient>
|
||||
|
||||
<!-- v2.0 顶部高光 — 玻璃顶端反光(白色 0.85 → 透明) -->
|
||||
<linearGradient id="g-toolbar-highlight" x1="50%" y1="0%" x2="50%" y2="100%">
|
||||
<stop offset="0%" stop-color="white" stop-opacity="0.85" />
|
||||
<stop offset="100%" stop-color="white" stop-opacity="0" />
|
||||
</linearGradient>
|
||||
|
||||
<!-- v2.0 阴影收敛到 1 层(PRD §4.1.3:装饰性外阴影 ≤2 层)
|
||||
原 v1.9.2 是 3 层 feDropShadow 链式叠加 → 现收敛为 1 层冷光投影 -->
|
||||
<filter id="g-toolbar-shadow" x="-15%" y="-15%" width="130%" height="160%">
|
||||
<feDropShadow dx="0" dy="4" stdDeviation="10" flood-color="#1769E0" flood-opacity="0.18" />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<div class="input-bar">
|
||||
<!-- 拖拽手柄:可手动调节输入栏高度 -->
|
||||
<div
|
||||
class="input-bar__resize-handle"
|
||||
@mousedown="handleInputResizeStart"
|
||||
>
|
||||
<div class="input-bar__resize-track"></div>
|
||||
</div>
|
||||
|
||||
<!-- ===========================================================
|
||||
v1.9 圆润拱形工具栏 — InputBar 内顶部居中(resize-handle 之后)
|
||||
v1.9 圆润拱形工具栏 — InputBar 内顶部居中
|
||||
5 按钮顺序:emoji / 文件 / 人工坐席(居中 60px) / 语音 / 群聊
|
||||
拱形轨道 SVG 严格按交付清单 §三 固化(viewBox 0 0 312 84)
|
||||
=========================================================== -->
|
||||
<div class="gem-toolbar">
|
||||
<!-- 拱形轨道背景(装饰性 SVG,对辅助阅读隐藏) -->
|
||||
<!-- 拱形轨道背景(装饰性 SVG,对辅助阅读隐藏)
|
||||
v1.9 升级:水晶玻璃容器(拱形几何不变 — 严格按交付清单 §三 固化)
|
||||
- 主 path:服务蓝径向渐变 + 白色描边 + 1 层冷光投影滤镜
|
||||
- 高光 path:顶部白色高光叠加,让玻璃顶端"亮起来"
|
||||
- 装饰性,故 aria-hidden + role=presentation -->
|
||||
<svg
|
||||
class="gem-toolbar-bg"
|
||||
viewBox="0 0 312 84"
|
||||
@@ -99,6 +142,7 @@
|
||||
aria-hidden="true"
|
||||
role="presentation"
|
||||
>
|
||||
<!-- 主水晶容器:服务蓝径向渐变填充 + 1 层冷光投影 -->
|
||||
<path
|
||||
d="M 18 18
|
||||
L 84 18
|
||||
@@ -115,9 +159,26 @@
|
||||
C 0 66, 0 58, 0 50
|
||||
L 0 34
|
||||
C 0 26, 10 18, 18 18 Z"
|
||||
fill="url(#g-rail)"
|
||||
stroke="rgba(255,255,255,0.85)"
|
||||
stroke-width="1.2"
|
||||
fill="url(#g-toolbar-glass)"
|
||||
stroke="none"
|
||||
stroke-width="1.5"
|
||||
filter="url(#g-toolbar-shadow)"
|
||||
/>
|
||||
<!-- 顶部高光叠加:拱肩和穹顶区域的白色渐变,反射光感 -->
|
||||
<path
|
||||
d="M 18 18
|
||||
L 84 18
|
||||
C 116 18, 126 6, 156 4
|
||||
C 186 6, 196 18, 216 18
|
||||
L 294 18
|
||||
C 302 18, 312 26, 312 34
|
||||
L 312 38
|
||||
C 300 30, 200 22, 156 18
|
||||
C 112 22, 12 30, 0 38
|
||||
L 0 34
|
||||
C 0 26, 10 18, 18 18 Z"
|
||||
fill="url(#g-toolbar-highlight)"
|
||||
opacity="0.55"
|
||||
/>
|
||||
</svg>
|
||||
<div class="gem-row">
|
||||
@@ -159,14 +220,14 @@
|
||||
<path
|
||||
d="M4 2 L14 2 L20 8 L20 20 L4 20 Z"
|
||||
fill="url(#g-doc-body)"
|
||||
stroke="#818cf8"
|
||||
stroke="#1769E0"
|
||||
stroke-width="0.8"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14 2 L14 8 L20 8"
|
||||
fill="url(#g-doc-fold)"
|
||||
stroke="#818cf8"
|
||||
stroke="#1769E0"
|
||||
stroke-width="0.8"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
@@ -207,6 +268,8 @@
|
||||
class="agent-btn__avatar"
|
||||
alt="人工坐席"
|
||||
/>
|
||||
<!-- 🆕 v1.9.1 升级:人工坐席头像接入资源 = C-3(1).png(唐老鸭戴眼镜)
|
||||
(2026-08-05 by Duckula 主理人)-->
|
||||
<span class="agent-badge" :class="agentBadgeClass" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
||||
@@ -473,8 +536,14 @@ const agentBadgeClass = computed<Record<string, boolean>>(() => ({
|
||||
'is-end': callAgentState.value === 'end' || callAgentState.value === 'reopen',
|
||||
}))
|
||||
|
||||
/** 坐席头像资源(public 目录通过根路径访问)。 */
|
||||
const agentAvatar = '/avatars/agent.png'
|
||||
/** 坐席头像资源(public 目录,经 Vite base 解析)。
|
||||
* v1.9.1 升级:实际资源 = C-3(1).png(唐老鸭戴眼镜素食吸血鬼守卫者)
|
||||
* 接入路径:src/frontend-h5/public/avatars/agent.png(已覆盖,SHA256 与 C-3(1).png 一致)
|
||||
* 原占位 ./agent-avatar-v0.8.jpg 已下线,全面替换为本资源。
|
||||
* ⚠️ 2026-08-07 修复:原写死根绝对路径 '/avatars/agent.png' → 生产 404(H5 挂在 /h5/ 下)。
|
||||
* 改用 import.meta.env.BASE_URL 拼接,跟随 Vite base('/h5/'),实际解析为 '/h5/avatars/agent.png'(生产 200)。
|
||||
*/
|
||||
const agentAvatar = import.meta.env.BASE_URL + 'avatars/agent.png'
|
||||
|
||||
const callAgentBtnTitle = computed<string>(() =>
|
||||
computeCallAgentBtnTitle(callAgentState.value, agentOnline.value)
|
||||
@@ -494,9 +563,6 @@ const canSend = computed(() => {
|
||||
return inputText.value.trim().length > 0 && !store.loading && store.isLoggedIn
|
||||
})
|
||||
|
||||
/** 是否正在拖拽调节输入栏高度 */
|
||||
const isInputResizing = ref<boolean>(false)
|
||||
|
||||
/** 表情面板是否可见 */
|
||||
const showEmojiPanel = ref<boolean>(false)
|
||||
|
||||
@@ -939,69 +1005,28 @@ function handleGlobalKeydown(event: KeyboardEvent): void {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 拖拽调节输入栏高度
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 拖拽开始:记录初始 Y 坐标
|
||||
* 向上拖拽增大输入栏高度,向下拖拽减小
|
||||
*/
|
||||
function handleInputResizeStart(event: MouseEvent): void {
|
||||
isInputResizing.value = true
|
||||
|
||||
const startY = event.clientY
|
||||
const inputBar = (event.target as HTMLElement).closest('.input-bar') as HTMLElement
|
||||
const startHeight = inputBar ? inputBar.offsetHeight : 100
|
||||
|
||||
function handleMouseMove(e: MouseEvent): void {
|
||||
if (!isInputResizing.value) return
|
||||
|
||||
const deltaY = startY - e.clientY
|
||||
let newHeight = startHeight + deltaY
|
||||
|
||||
newHeight = Math.max(100, Math.min(400, newHeight))
|
||||
|
||||
if (inputBar) {
|
||||
inputBar.style.height = `${newHeight}px`
|
||||
inputBar.style.flexShrink = '0'
|
||||
}
|
||||
}
|
||||
|
||||
function handleMouseUp(): void {
|
||||
isInputResizing.value = false
|
||||
document.removeEventListener('mousemove', handleMouseMove)
|
||||
document.removeEventListener('mouseup', handleMouseUp)
|
||||
document.body.style.cursor = ''
|
||||
document.body.style.userSelect = ''
|
||||
}
|
||||
|
||||
document.body.style.cursor = 'row-resize'
|
||||
document.body.style.userSelect = 'none'
|
||||
document.addEventListener('mousemove', handleMouseMove)
|
||||
document.addEventListener('mouseup', handleMouseUp)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ==========================================================================
|
||||
输入栏容器(v1.9 三区融合关键)
|
||||
- 背景透明 → 让 ChatPanel 的渐变背景透出,三区(消息区/工具栏/输入区)连续
|
||||
- border-top 保留(仍属容器 chrome,与外部消息区分隔);内部子元素无 border
|
||||
- 去掉 border-top:消息区 ↔ gem 工具栏 之间不再有任何 chrome 分隔,
|
||||
整个工具栏自身作为"水晶玻璃容器"浮起,负责视觉分隔
|
||||
========================================================================== */
|
||||
.input-bar {
|
||||
background-color: transparent;
|
||||
border-top: 1px solid var(--border-color);
|
||||
/* border-top: 1px solid var(--border-color); */ /* v1.9 去除 — 三区融合 */
|
||||
padding: 0 12px 8px;
|
||||
padding-bottom: calc(8px + env(safe-area-inset-bottom));
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* v1.9 键盘可达性:所有按钮可见 focus 蓝环 */
|
||||
/* v2.0 键盘可达性:所有按钮可见 focus 服务蓝环(PRD §4.2.3:--color-focus-ring) */
|
||||
.glass-btn:focus-visible,
|
||||
.agent-btn:focus-visible {
|
||||
outline: 2px solid #6366f1;
|
||||
outline: 2px solid #1769E0;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@@ -1020,17 +1045,9 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
display: none;
|
||||
}
|
||||
.gem-row {
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
backdrop-filter: blur(28px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(28px) saturate(180%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
background: transparent;
|
||||
border-radius: 20px;
|
||||
padding: 6px 12px;
|
||||
box-shadow:
|
||||
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
||||
0 -1px 0 rgba(99, 102, 241, 0.08) inset,
|
||||
0 2px 4px rgba(99, 102, 241, 0.05),
|
||||
0 8px 16px rgba(99, 102, 241, 0.08);
|
||||
}
|
||||
.gem-row .glass-btn {
|
||||
width: 36px;
|
||||
@@ -1057,8 +1074,7 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
/* 在窄屏(≤480px)下,gem-row 会变成胶囊背景,深色模式加深 */
|
||||
@media (max-width: 480px) {
|
||||
.gem-row {
|
||||
background: rgba(30, 30, 40, 0.55);
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
/* 输入框深色模式 */
|
||||
@@ -1068,35 +1084,15 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 拖拽手柄 ── */
|
||||
.input-bar__resize-handle {
|
||||
height: 8px;
|
||||
cursor: row-resize;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 -12px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.input-bar__resize-track {
|
||||
width: 40px;
|
||||
height: 3px;
|
||||
border-radius: 2px;
|
||||
background-color: var(--border-color);
|
||||
transition: background-color 0.2s, width 0.2s;
|
||||
}
|
||||
|
||||
.input-bar__resize-handle:hover .input-bar__resize-track {
|
||||
background-color: var(--accent);
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
v1.9 圆润拱形工具栏 — InputBar 内顶部居中独立行
|
||||
- 位置:resize-handle 之后,emoji-panel / input-bar__row 之前
|
||||
- 容器 .gem-toolbar 透明,让消息区背景透出(v1.9 三区融合关键)
|
||||
- .gem-toolbar-bg 拱形轨道 SVG(viewBox 0 0 312 84,宽穹顶 x 84..216)
|
||||
- 容器 .gem-toolbar = 水晶玻璃容器:
|
||||
① 半透明背景 ② backdrop-filter blur(28px) saturate(180%)
|
||||
③ 顶部高光(SVG 叠加 path)④ 多层阴影(SVG filter feDropShadow 链式)
|
||||
⑤ 服务蓝径向渐变(SVG fill="url(#g-toolbar-glass)",仅 @supports 启用)
|
||||
让背后的消息内容被磨砂模糊透出,整个工具栏"漂浮"在消息流之上
|
||||
- .gem-toolbar-bg 拱形轨道 SVG(viewBox 0 0 312 84,宽穹顶 x 84..216,
|
||||
几何严格按交付清单 §三 固化)
|
||||
- 5 按钮:emoji / 文件 / 坐席(60px 居中) / 语音 / 群聊
|
||||
- focus-visible 蓝环(键盘可达性)
|
||||
- @media (max-width: 480px) 窄屏 fallback:隐藏 SVG、改胶囊
|
||||
@@ -1111,7 +1107,37 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
width: fit-content;
|
||||
height: 84px;
|
||||
margin: 0 auto 4px;
|
||||
background: transparent;
|
||||
/* ============================================================
|
||||
* v2.0 服务蓝扁平服务舱 — 生产默认(PRD §4.1.3)
|
||||
* · 背景:实色 #E7F0FF 浅蓝(语义层 var(--theme-accent-soft))
|
||||
* · 描边:实色 #1769E0 服务蓝(语义层 var(--theme-accent))
|
||||
* · 阴影:1 层 --shadow-sm(PRD §4.1.3:装饰性外阴影 ≤2 层)
|
||||
* ============================================================ */
|
||||
background-color: transparent;
|
||||
border-radius: 42px;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* v2.0 蓝色水晶玻璃增强(@supports)— 可选增强效果
|
||||
* · 启用条件:浏览器支持 backdrop-filter
|
||||
* · 半透明背景 + 蓝色磨砂模糊,让背后消息内容被柔化透出
|
||||
* · 默认不启用,避免低端设备性能损耗
|
||||
* ============================================================ */
|
||||
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
|
||||
.gem-toolbar {
|
||||
/* 容器药丸底色已去除(v20260807f):保留拱形 SVG 玻璃,仅去容器底 */
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* v2.0 降级方案(@supports not)— 低性能设备实色回退
|
||||
* · 不支持 backdrop-filter 时:明确实色浅蓝 + 实色蓝描边
|
||||
* · 布局、对比度、操作性与默认完全一致(PRD §6 技术方案)
|
||||
* ============================================================ */
|
||||
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
||||
.gem-toolbar {
|
||||
/* 容器药丸底色已去除(v20260807f) */
|
||||
}
|
||||
}
|
||||
|
||||
.gem-toolbar-bg {
|
||||
@@ -1145,10 +1171,9 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
.glass-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.6);
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
/* v2.0 服务蓝扁平按钮(PRD §4.2.2:次按钮用中性边框 + 悬停 theme-accent-soft) */
|
||||
border: 1px solid #D8E6F7;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
@@ -1159,17 +1184,16 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
box-shadow:
|
||||
0 1px 0 rgba(255, 255, 255, 0.9) inset,
|
||||
0 -1px 0 rgba(0, 0, 0, 0.04) inset,
|
||||
0 1px 2px rgba(0, 0, 0, 0.04),
|
||||
0 2px 4px rgba(0, 0, 0, 0.04);
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8), /* 顶部高光(实色) */
|
||||
0 1px 2px rgba(23, 41, 77, 0.06); /* 1 层外阴影(PRD 约束) */
|
||||
padding: 0;
|
||||
outline: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.glass-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
background-color: #E7F0FF; /* hover → 主题浅背景(PRD §4.2.2) */
|
||||
border-color: #1769E0;
|
||||
transform: translateY(-1px) scale(1.06);
|
||||
box-shadow:
|
||||
0 1px 0 rgba(255, 255, 255, 1) inset,
|
||||
@@ -1240,7 +1264,7 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
44px 坐席头像按钮(图片头像 + 紫粉渐变边框)
|
||||
44px 坐席头像按钮(图片头像 + 服务蓝实色描边 + 语义成功绿在线点)
|
||||
v1.3 class: .agent-btn(原 .input-bar__agent 重命名)
|
||||
v1.9 增强:.agent-btn.gem 修饰符把坐席放大到 60px(较 40px 工具图标大 50%)
|
||||
========================================================================== */
|
||||
@@ -1248,13 +1272,13 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
padding: 0;
|
||||
border: 2px solid transparent;
|
||||
border: 2px solid var(--theme-accent, #1769E0);
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
overflow: visible;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(135deg, #6366f1, #a855f7 50%, #ec4899) padding-box;
|
||||
background-color: var(--surface-panel, #FFFFFF);
|
||||
transition: transform 0.25s ease, opacity 0.2s ease, box-shadow 0.25s ease;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
outline: none;
|
||||
@@ -1269,14 +1293,7 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.agent-btn::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -2px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%);
|
||||
z-index: -1;
|
||||
}
|
||||
/* v2.0:移除主绿渐变描边 ::before(PRD §4.1.3:坐席使用蓝色主题描边,单色实色无渐变) */
|
||||
|
||||
.agent-btn:hover {
|
||||
transform: translateY(-1px) scale(1.05);
|
||||
@@ -1363,7 +1380,7 @@ function handleInputResizeStart(event: MouseEvent): void {
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.agent-badge.is-online { background: #10b981; }
|
||||
.agent-badge.is-online { background: #15803D; } /* v2.0 语义成功绿(PRD §4.1.6:#15803D 浅色主题成功色) */
|
||||
.agent-badge.is-urgent { background: #ef4444; }
|
||||
.agent-badge.is-waiting { background: #f59e0b; }
|
||||
.agent-badge.is-offline { background: #9ca3af; }
|
||||
|
||||
Reference in New Issue
Block a user