style(ai): 助手页参数面板改为「每组选项各占一行」横向滑动

上一版把文体+字数、参考素材+比例各塞进同一个 scroll-view,靠后那组会被
滑出屏幕外;且在 375px 小屏上文体/字数仍会换行堆叠成 3 行,把消息区挤掉
小半屏。改为**每组选项各自一个 scroll-x 行**:

- 写作:文体一行、字数一行
- 图片:参考素材一行(「添加附件」放最左,保证不被滑出屏幕)、比例一行
- 删掉不再需要的竖分隔线 .option-sep
- 同步收紧 mode-tags 间距(16rpx → 12rpx)

实测(375×667 复刻页,见 probe/layout-preview.html):

| | 参数区 | composer 总高 | 占屏 |
| --- | --- | --- | --- |
| 写作 改版前 | 118.2px(3 行) | 185.4px | 28% |
| 写作 改版后 | 86.6px(2 行) | 153.8px | 23% |
| 图片 改版前 | 149.8px | 217.0px | 33% |
| 图片 改版后 | 120.6px | 187.8px | 28% |

横向轨道实测:文体 356px / 字数 381px 超出 331px 可用宽 → 确实滚动而非换行;
参考素材 163px、比例 242px 均在 331px 内,无需滑动即可看全。

验证:verify-uniapp-assistant-template.js 新增 4 项布局断言(每组恰好独占一个
option-scroll、无混行、chip/label 有 flex-shrink:0、旧版布局无残留),全绿;
判别力经 5 处变异测试证伪(删整行 / 去 flex-shrink / 加回分隔线 /
混入别组选项 / 退回换行堆叠)。

