440 lines
12 KiB
Vue
440 lines
12 KiB
Vue
<template>
|
||
<view>
|
||
<view class="page" v-if="store">
|
||
<!-- xuchao: 顶部导航(返回+页面名称) -->
|
||
<view class="nav-bar">
|
||
<view class="nav-back" @click="goBack">
|
||
<u-icon name="arrow-left" color="#1a1818" size="40"></u-icon>
|
||
</view>
|
||
<text class="nav-title">{{ store.name }}</text>
|
||
</view>
|
||
<!-- 门店信息卡片(信息+地址合并容器) -->
|
||
<view class="store-card">
|
||
<view class="store-main">
|
||
<image class="store-img" :src="store.image" mode="aspectFill" />
|
||
<view class="store-info">
|
||
<text class="store-name">{{ store.name }}</text>
|
||
<text class="store-category">{{ store.category }}</text>
|
||
<text class="store-hours" v-if="store.businessTime">营业时间:{{ store.businessTime }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="divider"></view>
|
||
<view class="address-row">
|
||
<text class="address-text">{{ store.address }}</text>
|
||
<view class="distance-row" v-if="store.distance !== null">
|
||
<u-icon name="map" color="#999999" size="24"></u-icon>
|
||
<text class="distance-text">{{ store.distance < 1 ? Math.round(store.distance * 1000) + 'm' : Math.round(store.distance) + 'km' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商户电话(取商铺客服电话字段,多个用,分隔,点击拨号) -->
|
||
<view class="discount-section" v-if="servicePhoneList.length">
|
||
<view class="section-title">
|
||
<u-icon name="phone-fill" color="#1296DB" size="34"></u-icon>
|
||
<text class="discount-title">商户电话</text>
|
||
</view>
|
||
<view class="discount-list">
|
||
<text class="discount-item">
|
||
<text v-for="(p, i) in servicePhoneList" :key="i" class="phone-link"
|
||
@click="callPhone(p)">{{ i > 0 ? ',' : '' }}{{ p }}</text>
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商品信息(仅商户折扣板块展示,内容取商铺门票信息字段) -->
|
||
<view class="discount-section" v-if="!isVenue && ticketInfoList.length">
|
||
<view class="section-title">
|
||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_qysm.png" style="width: 30rpx;height: 30rpx;"></image>
|
||
<text class="discount-title">商品信息</text>
|
||
</view>
|
||
<view class="discount-list">
|
||
<text class="discount-item" v-for="(item, index) in ticketInfoList" :key="index">{{ item }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 文旅场馆显示「使用说明」(1001板块备注),商户折扣显示「商户优惠」(1002板块备注) -->
|
||
<view class="discount-section" v-if="remarkList.length">
|
||
<view class="section-title">
|
||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_qysm.png" style="width: 30rpx;height: 30rpx;"></image>
|
||
<text class="discount-title">{{ isVenue ? '使用说明' : '商户优惠' }}</text>
|
||
</view>
|
||
<view class="discount-list">
|
||
<text class="discount-item" v-for="(item, index) in remarkList" :key="index">{{ item }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- xuchao: 怀化石油汽油券购买模块(shopId 写死特判,只服务该门店,决策 1/10/15) -->
|
||
<view class="voucher-card" v-if="isPetrol">
|
||
<view class="section-title">
|
||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_qysm.png" style="width: 30rpx;height: 30rpx;"></image>
|
||
<text class="discount-title">汽油电子券</text>
|
||
</view>
|
||
<view class="voucher-ticket">
|
||
<view class="voucher-amt">满200减8 <text class="voucher-amt-sub">汽油电子券</text></view>
|
||
<view class="voucher-rule">无门槛 | 90 天有效 | 单日限用 1 张 | 可叠加</view>
|
||
<text class="voucher-wm">90天</text>
|
||
</view>
|
||
<view class="voucher-tip">支付成功后券码即时展示;到店出示二维码,收银员以“中石油汽油券”通道扫码核销。券一经售出不支持退换。</view>
|
||
<view class="voucher-btn" @click="onVoucherClick">{{ voucherBtnText }}</view>
|
||
</view>
|
||
</view>
|
||
<!-- xuchao: 门店不存在或加载失败时的提示态,避免纯空白 -->
|
||
<view class="page" v-else-if="loaded">
|
||
<view class="nav-bar">
|
||
<view class="nav-back" @click="goBack">
|
||
<u-icon name="arrow-left" color="#1a1818" size="40"></u-icon>
|
||
</view>
|
||
<text class="nav-title">详情</text>
|
||
</view>
|
||
<view class="load-failed">
|
||
<text class="load-failed-text">门店信息加载失败,该门店可能不存在或已下架</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { PETROL_SHOP_ID, bizOk, bizData } from '@/common/petrolVoucher.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
store: null,
|
||
loaded: false,
|
||
detailType: '1',
|
||
shopId: '',
|
||
voucher: null // xuchao: 石油券最新订单状态(statusCode 语义见 common/petrolVoucher.js)
|
||
}
|
||
},
|
||
computed: {
|
||
// xuchao: 入口板块:type=2 商户折扣,其余(含缺省)按文旅场馆渲染
|
||
isVenue() {
|
||
return this.detailType !== '2'
|
||
},
|
||
isPetrol() {
|
||
return this.loaded && String(this.shopId) === PETROL_SHOP_ID && !this.isVenue
|
||
},
|
||
voucherBtnText() {
|
||
const s = this.voucher ? this.voucher.statusCode : -1
|
||
if (s === 0) return '继续支付'
|
||
if (s === 1) return '查看我的券'
|
||
if (s === 2) return '查看我的券'
|
||
if (s === 3 || s === 4) return '重新购买'
|
||
return '¥200 购买'
|
||
},
|
||
ticketInfoList() {
|
||
if (!this.store || !this.store.ticketInfo) return []
|
||
return this.store.ticketInfo.split('\n')
|
||
},
|
||
remarkList() {
|
||
if (!this.store) return []
|
||
const text = this.isVenue ? this.store.usageNote : this.store.merchantDiscount
|
||
if (!text) return []
|
||
return text.split('\n')
|
||
},
|
||
// xuchao: 客服电话列表:按常见分隔符切分;无分隔符连写的多个11位手机号也自动拆开
|
||
servicePhoneList() {
|
||
if (!this.store || !this.store.servicePhone) return []
|
||
const parts = String(this.store.servicePhone).split(/[,,;;、\s\n]+/).filter(Boolean)
|
||
const out = []
|
||
parts.forEach(p => {
|
||
if (p.length > 11 && /^1[3-9]\d{9}$/.test(p.slice(0, 11))) {
|
||
let rest = p
|
||
const segs = []
|
||
while (rest.length >= 11 && /^1[3-9]\d{9}$/.test(rest.slice(0, 11))) {
|
||
segs.push(rest.slice(0, 11))
|
||
rest = rest.slice(11)
|
||
}
|
||
if (rest) segs[segs.length - 1] += rest
|
||
if (segs.length > 1) {
|
||
out.push(...segs)
|
||
return
|
||
}
|
||
}
|
||
out.push(p)
|
||
})
|
||
return out
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
if (options.type) this.detailType = String(options.type)
|
||
if (options.id) {
|
||
this.shopId = String(options.id)
|
||
this.loadDetail(options.id)
|
||
}
|
||
},
|
||
onShow() {
|
||
// xuchao: 支付/购券流程返回时刷新券按钮状态
|
||
if (String(this.shopId) === PETROL_SHOP_ID) this.loadVoucher()
|
||
},
|
||
methods: {
|
||
// xuchao: 拉取石油券最新订单状态(未登录不查,按钮保持“¥200 购买”,点击时再引导登录)
|
||
loadVoucher() {
|
||
const phone = uni.getStorageSync('phone')
|
||
if (!phone) { this.voucher = null; return }
|
||
this.$u.api.voucherLatest({ phone }).then(res => {
|
||
this.voucher = bizOk(res) ? bizData(res) : null
|
||
}).catch(() => { this.voucher = null })
|
||
},
|
||
onVoucherClick() {
|
||
const phone = uni.getStorageSync('phone')
|
||
if (!phone) {
|
||
uni.navigateTo({ url: '/pages/index/login?redirect=' + encodeURIComponent('/pages/venue/detail?id=' + this.shopId + '&type=' + this.detailType) })
|
||
return
|
||
}
|
||
const s = this.voucher ? this.voucher.statusCode : -1
|
||
if (s === 2 || s === 1) {
|
||
uni.navigateTo({ url: '/pages/petrol/voucherDetail' })
|
||
} else if (s === 0) {
|
||
uni.navigateTo({ url: '/pages/petrol/orderConfirm?orderNo=' + this.voucher.orderNo })
|
||
} else {
|
||
uni.navigateTo({ url: '/pages/petrol/orderConfirm' })
|
||
}
|
||
},
|
||
// xuchao: 点击某个商户电话唤起拨号(多个号码时逐个可点)
|
||
callPhone(phone) {
|
||
if (!phone) return
|
||
uni.makePhoneCall({ phoneNumber: String(phone) })
|
||
},
|
||
loadDetail(shopId) {
|
||
const loc = uni.getStorageSync('lng') && uni.getStorageSync('lat')
|
||
? { lng: uni.getStorageSync('lng'), lat: uni.getStorageSync('lat') }
|
||
: null
|
||
const params = { shopId: shopId }
|
||
if (loc) {
|
||
params.lng = loc.lng
|
||
params.lat = loc.lat
|
||
}
|
||
this.$u.api.getStoreDetail(params).then(res => {
|
||
if (res.errcode === 0 && res.data) {
|
||
this.store = res.data
|
||
}
|
||
this.loaded = true
|
||
}).catch(() => {
|
||
this.loaded = true
|
||
})
|
||
},
|
||
goBack() {
|
||
// xuchao: 直接通过链接进入(无历史栈)时回到首页,避免返回无响应
|
||
const pages = getCurrentPages()
|
||
if (pages.length > 1) {
|
||
uni.navigateBack()
|
||
} else {
|
||
uni.reLaunch({ url: '/pages/index/index' })
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.page {
|
||
/* xuchao: 顶部导航条占用 56px,改为 min-height 让长内容正常滚动,避免底部被裁切 */
|
||
min-height: 100vh;
|
||
background-color: #f2f2f7;
|
||
}
|
||
|
||
/* 门店卡片(信息+地址合并容器) */
|
||
.store-card {
|
||
background-color: #ffffff;
|
||
margin: 12px;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.store-main {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
padding: 12px;
|
||
gap: 12px;
|
||
}
|
||
|
||
.store-img {
|
||
width: 100px;
|
||
height: 100px;
|
||
border-radius: 6px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.store-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: flex-start;
|
||
gap: 8px;
|
||
}
|
||
|
||
.store-name {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #1a1818;
|
||
}
|
||
|
||
.store-category {
|
||
font-size: 13px;
|
||
color: #999999;
|
||
}
|
||
|
||
.store-hours {
|
||
font-size: 13px;
|
||
color: #666666;
|
||
}
|
||
|
||
.divider {
|
||
height: 1px;
|
||
background-color: #f2f2f7;
|
||
margin: 0 12px;
|
||
}
|
||
|
||
/* 地址行 */
|
||
.address-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 12px;
|
||
}
|
||
|
||
.address-text {
|
||
font-size: 13px;
|
||
color: #999999;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.distance-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 2px;
|
||
flex-shrink: 0;
|
||
margin-left: 8px;
|
||
}
|
||
|
||
.distance-text {
|
||
font-size: 12px;
|
||
color: #999999;
|
||
}
|
||
|
||
/* 使用说明 */
|
||
.discount-section {
|
||
background-color: #ffffff;
|
||
margin: 12px;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
}
|
||
|
||
.section-title {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.discount-tag-icon {
|
||
font-size: 16px;
|
||
color: #0088ff;
|
||
}
|
||
|
||
.discount-title {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: #1a1818;
|
||
}
|
||
|
||
.discount-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.discount-item {
|
||
font-size: 13px;
|
||
color: #666666;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
/* xuchao: 可点击拨号的电话样式 */
|
||
.phone-link {
|
||
color: #0088ff;
|
||
}
|
||
|
||
/* xuchao: 石油汽油券购买模块 */
|
||
.voucher-card {
|
||
background-color: #ffffff;
|
||
margin: 12px;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
}
|
||
|
||
.voucher-ticket {
|
||
position: relative;
|
||
overflow: hidden;
|
||
background: linear-gradient(135deg, #0d6fe0, #2f9bff);
|
||
border-radius: 8px;
|
||
padding: 14px;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.voucher-amt { font-size: 22px; font-weight: 700; }
|
||
.voucher-amt-sub { font-size: 12px; font-weight: 400; opacity: 0.9; margin-left: 4px; }
|
||
.voucher-rule { font-size: 12px; opacity: 0.9; margin-top: 6px; }
|
||
.voucher-wm { position: absolute; right: 4px; bottom: -12px; font-size: 52px; font-weight: 800; opacity: 0.1; }
|
||
.voucher-tip { font-size: 12px; color: #666666; line-height: 1.7; margin-top: 12px; }
|
||
.voucher-btn {
|
||
height: 42px;
|
||
margin-top: 12px;
|
||
border-radius: 8px;
|
||
background-color: #0088ff;
|
||
color: #ffffff;
|
||
font-size: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* xuchao: 加载失败提示态 */
|
||
.load-failed {
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 80px 24px;
|
||
}
|
||
|
||
.load-failed-text {
|
||
font-size: 14px;
|
||
color: #999999;
|
||
}
|
||
|
||
/* xuchao: 顶部返回导航条 */
|
||
.nav-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 56px;
|
||
background-color: #ffffff;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
position: relative;
|
||
}
|
||
|
||
.nav-back {
|
||
position: absolute;
|
||
left: 12px;
|
||
top: 0;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.nav-title {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: #1a1818;
|
||
padding: 0 56px;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
</style>
|