chore:输入框样式

This commit is contained in:
2026-09-11 09:15:12 +08:00
parent 596e7cdb03
commit bc127a45e8

View File

@@ -226,73 +226,112 @@
<!-- 输入区域 (WorkBuddy IDE 风格: 圆角白底容器 + 顶部输入 + 底部工具栏) --> <!-- 输入区域 (新版: 顶部胶囊形输入条 + 底部 5 个图标) -->
<view class="input-area" :style="inputAreaStyle"> <view class="input-area" :style="inputAreaStyle">
<view class="input-card"> <view class="input-card">
<!-- 顶部输入区: textarea + 占位模式下显示的快捷指令提示 --> <!-- 顶部输入行: 语音图标 + 输入区 + 加号 + 发送 -->
<view class="input-row-top"> <view class="input-row-top">
<textarea <!-- 无文字时左侧显示语音图标,点击才打开语音面板 -->
v-model="inputText" <view v-if="!hasInputText" class="input-row-icon" @click="onVoiceClick">
class="message-input" <svg class="voice-icon-svg" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#1f1f1f" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
placeholder="今天帮你做些什么?" <path d="M10 12 h6 l6 -4 v16 l-6 -4 h-6 a2 2 0 0 1 -2 -2 v-4 a2 2 0 0 1 2 -2 z"/>
placeholder-class="message-input-placeholder" <path d="M24 10 c2 3 2 9 0 12"/>
:maxlength="500" </svg>
:auto-height="true"
:show-confirm-bar="false"
:adjust-position="false"
:cursor-spacing="150"
@confirm="sendMessage"
@input="onInput"
@linechange="onLineChange" />
<!-- 快捷指令: 仅在空输入时显示, 位于输入框右侧 -->
<view v-if="!inputText && !inputLineCount" class="quick-tips">
<text class="quick-tip" @click="onQuickTipClick('quote')">
<text class="quick-tip-icon">@</text>
<text>引用对话文件</text>
</text>
<text class="quick-tip-sep">/</text>
<text class="quick-tip" @click="onQuickTipClick('skill')">
<text>调用技能与指令</text>
</text>
</view> </view>
<!-- 扩大按钮 (输入行数过多时显示) --> <!-- 输入区: textarea 始终可点击输入,有文字时下方显示 Auto 选择器 -->
<button v-if="inputLineCount > 3" class="expand-btn" @click="openExpandEditor"> <view class="input-left-content" :class="{ 'with-voice-icon': !hasInputText }">
<text class="iconfont icon-expand">[ ]</text> <textarea
</button> v-model="inputText"
</view> class="message-input"
placeholder="发消息或按住说话"
placeholder-class="message-input-placeholder"
:maxlength="500"
:auto-height="true"
:show-confirm-bar="false"
:adjust-position="false"
:cursor-spacing="150"
@confirm="sendMessage"
@input="onInput"
@linechange="onLineChange" />
<view v-if="hasInputText" class="model-selector" @click="onToggleModelSelector">
<!-- 圆圈 @ 图标,H5/小程序通用 -->
<view class="model-icon-circle">
<text class="model-icon-text">@</text>
</view>
<text class="model-name">{{ selectedModel }}</text>
<text class="model-arrow">▾</text>
</view>
</view>
<!-- 底部工具栏 --> <view class="input-right-actions">
<view class="input-toolbar"> <button class="top-plus-btn" @click="showMoreTools">
<!-- 左侧: + 按钮 + 默认权限下拉 -->
<view class="toolbar-left">
<button class="tool-btn-plus" @click="showMoreTools">
<text class="plus-icon">+</text> <text class="plus-icon">+</text>
</button> </button>
<button class="tool-btn-with-text" @click="onTogglePermission">
<text class="perm-icon">☑</text> <!-- 有文字时显示发送按钮 -->
<text class="perm-text">默认权限</text> <button v-if="hasInputText" class="top-send-btn" @click="sendMessage">
<text class="arrow-icon">▾</text> <!-- H5/小程序都兼容:旋转箭头模拟向上的纸飞机 -->
<text class="send-plane-text">➤</text>
</button> </button>
</view> </view>
</view>
<!-- 右侧: emoji + 麦克风 + 发送按钮 --> <!-- 底部工具栏: 5 个图标按钮均匀分布 -->
<view class="toolbar-right"> <view class="input-toolbar">
<button class="emoji-btn" v-if="false" @click="toggleEmojiPanel"> <view class="toolbar-item" hover-class="toolbar-item--hover" @click="onToolbarItem('task')">
<text class="iconfont icon-smile">😊</text> <view class="toolbar-icon-svg">
</button> <!-- 任务: 黑底对话气泡(微信式) + 三个白点 -->
<button class="voice-btn" v-if="false" @click="onVoiceClick"> <svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<text class="iconfont" :class="voiceInputing ? 'icon-stop' : 'icon-voice'">🎤</text> <path d="M4 6 h22 a4 4 0 0 1 4 4 v12 a4 4 0 0 1 -4 4 h-15 l-7 5 v-5 h0 a4 4 0 0 1 -4 -4 v-12 a4 4 0 0 1 4 -4 z" fill="#1f1f1f"/>
</button> <circle cx="11" cy="16" r="1.6" fill="#fff"/>
<!-- 发送按钮: 圆形灰色, 内含向上箭头图标 --> <circle cx="16" cy="16" r="1.6" fill="#fff"/>
<button <circle cx="21" cy="16" r="1.6" fill="#fff"/>
class="send-btn" </svg>
:class="{ disabled: !canSendMessage }" </view>
@click="sendMessage" <text class="toolbar-text">任务</text>
:disabled="!canSendMessage"> </view>
<text class="send-icon">▲</text> <view class="toolbar-item" hover-class="toolbar-item--hover" @click="onToolbarItem('automation')">
</button> <view class="toolbar-icon-svg">
<!-- 自动化: 圆形 + 对勾 -->
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#1f1f1f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="16" cy="16" r="11"/>
<path d="M11 16 l4 4 l7 -8"/>
</svg>
</view>
<text class="toolbar-text">自动化</text>
</view>
<view class="toolbar-item" hover-class="toolbar-item--hover" @click="onToolbarItem('library')">
<view class="toolbar-icon-svg">
<!-- 资料库: 打开的书(两页 + 书脊) -->
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#1f1f1f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 7 c5 -2 10 -2 13 1 c3 -3 8 -3 13 -1 v18 c-5 -2 -10 -2 -13 1 c-3 -3 -8 -3 -13 -1 z"/>
<path d="M16 8 v18"/>
</svg>
</view>
<text class="toolbar-text">资料库</text>
</view>
<view class="toolbar-item" hover-class="toolbar-item--hover" @click="onToolbarItem('expert')">
<view class="toolbar-icon-svg">
<!-- 专家: 圆形表盘 + 时针分针 -->
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#1f1f1f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="16" cy="16" r="11"/>
<path d="M16 9 v7 l5 3"/>
</svg>
</view>
<text class="toolbar-text">专家</text>
</view>
<view class="toolbar-item" hover-class="toolbar-item--hover" @click="onToolbarItem('more')">
<view class="toolbar-icon-svg">
<!-- 更多: 2x2 网格方块(apps) -->
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#1f1f1f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="4" y="4" width="9" height="9" rx="1.5"/>
<rect x="19" y="4" width="9" height="9" rx="1.5"/>
<rect x="4" y="19" width="9" height="9" rx="1.5"/>
<rect x="19" y="19" width="9" height="9" rx="1.5"/>
</svg>
</view>
<text class="toolbar-text">更多</text>
</view> </view>
</view> </view>
</view> </view>
@@ -456,6 +495,9 @@ export default {
showNicknameEditor: false, // 昵称编辑弹窗控制 showNicknameEditor: false, // 昵称编辑弹窗控制
// AI头像错误状态 // AI头像错误状态
avatarError: false, avatarError: false,
// 当前选中的 AI 模型, 显示在输入框左侧(如 Auto)
selectedModel: 'Auto',
availableModels: ['Auto', 'GPT-4', 'Claude', '文心一言', '通义千问', 'Kimi'],
// AiChat API相关 // AiChat API相关
currentConversationId: null, currentConversationId: null,
@@ -512,6 +554,9 @@ export default {
const hasContent = this.inputText && this.inputText.trim() !== '' const hasContent = this.inputText && this.inputText.trim() !== ''
const hasEmoji = this.containsEmoji(this.inputText) const hasEmoji = this.containsEmoji(this.inputText)
return hasContent || hasEmoji return hasContent || hasEmoji
},
hasInputText() {
return this.inputText && this.inputText.trim() !== ''
} }
}, },
// 新增:组件销毁时清除所有定时器 // 新增:组件销毁时清除所有定时器
@@ -2096,6 +2141,25 @@ _handleStreamError(msg) {
} catch (e) { /* noop */ } } catch (e) { /* noop */ }
}, },
// 底部 5 图标工具栏点击: 任务 / 专家 / 资料库 / 自动化 / 更多
// - task / expert / library / automation: 触发 toolbar-click 事件(占位)
// - more: 复用 showMoreTools 触发更多功能弹窗
onToolbarItem(type) {
try {
switch (type) {
case 'task':
case 'expert':
case 'library':
case 'automation':
this.$emit('toolbar-click', { type })
break
case 'more':
this.showMoreTools()
break
}
} catch (e) { /* noop */ }
},
// 默认权限下拉点击: 占位交互, 后续接入权限弹窗 // 默认权限下拉点击: 占位交互, 后续接入权限弹窗
onTogglePermission() { onTogglePermission() {
try { try {
@@ -2112,6 +2176,14 @@ _handleStreamError(msg) {
} }
}, },
// 切换模型选择器: 在 availableModels 列表中循环选择
onToggleModelSelector() {
const list = this.availableModels || ['Auto']
const idx = list.indexOf(this.selectedModel)
const nextIdx = (idx + 1) % list.length
this.selectedModel = list[nextIdx]
},
// 打开扩大编辑器 // 打开扩大编辑器
openExpandEditor() { openExpandEditor() {
this.expandInputText = this.inputText this.expandInputText = this.inputText
@@ -3043,16 +3115,20 @@ _handleStreamError(msg) {
background: #f5f5f5 !important; background: #f5f5f5 !important;
color: #1f1f1f !important; color: #1f1f1f !important;
border: none !important; border: none !important;
border-radius: 16rpx !important; border-radius: 20rpx !important;
box-shadow: none !important; box-shadow: none !important;
padding: 14rpx 18rpx !important; padding: 20rpx 30rpx !important; // 加大内边距,让气泡更"大"
display: inline-block; display: inline-block;
word-break: break-word; word-break: break-word;
white-space: pre-wrap; white-space: pre-wrap;
line-height: 1.6; line-height: 1.7;
text-align: left; text-align: left;
max-width: 100%; max-width: 100%;
.message-text {
font-size: 20rpx !important; // 还原为用户消息原字号
}
&::before { &::before {
display: none !important; display: none !important;
content: none !important; content: none !important;
@@ -3166,244 +3242,232 @@ _handleStreamError(msg) {
transition: height 0.25s ease; transition: height 0.25s ease;
} }
/* 输入区域 (WorkBuddy IDE 风格: 圆角白底容器 + 顶部输入 + 底部工具栏) */ /* 输入区域 (新版: 顶部胶囊形输入条 + 底部 5 个图标均匀分布) */
.input-area { .input-area {
background: transparent; background: transparent;
padding: 12rpx 20rpx 16rpx; padding: 12rpx 20rpx 16rpx;
flex-shrink: 0; flex-shrink: 0;
box-sizing: border-box; box-sizing: border-box;
/* 圆角白底容器: 把输入框、占位提示、底部工具栏都包在一个带边框的卡片里 */
.input-card { .input-card {
background: #ffffff; background: transparent;
border: 1rpx solid #e5e7eb; border: none;
border-radius: 20rpx; border-radius: 0;
padding: 14rpx 16rpx 12rpx; padding: 0;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); box-shadow: none;
box-sizing: border-box; box-sizing: border-box;
} }
/* 顶部输入区: textarea + 占位模式下的 @ / / 快捷提示 */ /* 顶部输入横条: 胶囊形,左侧输入区 + 右侧操作按钮 */
.input-row-top { .input-row-top {
position: relative;
display: flex; display: flex;
align-items: flex-start; align-items: center;
min-height: 72rpx; justify-content: space-between;
background: #ffffff;
border-radius: 999rpx;
padding: 18rpx 14rpx 18rpx 32rpx;
min-height: 108rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
.message-input { /* 无文字时左侧语音图标,点击打开语音面板 */
flex: 1; .input-row-icon {
min-height: 56rpx; flex-shrink: 0;
max-height: 240rpx; width: 52rpx;
background: transparent !important; height: 52rpx;
border: none !important;
padding: 12rpx 8rpx 12rpx 4rpx;
font-size: 30rpx;
line-height: 1.5;
color: #1f1f1f;
box-sizing: border-box;
}
/* placeholder 样式: 浅灰色 */
.message-input-placeholder {
color: #999 !important;
font-size: 30rpx !important;
}
/* 占位模式下显示在输入框右侧的快捷指令链接 */
.quick-tips {
position: absolute;
top: 50%;
left: 8rpx;
transform: translateY(-50%);
display: flex; display: flex;
align-items: center; align-items: center;
pointer-events: none; /* 让 textarea 能接收点击 */ justify-content: center;
margin-right: 12rpx;
.quick-tip, .voice-icon-svg {
.quick-tip-sep { width: 36rpx;
font-size: 24rpx; height: 36rpx;
color: #1f6cff; display: block;
margin-right: 12rpx; }
pointer-events: auto; }
.quick-tip-icon { /* 输入区: textarea 在上,模型选择器在下 */
margin-right: 4rpx; .input-left-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
min-height: 72rpx;
padding-right: 12rpx;
&.with-voice-icon {
margin-left: 0;
}
.message-input {
width: 100%;
min-height: 44rpx;
max-height: 240rpx;
background: transparent !important;
border: none !important;
padding: 0 0 6rpx 0;
font-size: 34rpx;
line-height: 1.5;
color: #1f1f1f;
box-sizing: border-box;
}
.message-input-placeholder {
color: #999 !important;
font-size: 32rpx !important;
}
.model-selector {
align-self: flex-start;
display: flex;
align-items: center;
gap: 6rpx;
height: 36rpx;
padding: 0;
margin-top: 4rpx;
background: transparent;
.model-icon-circle {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
border: 2rpx solid #666666;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
.model-icon-text {
font-size: 18rpx;
color: #666666;
line-height: 1;
margin-top: 2rpx;
}
}
.model-name {
font-size: 26rpx;
color: #666666;
font-weight: 400;
line-height: 1;
}
.model-arrow {
font-size: 22rpx;
color: #999999;
line-height: 1;
margin-top: 2rpx;
} }
} }
.quick-tip-sep {
color: #999;
margin-right: 12rpx;
}
} }
/* textarea 有内容时, 占位链接隐藏 (CSS 简易判断) */ /* 右侧操作按钮: + 号 和 发送 */
.quick-tips { .input-right-actions {
opacity: 1;
}
/* 扩大按钮 */
.expand-btn {
flex-shrink: 0; flex-shrink: 0;
width: 56rpx; display: flex;
height: 56rpx; align-items: center;
gap: 8rpx;
}
.top-plus-btn {
flex-shrink: 0;
width: 76rpx;
height: 76rpx;
border-radius: 50%; border-radius: 50%;
background-color: #f5f5f5; background: transparent;
border: none; border: none;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-left: 8rpx; padding: 0;
.iconfont { .plus-icon {
font-size: 28rpx; font-size: 52rpx;
color: #666; color: #1f1f1f;
font-weight: 300;
line-height: 1;
}
&::after {
border: none;
}
}
.top-send-btn {
flex-shrink: 0;
width: 76rpx;
height: 76rpx;
border-radius: 50%;
background: #1f1f1f;
border: none;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
.send-plane-text {
color: #ffffff;
font-size: 34rpx;
line-height: 1;
transform: rotate(-90deg); // 箭头向上,呈向上纸飞机
display: inline-block;
margin-left: -2rpx; // 视觉居中
margin-top: -2rpx;
}
&::after {
border: none;
} }
} }
} }
/* 底部工具栏 */ /* 底部工具栏: 5 个图标按钮均匀分布 */
.input-toolbar { .input-toolbar {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-around;
margin-top: 6rpx; margin-top: 24rpx;
min-height: 64rpx; padding: 4rpx 0;
.toolbar-left, .toolbar-item {
.toolbar-right { flex: 1;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
} gap: 8rpx;
padding: 4rpx 0;
/* 左侧: + 圆形按钮 */ &.toolbar-item--hover,
.tool-btn-plus { &:active {
width: 56rpx; opacity: 0.55;
height: 56rpx; }
border-radius: 50%;
background-color: #f5f5f5;
border: none;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
.plus-icon { .toolbar-icon {
font-size: 32rpx; font-size: 44rpx;
color: #666;
line-height: 1; line-height: 1;
color: #1f1f1f;
} }
}
/* 左侧: 默认权限下拉 */ .toolbar-icon-svg {
.tool-btn-with-text { width: 44rpx;
height: 56rpx; height: 44rpx;
padding: 0 18rpx;
border-radius: 28rpx;
background-color: #f5f5f5;
border: none;
display: flex;
align-items: center;
margin-right: 12rpx;
.perm-icon {
font-size: 28rpx;
color: #1f6cff;
margin-right: 6rpx;
line-height: 1; line-height: 1;
} display: flex;
align-items: center;
justify-content: center;
.perm-text { svg {
font-size: 26rpx; width: 100%;
color: #333; height: 100%;
line-height: 1; display: block;
}
.arrow-icon {
font-size: 22rpx;
color: #999;
margin-left: 6rpx;
line-height: 1;
}
}
/* 右侧: emoji 按钮 */
.emoji-btn {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background-color: #f5f5f5;
border: none;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
padding: 0;
.iconfont {
font-size: 30rpx;
color: #666;
line-height: 1;
}
}
/* 右侧: 语音按钮 */
.voice-btn {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background-color: #f5f5f5;
border: none;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
padding: 0;
.iconfont {
font-size: 30rpx;
color: #666;
line-height: 1;
}
}
/* 发送按钮: 圆形灰色, 内含向上箭头图标 (WorkBuddy 风格) */
.send-btn {
flex-shrink: 0;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background-color: #d1d5db;
border: none;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
margin-left: 0;
color: #ffffff;
text-align: center;
white-space: nowrap;
line-height: 1;
transition: background-color 0.2s ease;
.send-icon {
font-size: 28rpx;
line-height: 1;
color: #ffffff;
}
&.disabled {
background-color: #d1d5db;
opacity: 0.65;
}
&:not(.disabled) {
background-color: #1f1f1f;
.send-icon {
color: #ffffff;
} }
} }
.toolbar-text {
font-size: 22rpx;
color: #1f1f1f;
line-height: 1;
}
} }
} }
} }