Refs: .scratch/ai-assistant/issues/15-uniapp-assistant-modes-align-web.md
This commit is contained in:
2026-10-13 20:32:20 +08:00
parent 244f0c24d8
commit 3a0c099704
+109 -65
View File
@@ -112,51 +112,86 @@
{{ item.label }}
</view>
</view>
<view v-if="activeChatMode === 'writing'" class="option-panel">
<text class="option-label">文体</text>
<view
v-for="item in writingDocTypeOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': writingDocType === item.value, 'option-chip--disabled': loading }"
@tap="pickWritingDocType(item.value)"
>{{ item.label }}</view>
<text class="option-label">字数</text>
<view
v-for="item in writingWordCountOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': writingWordCount === item.value, 'option-chip--disabled': loading }"
@tap="pickWritingWordCount(item.value)"
>{{ item.label }}</view>
</view>
<!--
参数面板:手机屏窄,**每组选项各占一行、单行横向滑动**,不换行堆叠。
换行版在写作模式下要占 4 行(文体 2 行 + 字数 2 行),把消息区挤掉小半屏。
-->
<scroll-view
v-if="activeChatMode === 'writing'"
scroll-x
:show-scrollbar="false"
class="option-scroll"
>
<view class="option-track">
<text class="option-label">文体</text>
<view
v-for="item in writingDocTypeOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': writingDocType === item.value, 'option-chip--disabled': loading }"
@tap="pickWritingDocType(item.value)"
>{{ item.label }}</view>
</view>
</scroll-view>
<view v-if="activeChatMode === 'image'" class="option-panel">
<text class="option-label">图片比例</text>
<view
v-for="item in imageRatioOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': imageRatio === item.value, 'option-chip--disabled': loading }"
@tap="pickImageRatio(item.value)"
>{{ item.label }}</view>
</view>
<scroll-view
v-if="activeChatMode === 'writing'"
scroll-x
:show-scrollbar="false"
class="option-scroll"
>
<view class="option-track">
<text class="option-label">字数</text>
<view
v-for="item in writingWordCountOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': writingWordCount === item.value, 'option-chip--disabled': loading }"
@tap="pickWritingWordCount(item.value)"
>{{ item.label }}</view>
</view>
</scroll-view>
<view v-if="activeChatMode === 'image'" class="option-panel">
<text class="option-label">参考素材</text>
<view
class="option-chip"
:class="{ 'option-chip--disabled': !canPickImageFiles }"
@tap="chooseImageFiles"
>{{ uploadingFiles ? '上传中...' : '添加附件' }}</view>
<text class="attach-hint">
最多 {{ IMAGE_FILE_LIMIT }} 个,支持图片 / 视频 / 音频 / 文档
</text>
<view v-if="imageFiles.length" class="attach-list">
<view v-for="(item, index) in imageFiles" :key="item.id" class="attach-item">
<text class="attach-name">{{ item.name }}</text>
<view class="attach-remove" @tap="removeImageFile(index)">移除</view>
</view>
<!-- 「添加附件」放在最左:它是要点的主操作,不能被滑到屏幕外 -->
<scroll-view
v-if="activeChatMode === 'image'"
scroll-x
:show-scrollbar="false"
class="option-scroll"
>
<view class="option-track">
<text class="option-label">参考素材</text>
<view
class="option-chip"
:class="{ 'option-chip--disabled': !canPickImageFiles }"
@tap="chooseImageFiles"
>{{ uploadingFiles ? '上传中...' : '添加附件' }}</view>
<text class="option-hint">最多 {{ IMAGE_FILE_LIMIT }} 个</text>
</view>
</scroll-view>
<scroll-view
v-if="activeChatMode === 'image'"
scroll-x
:show-scrollbar="false"
class="option-scroll"
>
<view class="option-track">
<text class="option-label">比例</text>
<view
v-for="item in imageRatioOptions"
:key="item.value"
class="option-chip"
:class="{ 'option-chip--active': imageRatio === item.value, 'option-chip--disabled': loading }"
@tap="pickImageRatio(item.value)"
>{{ item.label }}</view>
</view>
</scroll-view>
<view v-if="activeChatMode === 'image' && imageFiles.length" class="attach-list">
<view v-for="(item, index) in imageFiles" :key="item.id" class="attach-item">
<text class="attach-name">{{ item.name }}</text>
<view class="attach-remove" @tap="removeImageFile(index)">移除</view>
</view>
</view>
@@ -1103,7 +1138,8 @@
return
}
uni.showActionSheet({
itemList: ['从相册选择图片', '从聊天记录选择文件'],
// 支持的类型写在选项里(面板上那行 hint 只留「最多 5 个」,省横向空间)
itemList: ['从相册选择图片', '从聊天记录选文件(视频/音频/文档)'],
success: (result) => {
if (result.tapIndex === 0) {
this.pickLocalImages()
@@ -1784,8 +1820,8 @@
.mode-tags {
display: flex;
flex-wrap: wrap;
gap: 14rpx;
margin-bottom: 16rpx;
gap: 12rpx;
margin-bottom: 12rpx;
}
.mode-tag {
@@ -1807,29 +1843,44 @@
opacity: 0.6;
}
/* 写作 / 图片模式的参数面板(文体、字数、图片比例、参考素材) */
.option-panel {
display: flex;
flex-wrap: wrap;
/*
写作 / 图片模式的参数面板。
手机屏窄,选项一律**单行横向滑动**(scroll-view + 不换行的 inline-flex 轨道),
不换行堆叠 —— 换行版在写作模式下要占 4 行,把消息区挤掉小半屏。
*/
.option-scroll {
width: 100%;
white-space: nowrap;
margin-bottom: 12rpx;
}
.option-track {
display: inline-flex;
align-items: center;
gap: 12rpx;
margin-bottom: 16rpx;
gap: 10rpx;
}
.option-label {
margin-right: 2rpx;
flex-shrink: 0;
font-size: 22rpx;
color: #8a7f79;
}
.option-hint {
flex-shrink: 0;
font-size: 20rpx;
color: #a59a94;
}
.option-chip {
padding: 8rpx 20rpx;
flex-shrink: 0;
padding: 10rpx 18rpx;
border-radius: 999rpx;
border: 1rpx solid rgba(20, 150, 242, 0.18);
background: rgba(255, 255, 255, 0.9);
color: #1496f2;
font-size: 22rpx;
line-height: 1.4;
line-height: 1.3;
}
.option-chip--active {
@@ -1842,28 +1893,21 @@
opacity: 0.5;
}
.attach-hint {
width: 100%;
font-size: 20rpx;
line-height: 1.5;
color: #a59a94;
}
.attach-list {
width: 100%;
margin-bottom: 12rpx;
}
.attach-item {
display: flex;
align-items: center;
gap: 12rpx;
padding: 10rpx 16rpx;
padding: 8rpx 14rpx;
border-radius: 16rpx;
background: rgba(20, 150, 242, 0.06);
}
.attach-item + .attach-item {
margin-top: 10rpx;
margin-top: 8rpx;
}
.attach-name {