shinnosuke
5 天以前 e52934f6527027bd6008c2ade61c3083159efd4a
rencaika/pages/benefits/benefits.uvue
@@ -43,7 +43,7 @@
               <image class="merchant-image" :src="item.image" mode="aspectFill" @error="replaceImage(item)"></image>
               <view class="benefit-info">
                  <text class="benefit-name">{{item.name}}</text>
                  <view class="tag-row"><text class="coupon-tag">券</text><text class="discount-tag">{{item.discount}}</text></view>
                  <view v-if="item.tags != null && item.tags.length > 0" class="tag-row"><text v-for="tag in item.tags" :key="tag" :class="tag == '券' ? 'coupon-tag' : 'discount-tag'">{{tag}}</text></view>
                  <view class="address-row"><image src="/static/benefits-assets/map-pin.svg"></image><text>{{item.address}}</text></view>
               </view>
            </view>
@@ -68,14 +68,17 @@
   import { isApiConfigured } from '../../config/api.uts'
   import { getMerchants } from '../../services/portal.uts'
   import { resolveApiUrl } from '../../services/http.uts'
   import { resolveTalentId } from '../../utils/talent-id.uts'
   import { openMerchantDetail } from '../../utils/merchant-navigation.uts'
   const navTop = ref(28)
   const navHeight = ref(32)
   const navWidth = ref(88)
   const navRight = ref(10)
   const isSolidNav = ref(false)
   const fallbackImage = '/static/common/image-fallback.svg'
   const replaceImage = (item: any) => { if (item.image != fallbackImage) item.image = fallbackImage }
   const fallbackImage = ''
   const talentId = ref('')
   const replaceImage = (item: any) => { if (item.image != '') item.image = '' }
   onLoad((options: any) => {
      // #ifdef MP-WEIXIN
@@ -91,6 +94,7 @@
         failInitialOnce.value = previewState == 'initialError'
         failLoadMoreOnce.value = previewState == 'loadMoreError'
      }
      talentId.value = resolveTalentId()
      loadInitialBenefits()
   })
