shinnosuke
4 天以前 5ce0d76154bf4c1d70543476cdfad9a30195b0f8
rencaika/pages/cinema-merchant/cinema-merchant.uvue
@@ -1,13 +1,13 @@
<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>
@@ -20,17 +20,17 @@
</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)
@@ -40,8 +40,7 @@
      // #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
@@ -63,7 +62,9 @@
         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 })
   }