| | |
| | | <template> |
| | | <view class="page"> |
| | | <view class="custom-nav" :class="isSolidNav ? 'is-solid' : ''"><view class="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" mode="aspectFit"></image></view><text class="nav-title">{{cinemaName}}</text><view class="capsule-space" :style="'width:' + navWidth + 'px'"></view></view></view> |
| | | <scroll-view class="content" scroll-y @scroll="handleScroll"> |
| | | <scroll-view :show-scrollbar="false" class="content" scroll-y @scroll="handleScroll"> |
| | | <view class="hero"><image class="hero-image" :src="cinemaHero" mode="aspectFill" @error="replaceHeroImage"></image><view class="hero-shade"></view></view> |
| | | <view class="merchant-shell"> |
| | | <view v-if="detailLoading" class="detail-state"><view class="loading-spinner"></view><text>正在加载影城信息</text></view> |
| | | <view v-else-if="detailError" class="detail-state error-state"><text>影城信息加载失败</text><text class="retry-text" @tap="loadCinema">重新加载</text></view> |
| | | <view v-else class="merchant-detail"> |
| | | <view class="merchant-info"><view class="title-row"><text class="merchant-name">{{cinemaName}}</text><view class="coupon-badge"><text>券</text></view></view><view class="service-tag"><text>{{talentCardTag}}</text></view><view class="address-row"><image class="address-icon" src="/static/benefits-assets/map-pin.svg" mode="aspectFit"></image><text class="address-text">{{cinemaAddress}}</text><view class="merchant-actions"><view class="action-button" @tap="openMap"><image src="/static/merchant-assets/navigation.svg" mode="aspectFit"></image></view><view v-if="cinemaMobile != ''" class="action-button" @tap="callCinema"><image src="/static/merchant-assets/phone.svg" mode="aspectFit"></image></view></view></view></view> |
| | | <view class="merchant-info"><view class="title-row"><text class="merchant-name">{{cinemaName}}</text><view class="coupon-badge"><text>券</text></view></view><view v-if="talentCardTag != ''" class="service-tag"><text>{{talentCardTag}}</text></view><view class="address-row"><image class="address-icon" src="/static/benefits-assets/map-pin.svg" mode="aspectFit"></image><text class="address-text">{{cinemaAddress}}</text><view class="merchant-actions"><view class="action-button" @tap="openMap"><image src="/static/merchant-assets/navigation.svg" mode="aspectFit"></image></view><view v-if="cinemaMobile != ''" class="action-button" @tap="callCinema"><image src="/static/merchant-assets/phone.svg" mode="aspectFit"></image></view></view></view></view> |
| | | <view class="tabs"><view class="tab-item" :class="currentTab == 'purchase' ? 'active' : ''" @tap="changeTab('purchase')"><text>消费购买</text><view></view></view><view class="tab-item" :class="currentTab == 'rights' ? 'active' : ''" @tap="changeTab('rights')"><text>权益详情</text><view></view></view></view> |
| | | <view v-if="currentTab == 'purchase'" class="coupon-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="loadCoupons">重新加载</text></view><view v-else-if="listLoaded && coupons.length == 0" class="list-state"><text>暂无可领取电影券</text></view><view class="coupon-item" v-for="item in coupons" :key="item.id"><image class="coupon-image" :src="item.image" mode="aspectFill" @error="replaceCouponImage(item)"></image><view class="coupon-info"><text class="coupon-name">{{item.name}}</text><view class="stock-row"><text>剩余可领</text><text>{{item.remainingCount}}</text><text>张</text></view><view class="coupon-bottom"><view class="coupon-price"><text>¥</text><text>{{item.price}}</text></view><view class="claim-button" :class="item.claimed ? 'claimed' : (item.soldOut ? 'sold-out' : '')" @tap="requestClaimCoupon(item)"><text>{{item.buttonText}}</text></view></view></view></view></view> |
| | | <view v-else class="rights-panel"><text class="rights-description">{{rightsDescription}}</text></view> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="uts"> |
| | | import { apiEnvironment, isApiConfigured } from '../../config/api.uts' |
| | | import { isApiConfigured } from '../../config/api.uts' |
| | | import { getCinemaMerchant, getTalentCardProfile, getTicketPackages, claimTicketPackage } from '../../services/portal.uts' |
| | | import { resolveApiUrl } from '../../services/http.uts' |
| | | import { getSession } from '../../services/session.uts' |
| | | import { resolveTalentId } from '../../utils/talent-id.uts' |
| | | import { safeBack } from '../../utils/navigation.uts' |
| | | |
| | | const fallbackImage = '' |
| | | const navTop = ref(28); const navHeight = ref(32); const navWidth = ref(88); const navRight = ref(10) |
| | | const isSolidNav = ref(false); const currentTab = ref('purchase'); const merchantId = ref(''); const talentId = ref(''); const cardId = ref('') |
| | | const cinemaName = ref('影城服务'); const cinemaAddress = ref(''); const cinemaHero = ref(fallbackImage); const cinemaMobile = ref(''); const cinemaLatitude = ref(0); const cinemaLongitude = ref(0) |
| | | const talentCardTag = ref('人才卡专享'); const rightsTitle = ref('人才观影专属权益'); const rightsDescription = ref('') |
| | | const talentCardTag = ref(''); const rightsTitle = ref('人才观影专属权益'); const rightsDescription = ref('') |
| | | const detailLoading = ref(true); const detailError = ref(false); const quotaRemaining = ref(0); const coupons = ref<any[]>([]); const listLoading = ref(false); const listLoaded = ref(false); const listError = ref(false) |
| | | const showClaimDialog = ref(false); const isSubmitting = ref(false); const pendingCouponId = ref(''); const pendingCouponStock = ref(0) |
| | | |
| | |
| | | // #endif |
| | | if (options != null && options['merchantId'] != null) merchantId.value = options['merchantId'] as string |
| | | if (options != null && options['name'] != null) cinemaName.value = decodeURIComponent(options['name'] as string) |
| | | const session = getSession(); if (session != null && session.talentId != null) talentId.value = session.talentId as string |
| | | if (talentId.value == '' && apiEnvironment == 'development') talentId.value = '2' |
| | | talentId.value = resolveTalentId() |
| | | if (talentId.value != '') { |
| | | getTalentCardProfile(talentId.value, (data: any) => { |
| | | const card = data != null ? data.card : null |
| | |
| | | cinemaHero.value = data.heroImage != null && data.heroImage != '' ? resolveApiUrl(data.heroImage as string) : fallbackImage |
| | | cinemaMobile.value = data.mobile != null ? data.mobile as string : '' |
| | | cinemaLatitude.value = data.latitude != null ? Number(data.latitude) : 0; cinemaLongitude.value = data.longitude != null ? Number(data.longitude) : 0 |
| | | talentCardTag.value = data.talentCardTag != null ? data.talentCardTag as string : talentCardTag.value; rightsTitle.value = data.rightsTitle != null ? data.rightsTitle as string : rightsTitle.value; rightsDescription.value = data.rightsDescription != null ? data.rightsDescription as string : '以商户说明为准' |
| | | talentCardTag.value = data.talentCardTag != null ? String(data.talentCardTag) : '' |
| | | rightsTitle.value = data.rightsTitle != null ? data.rightsTitle as string : rightsTitle.value |
| | | rightsDescription.value = data.rightsDescription != null ? data.rightsDescription as string : '以商户说明为准' |
| | | loadCoupons(); loadQuota() |
| | | }, () => { detailLoading.value = false; detailError.value = true }) |
| | | } |