2026-07-08 16:17:50 +08:00

159 lines
7.2 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.

<template>
<view class="hsd-page">
<swiper class="hsd-swiper" autoplay circular v-if="carousel.length">
<swiper-item v-for="(p, i) in carousel" :key="i">
<image :src="p" mode="aspectFit" class="hsd-swiper-img" />
</swiper-item>
</swiper>
<image v-else :src="picUrl + (info.cover_pic || '')" class="hsd-swiper-img" mode="aspectFit" />
<view class="hsd-main">
<view class="hsd-name">{{ info.service_name }}</view>
<view class="hsd-pricedesc">{{ info.price_desc }}</view>
</view>
<!-- SKU 选择 -->
<view class="hsd-block" v-if="skuList.length">
<view class="hsd-block-tit">选择规格</view>
<view class="hsd-sku-list">
<view class="hsd-sku" :class="{ active: currentSku && currentSku.id === sku.id }"
v-for="sku in skuList" :key="sku.id" @tap="selectSku(sku)">
<view class="hsd-sku-name">{{ sku.sku_name }}</view>
<view class="hsd-sku-price" v-if="isHousekeeping">月薪 ¥{{ sku.month_salary }}</view>
<view class="hsd-sku-price" v-else>定金 ¥{{ sku.deposit }}</view>
</view>
</view>
</view>
<!-- 师傅选择 -->
<view class="hsd-block" v-if="workerList.length">
<view class="hsd-block-tit">选择师傅</view>
<view class="hsd-worker-list">
<view class="hsd-worker" :class="{ active: currentWorker && currentWorker.employee_id === w.employee_id }"
v-for="w in workerList" :key="w.employee_id" @tap="selectWorker(w)">
<image class="hsd-worker-img" :src="w.employee_image || defaultAvatar" mode="aspectFill" />
<view class="hsd-worker-name">{{ w.employee_name }}</view>
<view class="hsd-worker-exp">{{ w.expertise }}</view>
</view>
</view>
</view>
<!-- 服务流程图可多张按序展示 -->
<view class="hsd-block" v-if="flowChartList.length">
<view class="hsd-block-tit">服务流程</view>
<image v-for="(p, i) in flowChartList" :key="i" :src="p" mode="widthFix" class="hsd-detail-img" />
</view>
<view class="hsd-bottom">
<template v-if="isHousekeeping">
<view class="hsd-bottom-price">月薪 <text>¥{{ currentSku ? currentSku.month_salary : '--' }}</text></view>
<view class="hsd-bottom-btn" @tap="goConsult">咨询预约</view>
</template>
<template v-else>
<view class="hsd-bottom-price">定金 <text>¥{{ currentSku ? currentSku.deposit : '--' }}</text></view>
<view class="hsd-bottom-btn" @tap="goOrder">立即预约</view>
</template>
</view>
</view>
</template>
<script>
import { request, picUrl, NavgateTo } from '@/utils'
import { apiArr } from '@/api/homeService'
export default {
data() {
return {
picUrl,
defaultAvatar: 'https://static.hshuishang.com/defaultTx.png',
id: 0,
info: {},
carousel: [],
detailPics: [],
flowChartList: [],
skuList: [],
workerList: [],
currentSku: null,
currentWorker: null
}
},
onLoad(options) {
this.id = Number(options.id)
this.loadInfo()
},
computed: {
// 家政服务(原长期服务 service_type=2):走咨询签约,不付定金
isHousekeeping() {
return Number(this.info.service_type) === 2
}
},
methods: {
loadInfo() {
request(apiArr.serviceInfo, 'POST', { id: this.id }, {}, false).then(res => {
this.info = res || {}
const toUrls = (str) => (str ? String(str).split(',') : []).filter(Boolean).map(p => p.startsWith('http') ? p : this.picUrl + p)
// 轮播优先用封面图(后台维护的多图);无则兜底用历史 carousel 字段
const coverArr = toUrls(res.cover_pic)
this.carousel = coverArr.length ? coverArr : toUrls(res.carousel)
this.detailPics = toUrls(res.detail_pic)
this.flowChartList = toUrls(res.flow_chart) // 服务流程图,可多张
this.skuList = res.sku_list || []
this.workerList = res.worker_list || []
if (this.skuList.length) this.currentSku = this.skuList[0]
if (this.workerList.length) this.currentWorker = this.workerList[0]
})
},
selectSku(sku) { this.currentSku = sku },
selectWorker(w) { this.currentWorker = w },
goOrder() {
if (!this.currentSku) { uni.showToast({ title: '请选择规格', icon: 'none' }); return }
if (!this.currentWorker) { uni.showToast({ title: '请选择师傅', icon: 'none' }); return }
const params = {
service_info_id: this.id,
sku_id: this.currentSku.id,
employee_id: this.currentWorker.employee_id,
service_name: this.info.service_name,
deposit: this.currentSku.deposit
}
NavgateTo('/packages/homeService/order/index?params=' + encodeURIComponent(JSON.stringify(params)))
},
// 家政服务:先与商家客服沟通签约,不走定金下单
goConsult() {
const supplierId = this.info.supplier_id
if (!supplierId) { uni.showToast({ title: '商家信息缺失', icon: 'none' }); return }
// 客服列表依赖 merchantInfo.id写入当前服务所属商家
const mi = uni.getStorageSync('merchantInfo') || {}
mi.id = supplierId
uni.setStorageSync('merchantInfo', mi)
NavgateTo('/packages/customerService/changeService/index')
}
}
}
</script>
<style scoped>
.hsd-page { background: #f5f5f5; min-height: 100vh; padding-bottom: 130rpx; }
/* 轮播按正方形完整显示封面(1:1)aspectFit 不裁剪;非方图留白居中 */
.hsd-swiper, .hsd-swiper-img { width: 100%; height: 750rpx; background: #f2f2f2; }
.hsd-main { background: #fff; padding: 24rpx; }
.hsd-name { font-size: 36rpx; font-weight: 600; color: #222; }
.hsd-pricedesc { font-size: 26rpx; color: #FF370B; margin-top: 14rpx; }
.hsd-block { background: #fff; margin-top: 16rpx; padding: 24rpx; }
.hsd-block-tit { font-size: 30rpx; font-weight: 600; color: #222; margin-bottom: 18rpx; }
.hsd-sku-list, .hsd-worker-list { display: flex; flex-wrap: wrap; gap: 18rpx; }
.hsd-sku { border: 1rpx solid #eee; border-radius: 10rpx; padding: 16rpx 24rpx; }
.hsd-sku.active { border-color: #FF370B; background: #FFF1ED; }
.hsd-sku-name { font-size: 28rpx; color: #222; }
.hsd-sku-price { font-size: 24rpx; color: #FF370B; margin-top: 8rpx; }
.hsd-worker { width: 160rpx; display: flex; flex-direction: column; align-items: center; border: 1rpx solid #eee; border-radius: 10rpx; padding: 16rpx 8rpx; }
.hsd-worker.active { border-color: #FF370B; background: #FFF1ED; }
.hsd-worker-img { width: 100rpx; height: 100rpx; border-radius: 50%; background: #f0f0f0; }
.hsd-worker-name { font-size: 26rpx; color: #222; margin-top: 10rpx; }
.hsd-worker-exp { font-size: 20rpx; color: #999; margin-top: 4rpx; }
.hsd-detail-img { width: 100%; display: block; }
.hsd-bottom { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; align-items: center; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.04); }
.hsd-bottom-price { flex: 1; font-size: 26rpx; color: #333; }
.hsd-bottom-price text { color: #FF370B; font-size: 36rpx; font-weight: 600; }
.hsd-bottom-btn { background: linear-gradient(91deg, #FF7658, #FF370B); color: #fff; font-size: 30rpx; padding: 20rpx 60rpx; border-radius: 44rpx; }
</style>