wutong 4b83a95d2e fix: 修改未来到家以及我的社区的部分内容修订
- 未来到家:金刚区图标去底块并对齐首页尺寸;瀑布流默认展示全部小类商品
- 我的社区:岁银改临时事件并扩充各分类假数据;公告改资讯卡样式(阅读数+更新时间);
  轮播/横幅统一 300rpx 圆角、指示点右下角;tab 去灰底改红色横杠;默认页轮播换新图
- 首页:金刚区间距加大;推荐 tab 改为附近;扫一扫按钮转红色系;清理遗留 console.log

Claude-Session: https://claude.ai/code/session_01WQrg6u9Cp9sFPLF6vmbJDq
2026-07-08 18:17:12 +08:00

456 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
页面未来到家到家服务按设计稿重做
说明顶部红头品牌 + 城市 + 关键词搜索二级分类以金刚区展示
下面商品用瀑布流与首页好店一致两列图片按原始宽高比
大类到家服务 / 家政服务 tab 忽略金刚区改为铺开展示两大类下的全部小类
后端 /service/category/sub-list瀑布流默认展示全部小类的商品category_id=0 不过滤
-->
<template>
<view class="fh-page">
<!-- 顶部红头 -->
<view class="fh-hd" :style="{ paddingTop: statusBarTop + 'px' }">
<view class="fh-hd-top">
<view class="fh-back" @tap="goBack">
<u-icon name="arrow-left" color="#fff" size="36"></u-icon>
</view>
<view class="fh-brand">
<text class="fh-brand-title">未来到家</text>
<text class="fh-brand-sub">专业服务 · 品质到家</text>
</view>
</view>
<!-- 搜索栏 -->
<view class="fh-search">
<view class="fh-search-city">
<text class="fh-city-name">{{ cityName }}</text>
<text class="fh-city-arrow"></text>
</view>
<input class="fh-search-input" v-model="keyword" placeholder="空调清洗" placeholder-class="fh-search-ph"
confirm-type="search" @confirm="doSearch" />
<view class="fh-search-btn" @tap="doSearch">搜索</view>
</view>
</view>
<view class="fh-body">
<!-- 金刚区二级分类 -->
<view class="fh-grid" v-if="categoryList.length">
<view class="fh-grid-item" v-for="cat in categoryList" :key="cat.id" @tap="selectCate(cat)">
<image class="fh-grid-icon" :src="picUrl + cat.category_pic" mode="aspectFill" />
<text class="fh-grid-txt">{{ cat.category_name }}</text>
</view>
</view>
<!-- 商品瀑布流与首页好店一致两列图片按原始宽高比 -->
<view class="wf">
<view class="wf-col">
<view class="wf-card" v-for="item in leftCol" :key="item.id" @tap="toDetail(item)">
<image class="wf-img" :src="item.showImg" :style="{ height: item.imgH + 'rpx' }" mode="aspectFill" />
<view class="wf-meta">
<view class="wf-name">{{ item.service_name }}</view>
<view class="wf-desc" v-if="item.intro">{{ item.intro }}</view>
<text class="wf-tag" v-if="cateMap[item.category_id]">{{ cateMap[item.category_id] }}</text>
<view class="wf-foot">
<text class="wf-price" v-if="item.price_desc">{{ item.price_desc }}</text>
<text class="wf-book">去预约</text>
</view>
</view>
</view>
</view>
<view class="wf-col">
<view class="wf-card" v-for="item in rightCol" :key="item.id" @tap="toDetail(item)">
<image class="wf-img" :src="item.showImg" :style="{ height: item.imgH + 'rpx' }" mode="aspectFill" />
<view class="wf-meta">
<view class="wf-name">{{ item.service_name }}</view>
<view class="wf-desc" v-if="item.intro">{{ item.intro }}</view>
<text class="wf-tag" v-if="cateMap[item.category_id]">{{ cateMap[item.category_id] }}</text>
<view class="wf-foot">
<text class="wf-price" v-if="item.price_desc">{{ item.price_desc }}</text>
<text class="wf-book">去预约</text>
</view>
</view>
</view>
</view>
</view>
<view class="wf-more" v-if="hasMore && (leftCol.length || rightCol.length)">上拉加载更多</view>
<view class="wf-more" v-else-if="leftCol.length || rightCol.length">没有更多了</view>
<view class="fh-empty" v-if="!leftCol.length && !rightCol.length && !loadingMore">暂无服务</view>
</view>
</view>
</template>
<script>
import { request, picUrl, NavgateTo, menuButtonInfo } from '@/utils'
import { apiArr } from '@/api/homeService'
// 瀑布单列图片宽度rpx与首页好店一致 (750-60)/2 = 345
const WF_COL_W = 345
// 卡片文字区估算高度,仅用于两列高度均衡
const WF_META_H = 150
export default {
data() {
return {
picUrl,
statusBarTop: 0,
cityName: '定位中',
keyword: '',
categoryList: [],
cateMap: {}, // 分类 id → 名称,用作商品卡片的红色标签
currentCate: 0,
// 瀑布两列
leftCol: [],
rightCol: [],
colHeights: [0, 0],
page_num: 1,
page_size: 10,
hasMore: true,
loadingMore: false
}
},
onLoad() {
const menu = menuButtonInfo()
this.statusBarTop = menu.top || 0
const loc = uni.getStorageSync('location') || {}
this.cityName = loc.cityName || '定位中'
this.initData()
},
onPullDownRefresh() {
this.initData().finally(() => uni.stopPullDownRefresh())
},
onReachBottom() {
if (this.hasMore && !this.loadingMore) this.loadList(false)
},
methods: {
async initData() {
await this.loadCategory()
// 瀑布流默认展示全部小类的商品category_id=0 后端不过滤分类)
this.currentCate = 0
this.keyword = ''
await this.loadList(true)
},
async loadCategory() {
try {
// 两大类(到家1+家政2)全部小类合并,供金刚区铺开展示
const res = await request(apiArr.categorySubList, 'POST', {}, {}, false)
this.categoryList = (res && res.rows) ? res.rows : []
const map = {}
this.categoryList.forEach(c => { map[c.id] = c.category_name })
this.cateMap = map
} catch (e) {
this.categoryList = []
this.cateMap = {}
}
},
selectCate(cat) {
// 金刚区图标点击 → 打开服务目录页(左侧小类导航 + 右侧分组商品),定位到该小类
NavgateTo('/packages/homeService/catalog/index?cate_id=' + cat.id, { isLogin: false })
},
doSearch() {
// 关键词搜索:跨分类
this.currentCate = 0
this.loadList(true)
},
async loadList(reset) {
if (this.loadingMore) return
this.loadingMore = true
if (reset) {
this.page_num = 1
this.hasMore = true
this.leftCol = []
this.rightCol = []
this.colHeights = [0, 0]
}
try {
const res = await request(apiArr.serviceList, 'POST', {
// service_type 传 0(不限):金刚区含两大类小类,靠 category_id 唯一定位;搜索时跨两大类
service_type: 0,
category_id: this.currentCate,
keyword: this.keyword,
page_num: this.page_num,
page_size: this.page_size
}, {}, false)
const rows = (res && res.rows) ? res.rows : []
rows.forEach((item) => {
// 封面图可能是逗号分隔多张,列表取第一张
const cover0 = item.cover_pic ? String(item.cover_pic).split(',')[0] : ''
item.showImg = cover0 ? picUrl + cover0 : ''
})
this.hasMore = rows.length === this.page_size
if (this.hasMore) this.page_num++
await this.appendMasonry(rows)
} catch (e) {
console.warn('服务列表加载失败:', e)
} finally {
this.loadingMore = false
}
},
// 逐条量图片宽高比 → 追加到较矮的一列,制造瀑布(与首页好店一致)
async appendMasonry(rows) {
for (const item of rows) {
let ratio = 0.8
if (item.showImg) {
try {
const info = await new Promise((resolve, reject) => {
uni.getImageInfo({ src: item.showImg, success: resolve, fail: reject })
})
if (info && info.width) ratio = info.height / info.width
} catch (e) { /* 用默认比例 */ }
}
item.imgH = Math.round(WF_COL_W * ratio)
const target = this.colHeights[0] <= this.colHeights[1] ? 0 : 1
if (target === 0) this.leftCol.push(item)
else this.rightCol.push(item)
this.colHeights[target] += item.imgH + WF_META_H
}
},
toDetail(item) {
NavgateTo('/packages/homeService/detail/index?id=' + item.id)
},
goBack() {
uni.navigateBack({ delta: 1, fail: () => { NavgateTo('/pages/index2/index2') } })
}
}
}
</script>
<style scoped>
page { background: #f5f6f8; }
.fh-page { min-height: 100vh; background: #f5f6f8; }
/* ===== 顶部红头(吸顶:搜索栏不随页面滚动) ===== */
.fh-hd {
position: sticky;
top: 0;
z-index: 100;
/* 设计稿:横向红色渐变 90deg #FF1A1F → #FF634A */
background: linear-gradient(90deg, #ff1a1f 0%, #ff634a 100%);
padding-left: 28rpx;
padding-right: 28rpx;
padding-bottom: 28rpx;
}
.fh-hd-top {
position: relative;
display: flex;
align-items: center;
height: 80rpx;
}
.fh-back {
position: absolute;
left: 0;
top: 0;
height: 80rpx;
display: flex;
align-items: center;
padding-right: 16rpx;
}
.fh-brand {
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 56rpx;
}
.fh-brand-title {
/* 设计稿 33px ≈ 58rpx */
font-size: 58rpx;
font-weight: 700;
color: #fff;
letter-spacing: 2rpx;
}
.fh-brand-sub {
margin-top: 8rpx;
/* 设计稿 12px ≈ 21rpx */
font-size: 21rpx;
color: rgba(255, 255, 255, 0.92);
letter-spacing: 4rpx;
}
/* 搜索栏 */
.fh-search {
display: flex;
align-items: center;
height: 77rpx;
margin-top: 22rpx;
background: #fff;
border-radius: 42rpx;
padding: 0 8rpx 0 26rpx;
}
.fh-search-city {
display: flex;
align-items: center;
flex-shrink: 0;
/* 设计稿城市 16px ≈ 28rpx#111111 */
font-size: 28rpx;
color: #111;
max-width: 180rpx;
}
.fh-city-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fh-city-arrow {
margin-left: 6rpx;
font-size: 22rpx;
color: #666;
}
.fh-search-city::after {
content: '';
width: 2rpx;
height: 34rpx;
background: #d9d9d9;
margin: 0 20rpx;
}
.fh-search-input {
flex: 1;
/* 设计稿搜索词 15px ≈ 26rpx */
font-size: 26rpx;
color: #333;
}
.fh-search-ph { color: #a0a0a0; }
.fh-search-btn {
flex-shrink: 0;
/* 设计稿搜索按钮 64×36px ≈ 112×63rpx#FF3929radius 18px≈31rpx */
height: 63rpx;
line-height: 63rpx;
min-width: 112rpx;
text-align: center;
padding: 0 26rpx;
background: #ff3929;
color: #fff;
font-size: 26rpx;
font-weight: 700;
border-radius: 31rpx;
}
/* ===== 主体 ===== */
.fh-body {
position: relative;
margin-top: -12rpx;
padding: 20rpx 20rpx 40rpx;
}
/* 金刚区 */
.fh-grid {
display: flex;
flex-wrap: wrap;
background: #fff;
border-radius: 20rpx;
padding: 24rpx 6rpx 4rpx;
}
.fh-grid-item {
width: 20%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 26rpx;
}
.fh-grid-icon {
/* 与首页金刚区一致index2.css .grid-icon84rpx、圆角 24rpx无底块无边框 */
width: 84rpx;
height: 84rpx;
border-radius: 24rpx;
display: block;
}
.fh-grid-txt {
margin-top: 12rpx;
/* 设计稿分类文字 14px ≈ 24rpx#111111 */
font-size: 24rpx;
color: #111;
text-align: center;
}
/* ===== 瀑布流(与首页好店一致) ===== */
.wf {
display: flex;
align-items: flex-start;
margin-top: 20rpx;
}
.wf-col {
width: 345rpx;
}
.wf-col:first-child {
margin-right: 20rpx;
}
.wf-card {
background: #fff;
/* 设计稿卡片1px #EDEDED 描边radius 10px≈17rpx */
border: 1rpx solid #ededed;
border-radius: 17rpx;
overflow: hidden;
margin-bottom: 20rpx;
}
.wf-img {
width: 100%;
display: block;
background: #eee;
}
.wf-meta {
padding: 16rpx 14rpx;
}
.wf-name {
/* 设计稿标题 15px≈26rpx#111111 */
font-size: 26rpx;
font-weight: 700;
color: #111;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.wf-desc {
margin-top: 8rpx;
/* 设计稿描述 11px≈19rpx#777777 */
font-size: 19rpx;
color: #777;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/* 服务标签:浅底红框红字胶囊 */
.wf-tag {
display: inline-block;
margin-top: 12rpx;
background: #fff6f4;
border: 1rpx solid #ff4a38;
border-radius: 7rpx;
color: #ff3929;
font-size: 18rpx;
line-height: 1.4;
padding: 2rpx 10rpx;
}
.wf-foot {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 14rpx;
}
.wf-price {
/* 设计稿价格 16px≈28rpx#FF3929 */
font-size: 28rpx;
font-weight: 700;
color: #ff3929;
}
.wf-book {
flex-shrink: 0;
/* 设计稿预约按钮:纯红 #FF3929radius 15px≈26rpx */
background: #ff3929;
color: #fff;
font-size: 22rpx;
font-weight: 700;
padding: 10rpx 24rpx;
border-radius: 26rpx;
}
.wf-more {
text-align: center;
color: #999;
font-size: 24rpx;
padding: 24rpx 0 20rpx;
}
.fh-empty {
text-align: center;
color: #999;
font-size: 26rpx;
padding: 100rpx 0;
}
</style>