实现ui问题

This commit is contained in:
2026-08-31 18:11:01 +08:00
parent 18ee29e422
commit 18935ae223
6 changed files with 104 additions and 60 deletions
+11 -7
View File
@@ -58,6 +58,8 @@ buildUrl(ASSET_BASE + 'logo.png')
| PingFang SC/ 文件夹(7 个字重 ttf,见 2.3 | fonts/PingFang-Regular.subset.ttf 等(已生成,见 2.3 | 全局字体 |
> 中文文件名由 buildUrl/uni.request 自动 URL 编码,三端均可正常访问;只有字体目录用英文名 `fonts/`。
>
> Figma 导出的小图标(UI-009/0010)为本地静态资源,不上传服务器:`static/icons/products/icon_search.png`48×48@3x)、`static/icons/products/icon_filter.png`54×54@3x)。
### 2.3 字体方案
@@ -213,14 +215,16 @@ uni.loadFontFace({
### UI-009 产品页 · 搜索栏 · 图标与搜索按钮(P1)
- 文件:[SearchBar.vue](pages/products/components/SearchBar.vue)
- 方案:
1. 替换现有搜索图标为设计稿图标(**注意:切图文件夹内暂无搜索图标,需向设计索取或从设计稿导出**
2. 搜索框右侧增加"搜索"按钮,样式按设计稿
- 方案(按 Figma node-id=1962-143
1. emoji 🔍 替换为设计稿导出的 `icon_search.png`31rpxFigma 3 倍图 48×48
2. 搜索框右侧增加"搜索"按钮96×54rpx、`#FF6800`、圆角 27rpx、白字 25rpx,距框边缘 4rpx,点击触发搜索
3. 搜索框 209×32px → 402×62rpx`#F5F5F5` 圆角 31rpx;占位文案"搜索产品" `#929292` 25rpx;上下留白 6px→12rpx
### UI-0010 产品页 · 搜索栏 · 筛选被遮挡(P1)
- 文件:[SearchBar.vue](pages/products/components/SearchBar.vue) / [products.vue](pages/products/products.vue)
- 方案:参考设计稿调整搜索栏与筛选按钮布局(层级/宽度/间距),确保筛选按钮完整可见可点
- 文件:[SearchBar.vue](pages/products/components/SearchBar.vue) / [products.vue](pages/products/products.vue) / [products.css](pages/products/products.css)
- 被遮挡原因:筛选按钮原在搜索行右侧,小程序胶囊按钮恰好覆盖该区域
- 方案(按设计稿+实际确认):筛选入口与已选标签合并为**同一行**([ActiveFilters.vue](pages/products/components/ActiveFilters.vue) 重构):`[筛选图标 35rpx] [已选标签 scroll-x 横向滚动不换行] [清除(有标签才显示)]`;搜索行右侧留空避开胶囊;FilterDrawer 弹窗逻辑不变(入口 emit `open` → 父组件 `toggleFilter`
### UI-0011 产品页 · 国家分类 · 间距(P3)
@@ -270,8 +274,8 @@ uni.loadFontFace({
| UI-006 | ✅ 已改 | [WhyChoose.vue](pages/index/components/WhyChoose.vue):标题"为什么选择Inkrecah"→"为什么选择Inkreach";卡片去掉 margin-bottom,上下间距统一用 gap 20rpx 与左右一致;区块上下留白对称(96rpx) |
| UI-007 | ✅ 已改 | [CompanyIntro.vue](pages/index/components/CompanyIntro.vue) 背景图改用远程切图原图 公司简介背景.png |
| UI-008 | ✅ 已改 | CompanyIntro.vue `.phone-text` 字号 23rpx → 31rpx16号) |
| UI-009 | ⏸ 暂缓 | 等设计/Figmanode-id=1962-143 |
| UI-0010 | ⏸ 暂缓 | 等设计/Figmanode-id=1962-143 |
| UI-009 | ✅ 已改 | [SearchBar.vue](pages/products/components/SearchBar.vue)emoji 🔍 → Figma 导出 icon_search.png31rpx);新增橙色"搜索"按钮(96×54rpx `#FF6800` 圆角 27rpx,点击/键盘确认均触发搜索);搜索框 402×62rpx `#F5F5F5` 圆角 31rpx,占位"搜索产品" 25rpx `#929292` |
| UI-0010 | ✅ 已改 | 筛选入口从搜索行(被胶囊遮挡)移至商品区顶部;[ActiveFilters.vue](pages/products/components/ActiveFilters.vue) 重构为一行布局:筛选图标 + 已选标签横向滚动(scroll-x 不换行)+ 清除按钮,FilterDrawer 逻辑不变 |
| UI-0011 | ✅ 已改 | [CountryBar.vue](pages/products/components/CountryBar.vue):国旗与名称间距 20rpx → 8rpx4px);标签上下 row-gap 16rpx → 20rpx+2px |
| UI-0012 | ✅ 已改 | [products.css](pages/products/products.css) 页面背景 + [ProductGrid.vue](pages/products/components/ProductGrid.vue) 右侧内容区背景 → #ECECEC |
| UI-0013 | ✅ 已改 | tab_product_gray/orange.png 由 57×57 放大至 72×72Pillow LANCZOS),与 home 图标一致 |
+53 -16
View File
@@ -1,11 +1,27 @@
<template>
<!-- 已选筛选标签 - Figma 1519:250 圆角 60px -->
<view class="active-filters" id="activeFilters" v-if="list.length > 0">
<!-- 筛选条件条[筛选图标] [已选标签横向滚动] [清除] 同一行防换行 -->
<view class="active-filters" id="activeFilters">
<!-- 筛选入口打开筛选抽屉 -->
<view class="filter-entry" @tap="onOpen">
<image
class="filter-entry-icon"
src="/static/icons/products/icon_filter.png"
mode="aspectFit"
/>
</view>
<!-- 已选标签横向滚动不换行 -->
<scroll-view class="tags-scroll" scroll-x>
<view class="tags-inner">
<view class="active-filter-tag" v-for="(item, index) in list" :key="index">
<text class="filter-text">{{ item.label }}</text>
<text class="filter-remove" @tap="onRemove(item.key)">×</text>
</view>
<view class="clear-all" @tap="onClearAll">清除全部</view>
</view>
</scroll-view>
<!-- 清除有标签时才显示 -->
<view class="clear-all" v-if="list.length > 0" @tap="onClearAll">清除</view>
</view>
</template>
@@ -19,7 +35,7 @@ export default {
}
},
mounted() {
// 首次测量(可能为 0,因为 v-if 可能为 false
// 首次测量自身高度给父组件布局用
this.$nextTick(() => this.emitHeight())
},
watch: {
@@ -30,11 +46,6 @@ export default {
},
methods: {
emitHeight() {
// v-if 为 false 时 #activeFilters 不存在,返回 0
if (!this.list || this.list.length === 0) {
this.$emit('height-change', 0)
return
}
const query = uni.createSelectorQuery().in(this)
query.select('#activeFilters').boundingClientRect()
query.exec((res) => {
@@ -45,6 +56,9 @@ export default {
}
})
},
onOpen() {
this.$emit('open')
},
onRemove(key) {
this.$emit('remove', key)
},
@@ -56,26 +70,48 @@ export default {
</script>
<style scoped>
/* 顶部筛选条 - 白底,不占高度时隐藏 */
/* 顶部筛选条 - 白底,筛选图标 + 横向滚动标签 + 清除,同一行 */
.active-filters {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16rpx;
padding: 20rpx 20rpx;
padding: 16rpx 20rpx;
background: #ffffff;
border-bottom: 1rpx solid #eeeeee;
}
/* 单个标签 - padding 6px 10px 圆角 60px */
.active-filter-tag {
/* 筛选入口图标(设计稿 18x18px → 35rpx */
.filter-entry {
display: flex;
align-items: center;
padding: 8rpx 16rpx 8rpx 0;
flex-shrink: 0;
}
.filter-entry-icon {
width: 35rpx;
height: 35rpx;
}
/* 标签区:横向滚动不换行 */
.tags-scroll {
flex: 1;
min-width: 0;
white-space: nowrap;
}
.tags-inner {
display: inline-flex;
align-items: center;
gap: 16rpx;
padding: 4rpx 0;
}
/* 单个标签 - padding 6px 10px 圆角 60px,不换行 */
.active-filter-tag {
display: inline-flex;
align-items: center;
gap: 8rpx;
padding: 12rpx 20rpx;
background: #ffffff;
border: 1rpx solid #ff6800;
border-radius: 60rpx;
line-height: 1.2;
flex-shrink: 0;
}
/* 文字 12px Medium 橙色 */
.filter-text {
@@ -88,7 +124,8 @@ export default {
color: #ff6800;
}
.clear-all {
margin-left: auto;
padding-left: 16rpx;
flex-shrink: 0;
font-size: 24rpx;
color: #999999;
}
+34 -32
View File
@@ -2,19 +2,17 @@
<!-- 搜索栏 -->
<view class="search-bar" id="searchBar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="search-input-wrap">
<text class="search-icon">🔍</text>
<image class="search-icon" src="/static/icons/products/icon_search.png" mode="aspectFit" />
<input
class="search-input"
placeholder="搜索品"
placeholder="搜索品"
placeholder-class="search-placeholder"
:value="keyword"
@input="onInput"
@blur="onBlur"
@confirm="onConfirm"
/>
</view>
<view class="filter-btn" @tap="onFilter">
<text class="filter-icon"></text>
<text class="filter-text">筛选</text>
<view class="search-btn" @tap="onSearch">搜索</view>
</view>
</view>
</template>
@@ -61,56 +59,60 @@ export default {
onBlur() {
this.$emit('blur')
},
onFilter() {
this.$emit('filter')
onConfirm() {
// 键盘确认键与搜索按钮同一行为
this.$emit('blur')
},
onSearch() {
this.$emit('search')
}
}
}
</script>
<style scoped>
/* 设计稿:左右留白 10px(20rpx),上下留白 6px(12rpx),搜索框 209x32px(402x62rpx) */
.search-bar {
display: flex;
align-items: center;
gap: 20rpx;
padding: 20rpx 32rpx;
padding: 12rpx 20rpx;
background: #ffffff;
border-bottom: 2rpx solid #f5f5f5;
box-sizing: border-box;
}
.search-input-wrap {
flex: 1;
display: flex;
align-items: center;
height: 72rpx;
padding: 0 24rpx;
width: 402rpx;
height: 62rpx;
padding: 0 4rpx 0 21rpx;
background: #f5f5f5;
border-radius: 36rpx;
border-radius: 31rpx;
box-sizing: border-box;
}
.search-icon {
font-size: 28rpx;
margin-right: 12rpx;
width: 31rpx;
height: 31rpx;
flex-shrink: 0;
margin-right: 8rpx;
}
.search-input {
flex: 1;
font-size: 26rpx;
min-width: 0;
font-size: 25rpx;
color: #333333;
}
.search-placeholder {
color: #999999;
color: #929292;
}
.filter-btn {
/* 设计稿:搜索按钮 50x28px(96x54rpx)#FF6800,圆角 14px(27rpx),距边缘 2px(4rpx) */
.search-btn {
display: flex;
align-items: center;
gap: 8rpx;
padding: 12rpx 20rpx;
font-size: 26rpx;
color: #666666;
}
.filter-icon {
font-size: 28rpx;
}
.filter-text {
font-size: 26rpx;
justify-content: center;
width: 96rpx;
height: 54rpx;
flex-shrink: 0;
background: #ff6800;
border-radius: 27rpx;
font-size: 25rpx;
color: #ffffff;
}
</style>
+3 -2
View File
@@ -6,7 +6,7 @@
:keyword="searchKeyword"
@input="onSearchInput"
@blur="onSearchBlur"
@filter="toggleFilter"
@search="onSearchBlur"
@height-change="onSearchBarHeight"
/>
@@ -29,9 +29,10 @@
<!-- 右侧内容区:上方筛选条件 + 下方商品滚动区 -->
<view class="right-wrap">
<!-- 已选筛选标签(只在右侧顶部出现,不挤压左边) -->
<!-- 筛选条件条筛选图标 + 已选标签横向滚动 + 清除同一行 -->
<ActiveFilters
:list="activeFilters"
@open="toggleFilter"
@remove="removeFilter"
@clear-all="clearAllFilters"
@height-change="onActiveFiltersHeight"
Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B