<template>
|
<view class="page">
|
<view class="custom-nav" :class="(isSolidNav ? 'is-solid ' : '') + (isHotelMerchant ? 'is-hotel' : '')">
|
<view class="custom-nav-bg"></view>
|
<view class="safe-space" :style="'height:' + navTop + 'px'"></view>
|
<view class="nav-row" :style="'height:' + navHeight + 'px;padding-right:' + navRight + 'px'">
|
<view class="back-button" @tap="goBack"><image src="/static/food-assets/arrow-left-white.svg"></image></view>
|
<text class="nav-title">{{merchantName}}</text>
|
<view class="capsule-space" :style="'width:' + navWidth + 'px'"></view>
|
</view>
|
</view>
|
|
<scroll-view :class="'content' + (isMedicalMerchant ? ' content-full' : '')" scroll-y @scroll="handleScroll">
|
<view class="hero">
|
<image class="hero-image" :src="merchantHero" mode="aspectFill" @error="replaceHeroImage"></image>
|
<view class="hero-shade"></view>
|
</view>
|
|
<view class="merchant-panel">
|
<view v-if="merchantLoading" class="merchant-detail-state"><view class="loading-spinner"></view><text>正在加载商户详情</text></view>
|
<view v-else-if="merchantError" class="merchant-detail-state error-state"><text>商户详情加载失败</text><text class="retry-text" @tap="retryMerchantDetail">重新加载</text></view>
|
<view v-else class="merchant-info-card">
|
<view v-if="!merchantAvailable" class="merchant-unavailable"><text>{{merchantUnavailableReason}}</text></view>
|
<view v-if="isParkingMerchant" class="parking-title-block">
|
<view class="parking-title-row"><text class="merchant-title">{{merchantName}}</text><view class="round-action" @tap="callMerchant"><image src="/static/merchant-assets/phone.svg"></image></view></view>
|
<text class="parking-free">{{parkingBenefitText}}</text>
|
</view>
|
<view v-else-if="isMedicalMerchant" class="merchant-title-row">
|
<text class="merchant-title">{{merchantName}}</text>
|
<text class="medical-free-tag">免费</text>
|
</view>
|
<view v-else class="merchant-title-row">
|
<text class="merchant-title">{{merchantName}}</text>
|
<view class="merchant-tags"><text class="coupon-tag">{{merchantPrimaryTag}}</text><text v-if="merchantDiscount != ''" class="discount-tag">{{merchantDiscount}}</text></view>
|
</view>
|
<view class="service-tags"><text v-if="!isParkingMerchant && !isMedicalMerchant">{{merchantServiceLabel}}</text><text>{{applicableCards}}</text></view>
|
<view v-if="!isParkingMerchant" class="merchant-address-row">
|
<image class="address-icon" src="/static/benefits-assets/map-pin.svg"></image>
|
<text>{{merchantAddress}}</text>
|
<view class="merchant-actions"><view :class="merchantLocation.latitude > 0 && merchantLocation.longitude > 0 ? 'round-action' : 'round-action is-disabled'" @tap="openMap"><image src="/static/merchant-assets/navigation.svg"></image></view><view :class="merchantPhone != '' ? 'round-action' : 'round-action is-disabled'" @tap="callMerchant"><image src="/static/merchant-assets/phone.svg"></image></view></view>
|
</view>
|
</view>
|
|
<view v-if="!merchantError" class="tabs">
|
<view class="tab-item" :class="currentTab == 'primary' ? 'active' : ''" @tap="changeTab('primary')"><text>{{isMedicalMerchant ? '预约' : (groupBuyingEnabled ? '消费购买' : '使用说明')}}</text><view class="tab-line"></view></view>
|
<view class="tab-item" :class="currentTab == 'rights' ? 'active' : ''" @tap="changeTab('rights')"><text>{{isParkingMerchant ? '停车场地址' : (isTransportMerchant ? '适用门店' : '权益详情')}}</text><view class="tab-line"></view></view>
|
</view>
|
|
<view v-if="!merchantError && currentTab == 'primary'">
|
<view v-if="isMedicalMerchant" class="medical-package-list">
|
<view v-if="listLoading" class="list-state"><view class="loading-spinner"></view><text>正在加载体检套餐</text></view>
|
<view v-else-if="listError" class="list-state error-state"><text>体检套餐加载失败</text><text class="retry-text" @tap="loadMerchantLists">重新加载</text></view>
|
<view v-else-if="listLoaded && visibleMedicalPackages.length == 0" class="list-state"><text>暂无可预约体检套餐</text></view>
|
<view class="medical-package-item" v-for="item in visibleMedicalPackages" :key="item.id" hover-class="package-item-active" @tap="openMedicalPackage(item)">
|
<image class="medical-package-image" :src="item.image" mode="aspectFill" @error="replaceImage(item)"></image>
|
<view class="medical-package-info">
|
<text class="medical-package-name">{{item.name}}</text>
|
<view class="medical-package-bottom">
|
<view class="medical-open-row"><text class="medical-open-label">开放时间</text><text class="medical-open-value">{{item.openTime}}</text></view>
|
<view class="medical-view-button"><text>查看</text></view>
|
</view>
|
</view>
|
</view>
|
</view>
|
<view v-else-if="groupBuyingEnabled" class="package-list">
|
<view v-if="listLoading" class="list-state"><view class="loading-spinner"></view><text>正在加载可用套餐</text></view>
|
<view v-else-if="listError" class="list-state error-state"><text>套餐列表加载失败</text><text class="retry-text" @tap="loadMerchantLists">重新加载</text></view>
|
<view v-else-if="listLoaded && visiblePackages.length == 0" class="list-state"><text>{{isHotelMerchant ? '暂无可预约房型' : '暂无可购买套餐'}}</text></view>
|
<view class="package-item" :class="item.available === false ? 'is-sold-out' : ''" v-for="item in visiblePackages" :key="item.id" hover-class="package-item-active" @tap="handlePackage(item)">
|
<image class="package-image" :src="item.image" mode="aspectFill" @error="replaceImage(item)"></image>
|
<view class="package-info">
|
<text class="package-name">{{item.name}}</text>
|
<view class="package-tags"><text class="coupon-tag">券</text><text class="discount-tag">{{item.discount}}</text></view>
|
<view class="package-bottom"><view class="price-row"><text class="price-symbol">¥</text><text class="price">{{item.price}}</text><text v-if="!isHotelMerchant" class="old-price">¥{{item.originalPrice}}</text></view><view class="buy-button"><text>{{item.available === false ? '已售罄' : (isHotelMerchant ? '预约' : '购买')}}</text></view></view>
|
</view>
|
</view>
|
</view>
|
<view v-else class="usage-panel"><text>{{usageInstructions}}</text></view>
|
</view>
|
<view v-else-if="!merchantError && isTransportMerchant" class="store-panel">
|
<view v-if="listLoading" class="list-state"><view class="loading-spinner"></view><text>正在加载适用门店</text></view>
|
<view v-else-if="listError" class="list-state error-state"><text>适用门店加载失败</text><text class="retry-text" @tap="loadMerchantLists">重新加载</text></view>
|
<view v-else-if="listLoaded && applicableStores.length == 0" class="list-state"><text>暂无适用门店</text></view>
|
<view v-if="listLoaded && applicableStores.length > 0" class="store-table-header"><view class="store-head-name"><text>适用门店名称</text></view><view class="store-head-address"><text>详细地址</text></view><view class="store-head-action"></view></view>
|
<view class="store-row" v-for="item in applicableStores" :key="item.id">
|
<view class="store-name-cell"><text>{{item.name}}</text></view>
|
<view class="store-address-cell"><text>{{item.address}}</text></view>
|
<view :class="item.canNavigate === false ? 'store-location is-disabled' : 'store-location'" @tap="openStoreLocation(item)"><image src="/static/merchant-assets/store-pin-blue.svg" mode="aspectFit"></image></view>
|
</view>
|
</view>
|
<view v-else-if="!merchantError && isMedicalMerchant" class="medical-usage-panel"><text>{{usageInstructions}}</text></view>
|
<view v-else-if="!merchantError" class="rights-panel">
|
<text class="rights-title">人才卡专属权益</text>
|
<text class="rights-text">{{merchantRightsText}}</text>
|
<view class="rule-row"><text>适用卡种</text><text>{{applicableCards}}</text></view>
|
<view class="rule-row"><text>使用方式</text><text>到店出示人才码</text></view>
|
</view>
|
</view>
|
<view class="content-bottom"></view>
|
</scroll-view>
|
|
<view v-if="!isMedicalMerchant && merchantAvailable" class="action-bar">
|
<view v-if="isParkingMerchant && parkingActionMode == 'talentCode'" class="talent-code-button" @tap="showBottomVoucher"><image src="/static/merchant-assets/qr-code.svg"></image><text>出示人才码</text></view>
|
<view v-else-if="isParkingMerchant" class="talent-code-button" @tap="openPlatePage"><text>填写车牌</text></view>
|
<view v-else-if="isTransportMerchant" class="talent-code-button" @tap="openMobileDialog"><text>填写手机号</text></view>
|
<view v-else class="talent-code-button" @tap="showBottomVoucher"><image :src="hasFreeVoucher ? '/static/merchant-assets/coupon.svg' : '/static/merchant-assets/qr-code.svg'"></image><text>{{hasFreeVoucher ? '出示免费券' : '出示人才码'}}</text></view>
|
</view>
|
|
<view v-if="showMobileDialog" class="mobile-dialog-mask" @tap="closeMobileDialog">
|
<view class="mobile-dialog" @tap.stop>
|
<view class="mobile-dialog-close" @tap="closeMobileDialog"><text>×</text></view>
|
<text class="mobile-dialog-title">填写手机号</text>
|
<text class="mobile-dialog-desc">提交后工作人员将根据加油权益与您联系</text>
|
<view class="mobile-input-box"><input v-model="mobile" type="number" maxlength="11" placeholder="请输入手机号" placeholder-class="mobile-placeholder" /></view>
|
<text v-if="mobileError != ''" class="mobile-error">{{mobileError}}</text>
|
<view class="mobile-submit" @tap="submitMobile"><text>提交</text></view>
|
</view>
|
</view>
|
|
</view>
|
</template>
|
|
<script setup lang="uts">
|
import { apiEnvironment, isApiConfigured } from '../../config/api.uts'
|
import { getFuelMerchantDetail, getMedicalPackages, getMerchantDetail, getParkingMerchantDetail, getProducts, submitFuelMobileRegistration } from '../../services/portal.uts'
|
import { resolveApiUrl } from '../../services/http.uts'
|
import { getSession } from '../../services/session.uts'
|
import { safeBack } from '../../utils/navigation.uts'
|
import { submitBusiness } from '../../services/business.uts'
|
|
const navTop = ref(28)
|
const navHeight = ref(32)
|
const navWidth = ref(88)
|
const navRight = ref(10)
|
const isSolidNav = ref(false)
|
const currentTab = ref('primary')
|
const isHotelMerchant = ref(false)
|
const isTransportMerchant = ref(false)
|
const isFuelMerchant = ref(false)
|
const isParkingMerchant = ref(false)
|
const isMedicalMerchant = ref(false)
|
// 后台停车权益配置:plate=填写车牌,talentCode=出示人才码。
|
const parkingActionMode = ref('plate')
|
// 后台车牌表单配置:withParking=需搜索停车场,simple=仅填写车牌。
|
const parkingPlateMode = ref('simple')
|
const showMobileDialog = ref(false)
|
const mobile = ref('')
|
const mobileError = ref('')
|
const isSubmittingMobile = ref(false)
|
const hasFreeVoucher = ref(false)
|
const merchantLoading = ref(false)
|
const merchantError = ref(false)
|
const merchantAvailable = ref(true)
|
const merchantUnavailableReason = ref('该商户已停业或下架,暂不可购买和核销')
|
const merchantPhone = ref('08123335555')
|
const merchantId = ref('merchant-food-default')
|
const merchantType = ref('food')
|
const merchantName = ref('百杏厨房(中环天地店)')
|
const merchantHero = ref('')
|
const fallbackImage = ''
|
const replaceHeroImage = () => { merchantHero.value = '' }
|
const replaceImage = (item: any) => { if (item.image != '') item.image = '' }
|
const merchantPrimaryTag = ref('券')
|
const merchantDiscount = ref('8.8折')
|
const merchantAddress = ref('四川省攀枝花市东区炳三区新福路20号中环天地负一层')
|
const merchantServiceLabel = ref('到店消费')
|
const applicableCards = ref('卓越卡可用')
|
const fuelBenefitId = ref('')
|
const parkingBenefitId = ref('')
|
const parkingBenefitText = ref('免费')
|
const talentId = ref('')
|
const fuelRegistrationKey = ref('')
|
const merchantRightsText = ref('持卓越人才卡到店消费可享指定菜品及套餐 8.8 折优惠,具体可用时段、适用门店和使用规则以商户现场说明为准。')
|
// 后台商户配置:false 时不展示套餐团购,主标签切换为“使用说明”。
|
const groupBuyingEnabled = ref(true)
|
const usageInstructions = ref('所有菜品8.8折优惠;就餐后亮码,商家扫码确认订单后在本小程序中完成支付。')
|
const merchantLocation = ref({
|
latitude: 26.5856,
|
longitude: 101.7184,
|
name: '百杏厨房(中环天地店)',
|
address: '四川省攀枝花市东区炳三区新福路20号中环天地负一层'
|
})
|
const allApplicableStores = [
|
{ id: 1, name: '盐源居小区停车场', address: '盐华路38号2栋', latitude: 26.5856, longitude: 101.7184 },
|
{ id: 2, name: '东林巷停车场', address: '东林巷29号1栋、2栋、3栋、东林巷31号1栋、2栋', latitude: 26.5862, longitude: 101.7191 },
|
{ id: 3, name: '东区政府第2号停车场', address: '东阳巷19号', latitude: 26.5849, longitude: 101.7177 },
|
{ id: 4, name: '东区政府第3号停车场', address: '原环保局办公楼', latitude: 26.5844, longitude: 101.7169 },
|
{ id: 5, name: '东区政府第4号停车场', address: '东阳巷8号', latitude: 26.5838, longitude: 101.7180 },
|
{ id: 6, name: '东区机关食堂外停车场', address: '东阳巷23号旁红砖房', latitude: 26.5832, longitude: 101.7190 },
|
{ id: 7, name: '攀枝花大道558号停车场', address: '攀枝花大道中段558号6栋', latitude: 26.5827, longitude: 101.7201 },
|
{ id: 8, name: '五十四交通银行旁停车场', address: '供销社背后金星巷3号', latitude: 26.5819, longitude: 101.7210 },
|
{ id: 9, name: '五十四供销社幼儿园停车场', address: '供销社背后金星巷3号', latitude: 26.5812, longitude: 101.7218 }
|
]
|
const applicableStores = ref<any[]>([])
|
|
const packages = ref([
|
{ id: 'food-set-001', name: '【川味盛宴】川菜12人餐', discount: '6折', price: '138', originalPrice: '266', image: '/static/food-assets/food-1.jpg' },
|
{ id: 'food-set-002', name: '【川香四溢】川菜4人餐', discount: '6折', price: '118', originalPrice: '198', image: '/static/food-assets/food-2.jpg' },
|
{ id: 'food-set-003', name: '【欢聚时光】招牌菜6人餐', discount: '6.8折', price: '168', originalPrice: '248', image: '/static/food-assets/food-1.jpg' },
|
{ id: 'food-set-004', name: '【暖心小聚】特色菜双人餐', discount: '7折', price: '88', originalPrice: '126', image: '/static/food-assets/food-2.jpg' },
|
{ id: 'food-set-005', name: '【家庭聚餐】经典川菜8人餐', discount: '6.5折', price: '238', originalPrice: '366', image: '/static/food-assets/food-1.jpg' },
|
{ id: 'food-set-006', name: '【人气必点】招牌菜4人餐', discount: '6.8折', price: '128', originalPrice: '188', image: '/static/food-assets/food-2.jpg' },
|
{ id: 'food-set-007', name: '【周末欢聚】特色菜10人餐', discount: '6折', price: '298', originalPrice: '498', image: '/static/food-assets/food-1.jpg' },
|
{ id: 'food-set-008', name: '【一人食】暖心工作餐', discount: '8折', price: '39', originalPrice: '49', image: '/static/food-assets/food-2.jpg' }
|
])
|
const hotelPackages = [
|
{ id: 101, name: '都市视野大床房', discount: '6折', price: '588-800', originalPrice: '', image: '/static/stay-assets/hotel-hampton.jpg' },
|
{ id: 102, name: '山景云窗商务双床房', discount: '6折', price: '388-600', originalPrice: '', image: '/static/stay-assets/hotel-vienna.jpg' },
|
{ id: 103, name: '都市视野大床房', discount: '6折', price: '588-800', originalPrice: '', image: '/static/stay-assets/hotel-hampton.jpg' },
|
{ id: 104, name: '行政景观大床房', discount: '6折', price: '688-920', originalPrice: '', image: '/static/stay-assets/hotel-vienna.jpg' },
|
{ id: 105, name: '亲子主题家庭房', discount: '6.5折', price: '628-860', originalPrice: '', image: '/static/stay-assets/hotel-hampton.jpg' },
|
{ id: 106, name: '高层城景双床房', discount: '6折', price: '468-680', originalPrice: '', image: '/static/stay-assets/hotel-vienna.jpg' },
|
{ id: 107, name: '豪华行政套房', discount: '6.8折', price: '988-1280', originalPrice: '', image: '/static/stay-assets/hotel-hampton.jpg' },
|
{ id: 108, name: '舒适大床房', discount: '6折', price: '428-620', originalPrice: '', image: '/static/stay-assets/hotel-vienna.jpg' }
|
]
|
// 体检医院演示套餐:图片按体验版素材规则复用“享”专题两张演示图。
|
const medicalPackages = [
|
{ id: 1, name: 'A套餐(脑血管系统筛查)', openTime: '5-6月', image: '/static/stay-assets/hotel-hampton.jpg' },
|
{ id: 2, name: 'B套餐(心血管系统筛查)', openTime: '5-6月', image: '/static/stay-assets/hotel-vienna.jpg' },
|
{ id: 3, name: 'C套餐(消化系统筛查)', openTime: '5-6月', image: '/static/stay-assets/hotel-hampton.jpg' }
|
]
|
const visiblePackages = ref<any[]>([])
|
const visibleMedicalPackages = ref<any[]>([])
|
const listLoading = ref(true)
|
const listLoaded = ref(false)
|
const listError = ref(false)
|
const failOnce = ref(false)
|
const forceEmpty = ref(false)
|
let parkingDetailLoaded = false
|
|
onLoad((options: any) => {
|
// #ifdef MP-WEIXIN
|
const capsule = uni.getMenuButtonBoundingClientRect()
|
const systemInfo = uni.getSystemInfoSync()
|
navTop.value = capsule.top
|
navHeight.value = capsule.height
|
navWidth.value = capsule.width
|
navRight.value = systemInfo.windowWidth - capsule.right
|
// #endif
|
if (options != null && options['previewState'] != null) {
|
const previewState = options['previewState'] as string
|
failOnce.value = previewState == 'initialError'
|
forceEmpty.value = previewState == 'empty'
|
}
|
if (options != null && options['merchantId'] != null && options['merchantId'] != '') merchantId.value = options['merchantId'] as string
|
if (options != null && options['name'] != null) {
|
const name = decodeURIComponent(options['name'] as string)
|
const routedMerchantType = options['merchantType'] != null ? decodeURIComponent(options['merchantType'] as string) : ''
|
const routedImage = options['image'] != null ? decodeURIComponent(options['image'] as string) : ''
|
const routedAddress = options['address'] != null ? decodeURIComponent(options['address'] as string) : ''
|
const routedDiscount = options['discount'] != null ? decodeURIComponent(options['discount'] as string) : ''
|
merchantType.value = routedMerchantType == '' ? 'food' : routedMerchantType
|
if (options['action'] != null && options['action'] == 'talentCode') parkingActionMode.value = 'talentCode'
|
if (options['plateMode'] != null && options['plateMode'] == 'withParking') parkingPlateMode.value = 'withParking'
|
if (options['type'] == 'medical') {
|
merchantType.value = 'medical'
|
isMedicalMerchant.value = true
|
merchantName.value = name
|
merchantHero.value = ''
|
merchantPrimaryTag.value = '免费'
|
merchantDiscount.value = ''
|
merchantAddress.value = '攀枝花市东区益康街34号4号综合3楼体检中心'
|
merchantLocation.value = { latitude: 26.5856, longitude: 101.7184, name: name, address: merchantAddress.value }
|
groupBuyingEnabled.value = false
|
usageInstructions.value = '①预约时间每年度5-6月,体检时间每年度6月1日-10月31日。\n②体检时请带上本人二代居民身份证。\n③检查前三天请注意休息,勿熬夜,以清淡饮食为宜,勿饮酒、忌高脂、高胆固醇食物、不吃保健品。检查前一日晚上十二点以后,请完全禁食(包括饮水)。\n④体检当天请着宽松衣物,不要穿连衣裙、连裤袜。做X线检查时,宜穿棉布内衣,勿穿带有金属纽扣的衣服、文胸;请摘去项链、手机、钢笔、钥匙等金属物品。\n⑤自费项目:体检当天,体检对象与体检医院沟通后确定,体检医院给予八折收费优惠。'
|
} else if (options['type'] == 'transport') {
|
merchantType.value = 'transport'
|
isTransportMerchant.value = true
|
isFuelMerchant.value = routedMerchantType == 'fuel' || name == '加油服务'
|
if (routedMerchantType == 'parking' || name.indexOf('停车') >= 0) {
|
isParkingMerchant.value = true
|
merchantName.value = '停车服务'
|
merchantHero.value = ''
|
merchantPrimaryTag.value = '免费'
|
merchantDiscount.value = ''
|
merchantAddress.value = '攀枝花市东区渡口公司管辖停车场'
|
merchantLocation.value = { latitude: 26.5856, longitude: 101.7184, name: merchantName.value, address: merchantAddress.value }
|
groupBuyingEnabled.value = false
|
usageInstructions.value = '登记信息后可享受渡口公司管辖的49处停车场免费停车服务'
|
} else {
|
merchantName.value = name == '加油服务' ? '中国石油东区新福路加油站' : name
|
merchantHero.value = ''
|
merchantPrimaryTag.value = '券'
|
merchantDiscount.value = '9.4折'
|
merchantAddress.value = '四川省攀枝花市东区新福路20号附3-21号'
|
merchantLocation.value = { latitude: 26.5856, longitude: 101.7184, name: merchantName.value, address: merchantAddress.value }
|
groupBuyingEnabled.value = false
|
usageInstructions.value = '持人才卡到店加油,出示人才码后按当日油价享受专属折扣;具体适用油品、活动库存和使用规则以加油站现场为准。'
|
merchantServiceLabel.value = '加油服务'
|
merchantRightsText.value = '持卓越人才卡到站加油并出示人才码,可享指定油品 9.4 折优惠,具体适用油品、优惠上限、可用时段和活动库存以加油站现场说明为准。'
|
}
|
} else if (routedMerchantType == 'hotel' || name.indexOf('酒店') >= 0) {
|
isHotelMerchant.value = true
|
merchantType.value = 'hotel'
|
merchantName.value = name
|
merchantHero.value = routedImage
|
merchantDiscount.value = routedDiscount == '' ? '6折' : routedDiscount
|
hasFreeVoucher.value = merchantDiscount.value.indexOf('免费') >= 0
|
merchantPrimaryTag.value = hasFreeVoucher.value ? '券' : '惠'
|
merchantAddress.value = routedAddress == '' ? '西区清香坪北街51号' : routedAddress
|
merchantLocation.value = { latitude: 26.5856, longitude: 101.7184, name: name, address: merchantAddress.value }
|
packages.value = hotelPackages
|
merchantServiceLabel.value = '住宿服务'
|
merchantRightsText.value = '持卓越人才卡入住可享商户配置的住宿权益,具体房型、价格、可用日期和预约规则以酒店实际说明为准。'
|
} else {
|
merchantName.value = name
|
if (routedImage != '') merchantHero.value = routedImage
|
if (routedAddress != '') merchantAddress.value = routedAddress
|
if (routedDiscount != '') merchantDiscount.value = routedDiscount
|
merchantLocation.value = { latitude: 26.5856, longitude: 101.7184, name: merchantName.value, address: merchantAddress.value }
|
|
if (routedMerchantType == 'scenic') {
|
merchantPrimaryTag.value = '权益'
|
groupBuyingEnabled.value = false
|
merchantServiceLabel.value = '景区服务'
|
usageInstructions.value = '到达景区后出示人才码,根据景区后台配置的权益规则核验使用;开放时间、适用区域及预约要求以景区现场说明为准。'
|
merchantRightsText.value = '持卓越人才卡可享该景区配置的专属游览权益,具体优惠内容、开放时间、预约方式和使用限制以景区说明为准。'
|
} else if (routedMerchantType == 'apartment') {
|
merchantPrimaryTag.value = '惠'
|
groupBuyingEnabled.value = false
|
merchantServiceLabel.value = '住宿服务'
|
usageInstructions.value = '到店后出示人才码并按人才公寓或驿站的后台配置提交入住申请,房源、入住时长及审核要求以服务方说明为准。'
|
merchantRightsText.value = '持卓越人才卡可申请该人才公寓或驿站配置的住宿权益,具体房源、租金、入住期限和申请条件以服务方说明为准。'
|
} else if (routedMerchantType != '' && routedMerchantType != 'food') {
|
merchantPrimaryTag.value = '权益'
|
groupBuyingEnabled.value = false
|
merchantServiceLabel.value = '人才服务'
|
usageInstructions.value = '到店后出示人才码,根据服务机构后台配置的权益规则进行核验使用。'
|
merchantRightsText.value = '持卓越人才卡可享该服务机构配置的人才专属权益,具体内容与使用规则以服务机构说明为准。'
|
} else {
|
merchantType.value = 'food'
|
merchantPrimaryTag.value = '券'
|
merchantServiceLabel.value = '到店消费'
|
merchantRightsText.value = '持卓越人才卡到店消费可享商户配置的餐饮优惠,具体可用时段、适用菜品和使用规则以商户现场说明为准。'
|
}
|
}
|
}
|
const session = getSession()
|
if (session != null && session.talentId != null) talentId.value = session.talentId as string
|
if (talentId.value == '' && apiEnvironment == 'development') talentId.value = '2'
|
if (isFuelMerchant.value || isParkingMerchant.value) {
|
loadTransportMerchantDetail()
|
} else {
|
loadRemoteMerchant()
|
loadMerchantLists()
|
}
|
})
|
const loadTransportMerchantDetail = () => {
|
if (isFuelMerchant.value) { loadFuelMerchant(); return }
|
if (isParkingMerchant.value) { loadParkingMerchant(); return }
|
loadRemoteMerchant()
|
}
|
const loadFuelMerchant = () => {
|
if (!isApiConfigured() || !/^\d+$/.test(merchantId.value)) {
|
merchantLoading.value = false
|
merchantError.value = true
|
return
|
}
|
merchantLoading.value = true
|
merchantError.value = false
|
listLoading.value = true
|
listLoaded.value = false
|
listError.value = false
|
getFuelMerchantDetail(merchantId.value, (data: any) => {
|
merchantName.value = data != null && data.merchantName != null ? data.merchantName as string : ''
|
merchantAddress.value = data != null && data.address != null ? data.address as string : ''
|
merchantPhone.value = data != null && data.contactMobile != null ? data.contactMobile as string : ''
|
merchantAvailable.value = data != null && (data.available === true || Number(data.available) == 1)
|
merchantDiscount.value = data != null && data.discountText != null ? data.discountText as string : '请咨询商户'
|
merchantServiceLabel.value = data != null && data.serviceLabel != null ? data.serviceLabel as string : '请咨询商户'
|
applicableCards.value = data != null && data.applicableCards != null ? data.applicableCards as string : '请咨询商户'
|
usageInstructions.value = data != null && data.usageInstructions != null ? data.usageInstructions as string : '请咨询商户'
|
merchantRightsText.value = data != null && data.rightsText != null ? data.rightsText as string : '请咨询商户'
|
groupBuyingEnabled.value = false
|
merchantType.value = 'fuel'
|
const heroes: any[] = data != null && data.heroImages instanceof Array ? data.heroImages as any[] : []
|
if (heroes.length > 0 && heroes[0].imageUrl != null && heroes[0].imageUrl != '') merchantHero.value = resolveApiUrl(heroes[0].imageUrl as string)
|
fuelBenefitId.value = data != null && data.benefit != null && data.benefit.benefitId != null ? '' + data.benefit.benefitId : ''
|
merchantLocation.value = {
|
latitude: data != null && data.latitude != null ? Number(data.latitude) : 0,
|
longitude: data != null && data.longitude != null ? Number(data.longitude) : 0,
|
name: merchantName.value,
|
address: merchantAddress.value
|
}
|
const stores: any[] = data != null && data.applicableStores instanceof Array ? data.applicableStores as any[] : []
|
applicableStores.value = stores.map((item: any) => ({
|
id: '' + item.id,
|
name: item.storeName != null ? item.storeName as string : '',
|
address: item.address != null ? item.address as string : '',
|
latitude: item.latitude != null ? Number(item.latitude) : 0,
|
longitude: item.longitude != null ? Number(item.longitude) : 0,
|
canNavigate: item.canNavigate === true || Number(item.canNavigate) == 1
|
}))
|
merchantLoading.value = false
|
listLoading.value = false
|
listLoaded.value = true
|
if (!merchantAvailable.value) currentTab.value = 'primary'
|
}, () => {
|
merchantLoading.value = false
|
merchantError.value = true
|
listLoading.value = false
|
listError.value = true
|
})
|
}
|
const loadParkingMerchant = () => {
|
if (!isApiConfigured() || !/^\d+$/.test(merchantId.value)) {
|
merchantLoading.value = false
|
merchantError.value = true
|
return
|
}
|
merchantLoading.value = true
|
merchantError.value = false
|
listLoading.value = true
|
listLoaded.value = false
|
listError.value = false
|
getParkingMerchantDetail(merchantId.value, (data: any) => {
|
merchantName.value = data != null && data.merchantName != null ? data.merchantName as string : ''
|
merchantHero.value = data != null && data.coverUrl != null && data.coverUrl != '' ? resolveApiUrl(data.coverUrl as string) : fallbackImage
|
merchantAddress.value = data != null && data.address != null ? data.address as string : ''
|
merchantPhone.value = data != null && data.contactMobile != null ? data.contactMobile as string : ''
|
merchantAvailable.value = data != null && (data.available === true || Number(data.available) == 1)
|
merchantUnavailableReason.value = data != null && data.unavailableReason != null && data.unavailableReason != '' ? data.unavailableReason as string : '该停车权益暂不可用'
|
merchantServiceLabel.value = data != null && data.serviceLabel != null ? data.serviceLabel as string : '停车服务'
|
parkingBenefitText.value = data != null && data.benefitText != null ? data.benefitText as string : '免费停车'
|
applicableCards.value = data != null && data.applicableCards != null ? data.applicableCards as string : '请咨询商户'
|
usageInstructions.value = data != null && data.usageInstructions != null ? data.usageInstructions as string : '请咨询商户'
|
merchantRightsText.value = data != null && data.rightsText != null ? data.rightsText as string : '请咨询商户'
|
parkingActionMode.value = data != null && data.actionMode == 'talentCode' ? 'talentCode' : 'plate'
|
parkingPlateMode.value = data != null && data.plateFormMode == 'withParking' ? 'withParking' : 'simple'
|
parkingBenefitId.value = data != null && data.benefit != null && data.benefit.benefitId != null ? '' + data.benefit.benefitId : ''
|
groupBuyingEnabled.value = false
|
merchantType.value = 'parking'
|
merchantLocation.value = {
|
latitude: data != null && data.latitude != null ? Number(data.latitude) : 0,
|
longitude: data != null && data.longitude != null ? Number(data.longitude) : 0,
|
name: merchantName.value,
|
address: merchantAddress.value
|
}
|
const stores: any[] = data != null && data.applicableStores instanceof Array ? data.applicableStores as any[] : []
|
applicableStores.value = stores.map((item: any) => ({
|
id: '' + item.id,
|
name: item.storeName != null ? item.storeName as string : '',
|
address: item.address != null ? item.address as string : '',
|
latitude: item.latitude != null ? Number(item.latitude) : 0,
|
longitude: item.longitude != null ? Number(item.longitude) : 0,
|
canNavigate: item.canNavigate === true || Number(item.canNavigate) == 1
|
}))
|
merchantLoading.value = false
|
listLoading.value = false
|
listLoaded.value = true
|
parkingDetailLoaded = true
|
}, () => {
|
merchantLoading.value = false
|
merchantError.value = true
|
listLoading.value = false
|
listError.value = true
|
})
|
}
|
onShow(() => {
|
if (isParkingMerchant.value && parkingDetailLoaded) loadParkingMerchant()
|
})
|
const loadRemoteMerchant = () => {
|
if (isFuelMerchant.value || isParkingMerchant.value) { loadTransportMerchantDetail(); return }
|
if (!isApiConfigured() || !/^\d+$/.test(merchantId.value)) return
|
merchantLoading.value = true
|
merchantError.value = false
|
getMerchantDetail(merchantId.value, (data: any) => {
|
merchantName.value = data != null && data.merchantName != null ? data.merchantName as string : merchantName.value
|
merchantHero.value = data != null && data.coverUrl != null && data.coverUrl != '' ? resolveApiUrl(data.coverUrl as string) : merchantHero.value
|
merchantAddress.value = data != null && data.address != null ? data.address as string : merchantAddress.value
|
const rawType = data != null && data.merchantType != null ? data.merchantType as string : merchantType.value
|
merchantType.value = rawType == '餐饮服务' ? 'food' : rawType
|
merchantAvailable.value = data == null || data.available !== false
|
merchantPhone.value = data != null && data.contactMobile != null ? data.contactMobile as string : ''
|
merchantDiscount.value = data != null && data.discountText != null ? data.discountText as string : merchantDiscount.value
|
merchantServiceLabel.value = data != null && data.serviceLabel != null && data.serviceLabel != '' ? data.serviceLabel as string : merchantServiceLabel.value
|
merchantRightsText.value = data != null && data.rightsText != null && data.rightsText != '' ? data.rightsText as string : merchantRightsText.value
|
usageInstructions.value = data != null && data.usageInstructions != null && data.usageInstructions != '' ? data.usageInstructions as string : usageInstructions.value
|
groupBuyingEnabled.value = data == null || data.groupBuyingEnabled == null ? groupBuyingEnabled.value : data.groupBuyingEnabled === true || Number(data.groupBuyingEnabled) == 1
|
isHotelMerchant.value = merchantType.value == 'hotel'
|
hasFreeVoucher.value = merchantDiscount.value.indexOf('免费') >= 0
|
merchantLocation.value = {
|
latitude: data != null && data.latitude != null ? Number(data.latitude) : 0,
|
longitude: data != null && data.longitude != null ? Number(data.longitude) : 0,
|
name: merchantName.value,
|
address: merchantAddress.value
|
}
|
merchantLoading.value = false
|
if (!merchantAvailable.value) {
|
visiblePackages.value = []
|
currentTab.value = 'rights'
|
}
|
}, () => {
|
merchantLoading.value = false
|
merchantError.value = true
|
})
|
}
|
const retryMerchantDetail = () => { if (isFuelMerchant.value || isParkingMerchant.value) loadTransportMerchantDetail(); else loadRemoteMerchant() }
|
const loadMerchantLists = () => {
|
if (isFuelMerchant.value || isParkingMerchant.value) { loadTransportMerchantDetail(); return }
|
listLoading.value = true
|
listLoaded.value = false
|
listError.value = false
|
if (isApiConfigured() && /^\d+$/.test(merchantId.value) && isMedicalMerchant.value) {
|
getMedicalPackages(merchantId.value, (data: any) => {
|
const records: any[] = data instanceof Array ? data as any[] : []
|
const packages: any[] = []
|
for (let index = 0; index < records.length; index++) {
|
const item: any = records[index]
|
packages.push({ id: '' + item.id, name: item.name || '体检套餐', openTime: item.openTime || '以医院通知为准', image: item.heroImage != null && item.heroImage != '' ? resolveApiUrl(item.heroImage as string) : fallbackImage, available: item.available === true, unavailableReason: item.unavailableReason || '' })
|
}
|
visibleMedicalPackages.value = packages
|
visiblePackages.value = []
|
applicableStores.value = []
|
listLoading.value = false
|
listLoaded.value = true
|
}, () => { listLoading.value = false; listError.value = true })
|
return
|
}
|
if (isApiConfigured() && /^\d+$/.test(merchantId.value) && !isMedicalMerchant.value && !isTransportMerchant.value) {
|
getProducts(merchantId.value, 1, 20, (data: any) => {
|
const records: any[] = data != null && data.records instanceof Array ? data.records as any[] : []
|
const remotePackages: any[] = []
|
for (let index = 0; index < records.length; index++) {
|
const item: any = records[index]
|
const sale = item.salePrice != null ? Number(item.salePrice) : 0
|
const original = item.originalPrice != null ? Number(item.originalPrice) : 0
|
const stock = item.stock != null ? Number(item.stock) : -1
|
remotePackages.push({ id: '' + item.id, name: item.productName != null ? item.productName as string : '人才专享套餐', discount: sale > 0 && original > sale ? '' + Math.round(sale / original * 100) / 10 + '折' : '人才专享', price: '' + sale, originalPrice: original > 0 ? '' + original : '', image: item.coverUrl != null && item.coverUrl != '' ? resolveApiUrl(item.coverUrl as string) : fallbackImage, available: stock != 0 })
|
}
|
visiblePackages.value = remotePackages
|
visibleMedicalPackages.value = []
|
applicableStores.value = []
|
listLoading.value = false
|
listLoaded.value = true
|
}, () => {
|
listLoading.value = false
|
listError.value = true
|
})
|
return
|
}
|
if (apiEnvironment != 'development') {
|
listLoading.value = false
|
listError.value = true
|
return
|
}
|
setTimeout(() => {
|
if (failOnce.value) { failOnce.value = false; listLoading.value = false; listError.value = true; return }
|
visiblePackages.value = forceEmpty.value ? [] : packages.value
|
visibleMedicalPackages.value = forceEmpty.value ? [] : medicalPackages
|
applicableStores.value = forceEmpty.value ? [] : allApplicableStores
|
listLoading.value = false
|
listLoaded.value = true
|
}, 450)
|
}
|
|
const goBack = () => safeBack('/pages/benefits/benefits')
|
const handleScroll = (event: any) => {
|
const shouldShow = event.detail.scrollTop > 64
|
if (isSolidNav.value != shouldShow) isSolidNav.value = shouldShow
|
}
|
const changeTab = (name: string) => { currentTab.value = name }
|
const openMap = () => {
|
if (merchantLocation.value.latitude <= 0 || merchantLocation.value.longitude <= 0) {
|
uni.showToast({ title: '商户暂未配置位置', icon: 'none' })
|
return
|
}
|
uni.openLocation({
|
latitude: merchantLocation.value.latitude,
|
longitude: merchantLocation.value.longitude,
|
name: merchantLocation.value.name,
|
address: merchantLocation.value.address,
|
scale: 18,
|
fail: () => uni.showToast({ title: '暂时无法打开地图导航', icon: 'none' })
|
})
|
}
|
const callMerchant = () => {
|
if (merchantPhone.value.trim().length == 0) {
|
uni.showToast({ title: '商户暂未配置联系电话', icon: 'none' })
|
return
|
}
|
uni.makePhoneCall({ phoneNumber: merchantPhone.value })
|
}
|
const openStoreLocation = (item: any) => {
|
if (item.canNavigate === false || Number(item.latitude) <= 0 || Number(item.longitude) <= 0) {
|
uni.showToast({ title: '该门店暂未配置位置', icon: 'none' })
|
return
|
}
|
uni.openLocation({
|
latitude: Number(item.latitude),
|
longitude: Number(item.longitude),
|
name: item.name,
|
address: item.address,
|
scale: 18,
|
fail: () => uni.showToast({ title: '暂时无法打开该门店位置', icon: 'none' })
|
})
|
}
|
const handlePackage = (item: any) => {
|
if (!merchantAvailable.value) {
|
uni.showToast({ title: '该商户已停业或下架', icon: 'none' })
|
return
|
}
|
if (item.available === false) {
|
uni.showToast({ title: '该套餐已售罄', icon: 'none' })
|
return
|
}
|
if (isHotelMerchant.value) {
|
uni.navigateTo({
|
url: '/pages/hotel-booking/hotel-booking?hotelName='
|
+ encodeURIComponent(merchantName.value)
|
+ '&hotelAddress=' + encodeURIComponent(merchantAddress.value)
|
+ '&roomName=' + encodeURIComponent(item.name)
|
})
|
return
|
}
|
uni.navigateTo({
|
url: '/pages/product-detail/product-detail?merchantId=' + encodeURIComponent(merchantId.value)
|
+ '&productId=' + encodeURIComponent(item.id)
|
+ '&name=' + encodeURIComponent(item.name)
|
+ '&image=' + encodeURIComponent(item.image)
|
+ '&price=' + encodeURIComponent(item.price)
|
+ '&originalPrice=' + encodeURIComponent(item.originalPrice)
|
+ '&discount=' + encodeURIComponent(item.discount)
|
})
|
}
|
const openMedicalPackage = (item: any) => {
|
if (item.available === false) { uni.showToast({ title: item.unavailableReason || '该套餐暂不可预约', icon: 'none' }); return }
|
uni.navigateTo({ url: '/pages/medical-package/medical-package?packageId=' + encodeURIComponent(item.id) + '&hospitalId=' + encodeURIComponent(merchantId.value) + '&name=' + encodeURIComponent(item.name) + '&hospital=' + encodeURIComponent(merchantName.value) })
|
}
|
const showBottomVoucher = () => {
|
if (hasFreeVoucher.value) {
|
uni.navigateTo({ url: '/pages/free-benefit/free-benefit?merchantId=' + encodeURIComponent(merchantId.value) })
|
return
|
}
|
uni.navigateTo({ url: '/pages/talent-code/talent-code?talentId=' + encodeURIComponent(talentId.value) + '&merchantId=' + encodeURIComponent(merchantId.value) + '&scene=' + encodeURIComponent(isParkingMerchant.value ? 'parking' : 'merchant') })
|
}
|
const openMobileDialog = () => {
|
mobileError.value = ''
|
if (isFuelMerchant.value) fuelRegistrationKey.value = 'fuel-registration-' + merchantId.value + '-' + Date.now()
|
showMobileDialog.value = true
|
}
|
const closeMobileDialog = () => { showMobileDialog.value = false; mobileError.value = '' }
|
const submitMobile = () => {
|
if (isSubmittingMobile.value) return
|
const value = mobile.value.trim()
|
if (!/^1[3-9][0-9]{9}$/.test(value)) {
|
mobileError.value = '请输入正确的 11 位手机号'
|
return
|
}
|
isSubmittingMobile.value = true
|
if (isFuelMerchant.value) {
|
if (talentId.value == '' || fuelBenefitId.value == '') {
|
isSubmittingMobile.value = false
|
mobileError.value = talentId.value == '' ? '请登录后提交手机号' : '加油权益暂未配置'
|
return
|
}
|
if (fuelRegistrationKey.value == '') fuelRegistrationKey.value = 'fuel-registration-' + merchantId.value + '-' + Date.now()
|
submitFuelMobileRegistration(merchantId.value, talentId.value, fuelBenefitId.value, value, fuelRegistrationKey.value, (data: any) => {
|
isSubmittingMobile.value = false
|
closeMobileDialog()
|
mobile.value = ''
|
uni.navigateTo({
|
url: '/pages/transport-submit-success/transport-submit-success?type=transport&merchantType=fuel'
|
+ '&merchantId=' + encodeURIComponent(merchantId.value)
|
+ '&name=' + encodeURIComponent(merchantName.value)
|
+ '®istrationId=' + encodeURIComponent(data != null && data.registrationId != null ? '' + data.registrationId : '')
|
})
|
}, (error) => {
|
isSubmittingMobile.value = false
|
mobileError.value = error.message
|
})
|
return
|
}
|
submitBusiness('transportMobileRegistration', { merchantId: merchantId.value, merchantType: merchantType.value, mobile: value }, () => {
|
isSubmittingMobile.value = false
|
closeMobileDialog()
|
mobile.value = ''
|
uni.navigateTo({ url: '/pages/transport-submit-success/transport-submit-success' })
|
}, (error) => {
|
isSubmittingMobile.value = false
|
mobileError.value = error.message
|
})
|
}
|
const openPlatePage = () => {
|
if (parkingBenefitId.value == '') {
|
uni.showToast({ title: '停车权益暂未配置', icon: 'none' })
|
return
|
}
|
uni.navigateTo({
|
url: '/pages/plate-info/plate-info?merchantId=' + encodeURIComponent(merchantId.value)
|
+ '&benefitId=' + encodeURIComponent(parkingBenefitId.value)
|
+ '&mode=' + encodeURIComponent(parkingPlateMode.value)
|
+ '&name=' + encodeURIComponent(merchantName.value)
|
})
|
}
|
</script>
|
|
<style>
|
.page { width: 100%; height: 100vh; background-color: #F6F6F6; }
|
.content { height: calc(100% - 150rpx); height: calc(100% - 150rpx - env(safe-area-inset-bottom)); background-color: #F6F6F6; }
|
.hero { height: 445rpx; position: relative; overflow: hidden; background-color: #3B3028; }
|
.hero-image { position: absolute; left: 0; top: 0; width: 100%; height: 445rpx; }
|
.hero-shade { position: absolute; left: 0; right: 0; top: 0; height: 190rpx; background-image: linear-gradient(180deg, rgba(0,0,0,.58) 0%, rgba(0,0,0,0) 100%); }
|
.custom-nav { position: fixed; z-index: 20; left: 0; right: 0; top: 0; padding-bottom: 20rpx; }
|
.custom-nav-bg { position: absolute; z-index: 0; left: 0; right: 0; top: 0; bottom: 0; opacity: 0; background-image: linear-gradient(180deg, #F26A38 0%, #EE542B 100%); transition: opacity 280ms ease-out; }
|
.custom-nav.is-solid .custom-nav-bg { opacity: 1; }
|
.safe-space { height: 28px; position: relative; z-index: 2; }
|
.nav-row { display: flex; height: 32px; box-sizing: border-box; padding-left: 24rpx; padding-right: 10px; position: relative; z-index: 2; flex-direction: row; align-items: center; justify-content: space-between; }
|
.back-button { display: flex; width: 54rpx; height: 54rpx; position: relative; z-index: 2; border-radius: 50%; background-color: rgba(45,45,45,.52); transition: background-color 280ms ease-out; justify-content: center; align-items: center; }
|
.custom-nav.is-solid .back-button { background-color: rgba(45,45,45,0); }
|
.back-button image { width: 34rpx; height: 34rpx; }
|
.nav-title { position: absolute; z-index: 1; left: 105rpx; right: 105rpx; opacity: 0; color: #FFFFFF; font-size: 29rpx; font-weight: 600; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: opacity 280ms ease-out; }
|
.custom-nav.is-solid .nav-title { opacity: 1; }
|
.custom-nav.is-hotel .nav-title { opacity: 1; }
|
.capsule-space { width: 88px; height: 100%; flex-shrink: 0; }
|
.merchant-panel { position: relative; z-index: 3; margin-top: -22rpx; border-top-left-radius: 27rpx; border-top-right-radius: 27rpx; overflow: hidden; background-color: #F6F6F6; }
|
.merchant-info-card { padding: 25rpx 38rpx 20rpx; background-color: #F6F6F6; }
|
.merchant-detail-state { display: flex; height: 280rpx; color: #969CA5; font-size: 25rpx; flex-direction: row; justify-content: center; align-items: center; }
|
.merchant-unavailable { margin-bottom: 18rpx; box-sizing: border-box; padding: 14rpx 18rpx; border-radius: 10rpx; background-color: #FFF0EC; }
|
.merchant-unavailable text { color: #E55C3D; font-size: 24rpx; line-height: 34rpx; }
|
.merchant-title-row { display: flex; min-height: 50rpx; flex-direction: row; align-items: center; justify-content: space-between; }
|
.parking-title-block { display: flex; flex-direction: column; }
|
.parking-title-row { display: flex; min-height: 54rpx; flex-direction: row; align-items: center; justify-content: space-between; }
|
.parking-title-row .round-action { margin-left: 20rpx; }
|
.parking-free { margin-top: 5rpx; color: #FF5A36; font-size: 24rpx; line-height: 34rpx; }
|
.merchant-title { min-width: 0; flex: 1; color: #292929; font-size: 35rpx; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
.merchant-tags { display: flex; margin-left: 15rpx; flex-direction: row; align-items: center; flex-shrink: 0; }
|
.coupon-tag { padding: 6rpx 8rpx; border-radius: 5rpx; background-color: #FFF0EC; color: #FF5D37; font-size: 24rpx; }
|
.discount-tag { margin-left: 10rpx; padding: 6rpx 9rpx; border-radius: 5rpx; background-color: #FFF5E7; color: #FF7C2B; font-size: 24rpx; }
|
.service-tags { display: flex; margin-top: 16rpx; flex-direction: row; }
|
.service-tags text { margin-right: 10rpx; padding: 6rpx 11rpx; border-width: 1rpx; border-style: solid; border-color: #FF9B70; border-radius: 5rpx; color: #EF7046; font-size: 24rpx; }
|
.merchant-address-row { display: flex; min-height: 72rpx; margin-top: 16rpx; flex-direction: row; align-items: flex-start; }
|
.address-icon { width: 27rpx; height: 27rpx; margin-top: 4rpx; margin-right: 8rpx; flex-shrink: 0; }
|
.merchant-address-row > text { width: 420rpx; min-width: 0; max-width: 420rpx; color: #7B8491; font-size: 24rpx; line-height: 34rpx; }
|
.merchant-actions { display: flex; margin-left: auto; flex-direction: row; align-items: flex-start; flex-shrink: 0; }
|
.round-action { display: flex; width: 52rpx; height: 52rpx; border-radius: 50%; background-color: #F2F3F5; flex-shrink: 0; justify-content: center; align-items: center; }
|
.round-action.is-disabled { opacity: .4; }
|
.merchant-actions .round-action:last-child { margin-left: 30rpx; }
|
.round-action image { width: 27rpx; height: 27rpx; }
|
.tabs { display: flex; height: 85rpx; padding: 0 38rpx; background-color: #F6F6F6; flex-direction: row; align-items: center; }
|
.tab-item { display: flex; height: 85rpx; margin-right: 54rpx; position: relative; color: #82868D; font-size: 32rpx; justify-content: center; align-items: center; }
|
.tab-item.active { color: #303030; font-weight: 600; }
|
.tab-line { position: absolute; left: 50%; bottom: 0; width: 59rpx; height: 7rpx; margin-left: -30rpx; border-radius: 4rpx; opacity: 0; background-image: linear-gradient(90deg, #FF4D36 0%, #FFBF3A 100%); }
|
.tab-item.active .tab-line { opacity: 1; }
|
.package-list { margin: 16rpx 25rpx 0; background-color: transparent; }
|
.list-state { display:flex; height:310rpx; flex-direction:row; justify-content:center; align-items:center; color:#969CA5; font-size:25rpx; }
|
.error-state { flex-direction:column; }
|
.retry-text { margin-top:20rpx; color:#F26A38; }
|
.loading-spinner { width:28rpx; height:28rpx; margin-right:13rpx; box-sizing:border-box; border:3rpx solid #FFD6C4; border-top-color:#FF6C2B; border-radius:50%; animation:merchant-list-loading 720ms linear infinite; }
|
@keyframes merchant-list-loading { from { transform:rotate(0deg); } to { transform:rotate(360deg); } }
|
.usage-panel { min-height: 548rpx; margin: 16rpx 25rpx 0; box-sizing: border-box; padding: 31rpx 27rpx; border-radius: 15rpx; background-color: #FFFFFF; }
|
.usage-panel text { color: #777F8B; font-size: 27rpx; line-height: 43rpx; white-space: pre-wrap; }
|
.package-item { display: flex; min-height: 218rpx; margin-bottom: 20rpx; box-sizing: border-box; padding: 20rpx 18rpx; border-radius: 15rpx; background-color: #FFFFFF; flex-direction: row; }
|
.package-item.is-sold-out { opacity: .56; }
|
.package-item.is-sold-out .buy-button { background-color: #A8ADB5; background-image: none; }
|
.package-item:last-child { margin-bottom: 0; }
|
.package-item-active { opacity: .78; }
|
.package-image { width: 168rpx; height: 168rpx; border-radius: 14rpx; flex-shrink: 0; }
|
.package-info { display: flex; min-width: 0; flex: 1; padding-left: 23rpx; flex-direction: column; }
|
.package-name { color: #292929; font-size: 31rpx; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
.package-tags { display: flex; margin-top: 13rpx; flex-direction: row; align-items: center; }
|
.package-bottom { display: flex; height: 57rpx; margin-top: auto; box-sizing: border-box; padding-left: 10rpx; border-radius: 29rpx; background-image: linear-gradient(90deg, rgba(255,247,240,.18) 0%, rgba(255,235,218,.72) 58%, rgba(255,222,195,.96) 100%); flex-direction: row; align-items: center; justify-content: space-between; }
|
.price-row { display: flex; height: 52rpx; flex-direction: row; align-items: center; }
|
.price-symbol { color: #FF4C2B; font-size: 28rpx; }
|
.price { margin-left: 3rpx; color: #FF4C2B; font-size: 38rpx; font-weight: 700; }
|
.old-price { margin-left: 12rpx; color: #B2B2B2; font-size: 24rpx; text-decoration: line-through; }
|
.buy-button { display: flex; width: 132rpx; height: 57rpx; border-radius: 29rpx; background-image: linear-gradient(90deg, #FF5733 0%, #FF8A20 100%); justify-content: center; align-items: center; }
|
.buy-button text { color: #FFFFFF; font-size: 27rpx; }
|
.rights-panel { margin: 16rpx 25rpx 0; padding: 28rpx 26rpx; border-radius: 15rpx; background-color: #FFFFFF; }
|
.rights-title { display: block; color: #303030; font-size: 32rpx; font-weight: 700; }
|
.rights-text { display: block; margin-top: 18rpx; color: #777F8B; font-size: 27rpx; line-height: 43rpx; }
|
.rule-row { display: flex; min-height: 70rpx; margin-top: 9rpx; border-top-width: 1rpx; border-top-style: solid; border-top-color: #F0F0F0; flex-direction: row; align-items: center; justify-content: space-between; color: #7D838C; font-size: 26rpx; }
|
.rule-row text:last-child { color: #3C424A; }
|
.store-panel { margin: 16rpx 25rpx 0; overflow: hidden; border-width: 2rpx; border-style: solid; border-color: #DCE7FA; border-radius: 16rpx; background-color: #FFFFFF; }
|
.store-table-header { display: flex; min-height: 67rpx; background-color: #EEF4FF; flex-direction: row; align-items: center; }
|
.store-head-name, .store-head-address { display: flex; height: 67rpx; box-sizing: border-box; padding: 0 13rpx; justify-content: flex-start; align-items: center; }
|
.store-head-name { width: 250rpx; }
|
.store-head-address { min-width: 0; flex: 1; }
|
.store-head-action { width: 72rpx; height: 67rpx; flex-shrink: 0; }
|
.store-head-name text, .store-head-address text { width: 100%; color: #26374F; font-size: 23rpx; font-weight: 700; text-align: left; }
|
.store-row { display: flex; min-height: 92rpx; border-top-width: 1rpx; border-top-style: solid; border-top-color: #E7ECF4; flex-direction: row; align-items: stretch; }
|
.store-name-cell { display: flex; width: 250rpx; box-sizing: border-box; padding: 17rpx 13rpx; border-right-width: 1rpx; border-right-style: solid; border-right-color: #E7ECF4; align-items: center; justify-content: flex-start; }
|
.store-address-cell { display: flex; min-width: 0; flex: 1; box-sizing: border-box; padding: 17rpx 13rpx; align-items: center; justify-content: flex-start; }
|
.store-name-cell text, .store-address-cell text { width: 100%; color: #48566A; font-size: 21rpx; line-height: 31rpx; text-align: left; }
|
.store-location { display: flex; width: 72rpx; flex-shrink: 0; justify-content: center; align-items: center; }
|
.store-location image { width: 34rpx; height: 34rpx; box-sizing: border-box; padding: 4rpx; border-width: 2rpx; border-style: solid; border-color: #8BB9FF; border-radius: 50%; background-color: #EEF6FF; }
|
.store-location.is-disabled { opacity: .4; }
|
.content-bottom { height: 35rpx; }
|
.content-full { height: 100%; }
|
.medical-free-tag { margin-left: 15rpx; color: #FF7C2B; font-size: 26rpx; flex-shrink: 0; }
|
.medical-package-list { margin: 16rpx 25rpx 0; }
|
.medical-package-item { display: flex; min-height: 218rpx; margin-bottom: 20rpx; box-sizing: border-box; padding: 20rpx 18rpx; border-radius: 15rpx; background-color: #FFFFFF; flex-direction: row; }
|
.medical-package-item:last-child { margin-bottom: 0; }
|
.medical-package-image { width: 168rpx; height: 168rpx; border-radius: 14rpx; flex-shrink: 0; }
|
.medical-package-info { display: flex; min-width: 0; flex: 1; padding-left: 23rpx; flex-direction: column; }
|
.medical-package-name { color: #292929; font-size: 31rpx; font-weight: 700; }
|
.medical-package-bottom { display: flex; margin-top: auto; flex-direction: row; align-items: center; justify-content: space-between; }
|
.medical-open-row { display: flex; flex-direction: row; align-items: center; }
|
.medical-open-label { color: #8A919C; font-size: 24rpx; }
|
.medical-open-value { margin-left: 14rpx; color: #FF7C2B; font-size: 26rpx; font-weight: 600; }
|
.medical-view-button { display: flex; width: 132rpx; height: 57rpx; border-radius: 29rpx; background-image: linear-gradient(90deg, #FF5733 0%, #FF8A20 100%); justify-content: center; align-items: center; }
|
.medical-view-button text { color: #FFFFFF; font-size: 27rpx; }
|
.medical-usage-panel { min-height: 548rpx; margin: 16rpx 25rpx 0; box-sizing: border-box; padding: 31rpx 27rpx; border-radius: 15rpx; background-color: #EFF1F4; }
|
.medical-usage-panel text { color: #777F8B; font-size: 27rpx; line-height: 43rpx; white-space: pre-wrap; }
|
.action-bar { display: flex; height: 150rpx; height: calc(150rpx + env(safe-area-inset-bottom)); box-sizing: border-box; padding: 20rpx 34rpx 2rpx; padding-bottom: calc(2rpx + env(safe-area-inset-bottom)); background-color: #FFFFFF; box-shadow: 0 -5rpx 15rpx rgba(0,0,0,.06); flex-direction: column; justify-content: flex-end; }
|
.talent-code-button { display: flex; width: 100%; height: 90rpx; flex-shrink: 0; border-radius: 46rpx; background-image: linear-gradient(90deg, #FF4D32 0%, #FF8A20 100%); flex-direction: row; justify-content: center; align-items: center; }
|
.talent-code-button image { width: 29rpx; height: 29rpx; margin-right: 14rpx; }
|
.talent-code-button text { color: #FFFFFF; font-size: 31rpx; font-weight: 500; }
|
.mobile-dialog-mask { display: flex; position: fixed; z-index: 100; left: 0; right: 0; top: 0; bottom: 0; background-color: rgba(24,29,38,.48); justify-content: center; align-items: center; }
|
.mobile-dialog { display: flex; width: 664rpx; min-height: 430rpx; position: relative; box-sizing: border-box; padding: 61rpx 48rpx 38rpx; border-radius: 34rpx; background-color: #FFFFFF; flex-direction: column; align-items: center; }
|
.mobile-dialog-close { display: flex; width: 64rpx; height: 64rpx; position: absolute; right: 28rpx; top: 22rpx; justify-content: center; align-items: center; }
|
.mobile-dialog-close text { color: #AAB2BF; font-size: 43rpx; line-height: 48rpx; font-weight: 300; }
|
.mobile-dialog-title { color: #212633; font-size: 36rpx; line-height: 50rpx; font-weight: 700; }
|
.mobile-dialog-desc { margin-top: 14rpx; color: #A9AFBA; font-size: 23rpx; line-height: 34rpx; }
|
.mobile-input-box { display: flex; width: 100%; height: 86rpx; margin-top: 28rpx; box-sizing: border-box; padding: 0 24rpx; border-width: 2rpx; border-style: solid; border-color: #E8EBEF; border-radius: 13rpx; background-color: #F8F9FB; align-items: center; }
|
.mobile-input-box input { width: 100%; height: 82rpx; color: #30343A; font-size: 30rpx; }
|
.mobile-placeholder { color: #B3B8C0; font-size: 27rpx; }
|
.mobile-error { align-self: flex-start; margin-top: 9rpx; color: #F05C3A; font-size: 22rpx; }
|
.mobile-submit { display: flex; width: 100%; height: 76rpx; margin-top: 25rpx; border-radius: 39rpx; background-image: linear-gradient(90deg, #FF4434 0%, #FF8C21 100%); justify-content: center; align-items: center; }
|
.mobile-submit text { color: #FFFFFF; font-size: 28rpx; font-weight: 600; }
|
</style>
|