294 lines
7.9 KiB
JavaScript
294 lines
7.9 KiB
JavaScript
// 服务页面 - 按照Figma设计实现
|
||
const api = require('../../utils/api')
|
||
const config = require('../../config/index')
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 44,
|
||
navBarHeight: 44,
|
||
totalNavHeight: 88,
|
||
searchText: '',
|
||
hasNotification: true,
|
||
totalUnread: 0,
|
||
|
||
// 轮播图 - 从后台素材管理API加载
|
||
banners: [],
|
||
swiperHeight: 400,
|
||
|
||
// 服务类型 - 6个
|
||
serviceTypes: [
|
||
{ id: 'points', name: '礼品商城', icon: '/images/fuw-shangcheng.png', bgColor: '#FFF7ED' },
|
||
{ id: 'merchants', name: '合作商家', icon: '/images/fuw-shangjia.png', bgColor: '#FFF1F2' },
|
||
{ id: 'eldercare', name: '智慧康养', icon: '/images/fuw-kangyang.png', bgColor: '#F0FDFA' },
|
||
{ id: 'custom', name: '定制服务', icon: '/images/fuw-dingzhi.png', bgColor: '#F0F9FF' },
|
||
{ id: 'academy', name: '心伴学堂', icon: '/images/fuw-pinpai.png', bgColor: '#F5F3FF' },
|
||
{ id: 'brand', name: '关于品牌', icon: '/images/fuw-aixin.png', bgColor: '#FFF1F2' }
|
||
],
|
||
|
||
// 内容列表 (通用)
|
||
listData: [],
|
||
isLoading: false,
|
||
page: 1,
|
||
hasMore: true,
|
||
|
||
// 审核状态
|
||
auditStatus: 0
|
||
},
|
||
|
||
onLoad() {
|
||
const systemInfo = wx.getSystemInfoSync()
|
||
const statusBarHeight = systemInfo.statusBarHeight || 44
|
||
const menuButton = wx.getMenuButtonBoundingClientRect()
|
||
const navBarHeight = menuButton.height + (menuButton.top - statusBarHeight) * 2
|
||
const totalNavHeight = statusBarHeight + navBarHeight
|
||
|
||
this.setData({
|
||
statusBarHeight,
|
||
navBarHeight,
|
||
totalNavHeight
|
||
})
|
||
|
||
// 加载Banner配置
|
||
this.loadBanners()
|
||
|
||
// 加载合作商家列表
|
||
this.loadListData()
|
||
},
|
||
|
||
/**
|
||
* 轮播图图片加载完成,自适应高度
|
||
*/
|
||
onBannerLoad(e) {
|
||
if (this.data.swiperHeight !== 400) return; // 只计算一次,避免多次抖动
|
||
const { width, height } = e.detail;
|
||
const sysInfo = wx.getSystemInfoSync();
|
||
// 减去左右padding (32rpx * 2)
|
||
const swiperWidth = sysInfo.windowWidth - (32 * 2 / 750 * sysInfo.windowWidth);
|
||
const ratio = width / height;
|
||
const swiperHeight = swiperWidth / ratio;
|
||
const swiperHeightRpx = swiperHeight * (750 / sysInfo.windowWidth);
|
||
|
||
this.setData({
|
||
swiperHeight: swiperHeightRpx
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 处理图片URL,如果是相对路径则拼接域名,并设置清晰度为85
|
||
*/
|
||
processImageUrl(url) {
|
||
if (!url) return ''
|
||
let fullUrl = url
|
||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||
const baseUrl = 'https://ai-c.maimanji.com'
|
||
fullUrl = baseUrl + (url.startsWith('/') ? '' : '/') + url
|
||
}
|
||
|
||
// 添加清晰度参数 q=85
|
||
if (fullUrl.includes('?')) {
|
||
if (!fullUrl.includes('q=')) {
|
||
fullUrl += '&q=85'
|
||
}
|
||
} else {
|
||
fullUrl += '?q=85'
|
||
}
|
||
return fullUrl
|
||
},
|
||
|
||
/**
|
||
* 加载合作商家列表
|
||
*/
|
||
async loadListData(reset = true) {
|
||
if (this.data.isLoading) return
|
||
if (!reset && !this.data.hasMore) return
|
||
|
||
this.setData({ isLoading: true })
|
||
const page = reset ? 1 : this.data.page + 1
|
||
|
||
try {
|
||
// 加载合作商家 (Merchants)
|
||
const res = await api.request('/service/providers', {
|
||
data: { page, limit: 20, type: 'merchant' }
|
||
})
|
||
|
||
let newData = []
|
||
let total = 0
|
||
|
||
if (res.success && res.data) {
|
||
newData = res.data.providers || []
|
||
total = res.data.total || 0
|
||
newData = newData.map(item => ({
|
||
...item,
|
||
id: item.id,
|
||
image: this.processImageUrl(item.avatar),
|
||
tags: item.skills || item.service_types || [],
|
||
desc: item.desc || item.introduction || '暂无简介',
|
||
rating: item.rating || item.avg_rating || '5.0'
|
||
}))
|
||
}
|
||
|
||
this.setData({
|
||
listData: reset ? newData : [...this.data.listData, ...newData],
|
||
page,
|
||
hasMore: (page * 20) < total,
|
||
isLoading: false
|
||
})
|
||
} catch (err) {
|
||
if (err.code === 404) {
|
||
console.warn('列表接口未部署 (404), 显示空列表')
|
||
} else {
|
||
console.error('加载列表数据失败', err)
|
||
}
|
||
this.setData({
|
||
listData: reset ? [] : this.data.listData,
|
||
isLoading: false,
|
||
hasMore: false
|
||
})
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 页面上拉触底事件的处理函数
|
||
*/
|
||
onReachBottom() {
|
||
this.loadListData(false)
|
||
},
|
||
|
||
onShow() {
|
||
wx.hideTabBar({ animation: false })
|
||
const app = getApp()
|
||
this.setData({
|
||
auditStatus: app.globalData.auditStatus
|
||
})
|
||
this.loadListData()
|
||
this.loadUnreadCount()
|
||
},
|
||
|
||
/**
|
||
* 加载服务页Banner
|
||
* 调用专用API,只返回在线的Banner,按排序顺序
|
||
*/
|
||
async loadBanners() {
|
||
try {
|
||
const res = await api.pageAssets.getServiceBanners()
|
||
|
||
if (res && res.success && res.data) {
|
||
// 提取URL数组(API已按排序返回,已过滤下线的)
|
||
const banners = res.data.map(item => this.processImageUrl(item.asset_url))
|
||
|
||
if (banners.length > 0) {
|
||
this.setData({ banners })
|
||
} else {
|
||
// 如果全部下线,使用默认配置
|
||
this.setDefaultBanners()
|
||
}
|
||
} else {
|
||
this.setDefaultBanners()
|
||
}
|
||
} catch (err) {
|
||
if (err.code !== 404) {
|
||
console.error('加载Banner失败:', err)
|
||
}
|
||
this.setDefaultBanners()
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 设置默认Banner(降级方案 - 使用CDN URL)
|
||
*/
|
||
setDefaultBanners() {
|
||
const cdnBase = 'https://ai-c.maimanji.com/images'
|
||
this.setData({
|
||
banners: [
|
||
`${cdnBase}/service-banner-1.png`,
|
||
`${cdnBase}/service-banner-2.png`,
|
||
`${cdnBase}/service-banner-3.png`,
|
||
`${cdnBase}/service-banner-4.png`,
|
||
`${cdnBase}/service-banner-5.png`,
|
||
`${cdnBase}/service-banner-6.png`
|
||
]
|
||
})
|
||
console.log('使用默认Banner配置')
|
||
},
|
||
|
||
/**
|
||
* 加载未读消息数
|
||
*/
|
||
loadUnreadCount() {
|
||
if (!api.chat || typeof api.chat.getConversations !== 'function') return
|
||
|
||
api.chat.getConversations().then(res => {
|
||
if (res && res.success && res.data) {
|
||
let count = 0
|
||
res.data.forEach(item => {
|
||
count += (item.unread_count || 0)
|
||
})
|
||
this.setData({ totalUnread: count })
|
||
}
|
||
}).catch(err => {
|
||
// 静默处理未读数获取失败
|
||
if (err.code !== 404) {
|
||
console.warn('获取未读数静默失败:', err)
|
||
}
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 点击服务类型
|
||
*/
|
||
onServiceType(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
|
||
if (id === 'points') {
|
||
// 礼品商城 - 跳转到兑换商城
|
||
wx.navigateTo({ url: '/pages/gift-shop/gift-shop' })
|
||
} else if (id === 'merchants') {
|
||
// 合作商家 - 刷新列表
|
||
this.loadListData()
|
||
} else if (id === 'eldercare') {
|
||
// 智慧康养 - 跳转到详情页
|
||
wx.navigateTo({ url: '/pages/eldercare/eldercare' })
|
||
} else if (id === 'custom') {
|
||
// 定制服务 - 跳转到详情页
|
||
wx.navigateTo({ url: '/pages/custom/custom' })
|
||
} else if (id === 'academy') {
|
||
// 心伴学堂 - 跳转到列表页
|
||
wx.navigateTo({ url: '/pages/academy/list/list' })
|
||
} else if (id === 'brand') {
|
||
// 关于品牌 - 跳转到品牌详情页
|
||
wx.navigateTo({ url: '/pages/brand/brand' })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 点击列表项 - 跳转商家详情
|
||
*/
|
||
onItemTap(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
wx.navigateTo({
|
||
url: `/pages/service-provider-detail/service-provider-detail?id=${id}`
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 切换Tab
|
||
*/
|
||
switchTab(e) {
|
||
const path = e.currentTarget.dataset.path
|
||
if (path) {
|
||
const app = getApp()
|
||
|
||
// 消息页面需要登录
|
||
if (path === '/pages/chat/chat') {
|
||
if (!app.globalData.isLoggedIn) {
|
||
wx.navigateTo({
|
||
url: '/pages/login/login?redirect=' + encodeURIComponent(path)
|
||
})
|
||
return
|
||
}
|
||
}
|
||
wx.switchTab({ url: path })
|
||
}
|
||
}
|
||
})
|