@@ -106,21 +110,21 @@
   ]
   const allBenefits = [
      { id: 1, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/food-assets/food-1.jpg' },
      { id: 2, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/food-assets/food-2.jpg' },
      { id: 3, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/food-assets/food-1.jpg' },
      { id: 4, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/food-assets/food-2.jpg' },
      { id: 5, name: '百杏厨房(中环天地店)', discount: '8.8折', address: '东区炳三区新福路20号中环天地负一层', image: '/static/food-assets/food-1.jpg' },
      { id: 6, name: '香佰里鲜货火锅(万象城店)', discount: '8.8折', address: '东区攀枝花大道东段298号', image: '/static/food-assets/food-2.jpg' },
      { id: 7, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/food-assets/food-1.jpg' },
      { id: 8, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/food-assets/food-2.jpg' },
      { id: 9, name: '百杏厨房(中环天地店)', discount: '8.8折', address: '东区炳三区新福路20号中环天地负一层', image: '/static/food-assets/food-1.jpg' },
      { id: 10, name: '香佰里鲜货火锅(万象城店)', discount: '8.8折', address: '东区攀枝花大道东段298号', image: '/static/food-assets/food-2.jpg' },
      { id: 11, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/food-assets/food-1.jpg' },
      { id: 12, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/food-assets/food-2.jpg' }
      { id: 1, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/common/image-placeholder.png' },
      { id: 2, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/common/image-placeholder.png' },
      { id: 3, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/common/image-placeholder.png' },
      { id: 4, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/common/image-placeholder.png' },
      { id: 5, name: '百杏厨房(中环天地店)', discount: '8.8折', address: '东区炳三区新福路20号中环天地负一层', image: '/static/common/image-placeholder.png' },
      { id: 6, name: '香佰里鲜货火锅(万象城店)', discount: '8.8折', address: '东区攀枝花大道东段298号', image: '/static/common/image-placeholder.png' },
      { id: 7, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/common/image-placeholder.png' },
      { id: 8, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/common/image-placeholder.png' },
      { id: 9, name: '百杏厨房(中环天地店)', discount: '8.8折', address: '东区炳三区新福路20号中环天地负一层', image: '/static/common/image-placeholder.png' },
      { id: 10, name: '香佰里鲜货火锅(万象城店)', discount: '8.8折', address: '东区攀枝花大道东段298号', image: '/static/common/image-placeholder.png' },
      { id: 11, name: '乡菜郎·攀枝花特色延边菜', discount: '6折', address: '西区格里坪镇清香坪东街78号', image: '/static/common/image-placeholder.png' },
      { id: 12, name: '金府酒楼(西区店)', discount: '6折', address: '西区清香坪北街51号', image: '/static/common/image-placeholder.png' }
   ]
   const visibleBenefits = ref([allBenefits[0], allBenefits[1], allBenefits[2], allBenefits[3]])
   const loadedBenefitCount = ref(4)
   const visibleBenefits = ref<any[]>([])
   const loadedBenefitCount = ref(0)
   const currentPage = ref(0)
   const initialLoading = ref(true)
   const loadingMore = ref(false)
@@ -130,23 +134,35 @@
   const loadMoreError = ref(false)
   const failInitialOnce = ref(false)
   const failLoadMoreOnce = ref(false)
   const formatDiscount = (item: any): string => {
      const sale = item.salePrice != null ? Number(item.salePrice) : 0
      const original = item.originalPrice != null ? Number(item.originalPrice) : 0
      if (sale > 0 && original > 0 && sale < original) return '' + Math.round(sale / original * 100) / 10 + '折'
      return '人才专享'
   }
   const mapMerchants = (records: any[]): any[] => {
      const mapped: any[] = []
      for (let index = 0; index < records.length; index++) {
         const item: any = records[index]
         const rawType = item.merchantType != null ? item.merchantType as string : 'food'
         const merchantType = rawType == '餐饮服务' ? 'food' : rawType
         const hasCoupon = item.couponAvailable === true || Number(item.couponAvailable) == 1
         const discount = item.discountText != null ? item.discountText as string : ''
         const hasConfiguredTags = item.benefitTags instanceof Array
         const configuredTags: any[] = hasConfiguredTags ? item.benefitTags as any[] : []
         const tags: string[] = []
         for (let tagIndex = 0; tagIndex < configuredTags.length; tagIndex++) {
            const tag = String(configuredTags[tagIndex]).trim()
            if (tag != '' && tags.indexOf(tag) < 0) tags.push(tag)
         }
         if (!hasConfiguredTags) {
            if (hasCoupon) tags.push('券')
            if (discount != '' && discount != '券') tags.push(discount)
         }
         mapped.push({
            id: '' + item.id,
            name: item.merchantName != null ? item.merchantName as string : '人才权益商户',
            merchantType: merchantType,
            discount: formatDiscount(item),
            detailType: item.detailType != null ? item.detailType as string : 'MERCHANT',
            detailBusinessId: item.detailBusinessId != null ? '' + item.detailBusinessId : '' + item.id,
            targetAction: item.targetAction != null ? item.targetAction as string : 'MERCHANT',
            hasCoupon: hasCoupon,
            discount: discount,
            tags: tags,
            address: item.address != null ? item.address as string : '',
            image: item.coverUrl != null && item.coverUrl != '' ? resolveApiUrl(item.coverUrl as string) : fallbackImage
         })
@@ -161,7 +177,7 @@
      hasLoaded.value = false
      currentPage.value = 0
      if (isApiConfigured()) {
         getMerchants(1, 4, '', (data: any) => {
         getMerchants(1, 4, '', talentId.value, (data: any) => {
            const records: any[] = data != null && data.records instanceof Array ? data.records as any[] : []
            visibleBenefits.value = mapMerchants(records)
            loadedBenefitCount.value = records.length
@@ -229,19 +245,13 @@
      }
      uni.showToast({ title: '已选择' + name, icon: 'none' })
   }
   const openMerchant = (item: any) => uni.navigateTo({
      url: '/pages/merchant/merchant?merchantType=' + encodeURIComponent(item.merchantType != null ? item.merchantType : 'food') + '&merchantId=' + encodeURIComponent(item.id)
         + '&name=' + encodeURIComponent(item.name)
         + '&image=' + encodeURIComponent(item.image)
         + '&address=' + encodeURIComponent(item.address)
         + '&discount=' + encodeURIComponent(item.discount)
   })
   const openMerchant = (item: any) => openMerchantDetail(item)
   const loadMoreBenefits = () => {
      if (initialLoading.value || loadingMore.value || !hasMoreBenefits.value) return
      loadMoreError.value = false
      loadingMore.value = true
      if (isApiConfigured()) {
         getMerchants(currentPage.value + 1, 4, '', (data: any) => {
         getMerchants(currentPage.value + 1, 4, '', talentId.value, (data: any) => {
            const records: any[] = data != null && data.records instanceof Array ? data.records as any[] : []
            const next = visibleBenefits.value.slice()
            const mapped = mapMerchants(records)
@@ -319,8 +329,9 @@
   .benefit-info { height: 184rpx; flex: 1; min-width: 0; box-sizing: border-box; padding: 8rpx 0 7rpx 26rpx; justify-content: space-between; }
   .benefit-name { color: #292929; font-size: 29rpx; line-height: 40rpx; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
   .tag-row { flex-direction: row; align-items: center; }
   .tag-row text { margin-right: 11rpx; }
   .coupon-tag { padding: 6rpx 8rpx; border-radius: 6rpx; background-color: #FFF0EC; color: #FF5D37; font-size: 21rpx; }
   .discount-tag { margin-left: 11rpx; padding: 6rpx 9rpx; border-radius: 6rpx; background-color: #FFF5E7; color: #FF7C2B; font-size: 21rpx; }
   .discount-tag { padding: 6rpx 9rpx; border-radius: 6rpx; background-color: #FFF5E7; color: #FF7C2B; font-size: 21rpx; }
   .address-row { display: flex; min-width: 0; box-sizing: border-box; padding: 7rpx 10rpx; border-radius: 7rpx; background-image: linear-gradient(90deg, rgba(239,240,242,.98) 0%, rgba(242,243,245,.76) 58%, rgba(255,255,255,0) 100%); flex-direction: row; align-items: center; }
   .address-row image { width: 27rpx; height: 27rpx; margin-right: 9rpx; flex-shrink: 0; }
   .address-row text { flex: 1; color: #7E8490; font-size: 21rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }