From f0911c67a009c35acb379dbfbf7b333e6ef3f7e5 Mon Sep 17 00:00:00 2001 From: lcj <17763797832@163.com> Date: Fri, 7 Aug 2026 10:45:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8A=96=E9=9F=B3=E6=A0=B8=E9=94=80?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E5=B0=8F=E6=B3=A5=E4=BA=BAAPI=E3=80=81?= =?UTF-8?q?=E5=85=AC=E5=91=8A=E8=AF=A6=E6=83=85=E9=A1=B5=E3=80=81=E6=99=AF?= =?UTF-8?q?=E5=8C=BA=E9=A2=84=E7=BA=A6=E4=BA=BA=E9=80=89=E4=BA=BA=E7=AD=89?= =?UTF-8?q?=E5=A4=9A=E5=A4=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 抖音核销(douyin-verify): - 对接小泥人 OAuth2 token 与 voucher-list 券码接口,按 code 分组展示订单券号及可激活次数 - 支持手动输入券码验证券码;核销流程改为先调后端 sendAndBind 发卡绑定,再验证券码 - 购卡须知改为富文本渲染,新增无可核销订单提示弹窗、客服电话拨打 - 增加 product_id 过滤与 per-page=100,验证券码命中后仅展示不弹提示 公告模块: - 首页/公告列表点击跳转到新增公告详情页(notice-detail),展示标题、发布时间、富文本内容及视频 - 公告列表卡片改为标题+发布时间+查看详情按钮,时间与按钮同排 - 富文本支持内嵌 video 解析播放;content 为空不显示分隔线;标题取公告 title 而非类型 首页与价格: - 首页大卡价格/划线价/立省改为商品详情接口动态获取 - 热门景区列表扩展至8条,支持优惠/折扣标签与默认占位图 预约/景区: - 预约页改为选择预约人(可选/已预约置灰),预约参数改用预约人信息 - 景区列表与详情支持优惠类型、折扣、特惠价展示,富文本图片防溢出 - 景区列表移除自定义导航改用原生导航 订单/绑卡: - 订单列表/详情增加抖音核销单号(thirdOrderNo)展示,核销订单隐藏金额与退款入口 - 绑卡页移除人脸可选开关,照片必传改为拍照 - 其他:图片域名统一为 hn12301,tabBar'旅游卡'改名,登录页支持 redirect 回跳 --- src/mock/images.ts | 6 +- src/packages/content/pages/notice-detail.vue | 151 ++++++ src/packages/content/pages/notice-list.vue | 90 ++-- src/packages/content/pages/scenic-detail.vue | 33 +- src/packages/content/pages/scenic-list.vue | 135 +---- src/packages/user/pages/bind.vue | 27 +- src/packages/user/pages/buy.vue | 135 ++++- src/packages/user/pages/douyin-verify.vue | 489 ++++++++++++++----- src/packages/user/pages/order/detail.vue | 19 +- src/packages/user/pages/order/list.vue | 36 +- src/packages/user/pages/reserve/index.vue | 227 +++++++-- src/packages/user/pages/reserve/list.vue | 22 +- src/packages/user/pages/reserve/success.vue | 8 +- src/pages.json | 11 +- src/pages/index/index.vue | 80 +-- src/pages/login/login.vue | 14 +- src/pages/profile/index.vue | 2 + src/pages/qrcode/index.vue | 12 +- 18 files changed, 1076 insertions(+), 421 deletions(-) create mode 100644 src/packages/content/pages/notice-detail.vue diff --git a/src/mock/images.ts b/src/mock/images.ts index e79a77b..43139f1 100644 --- a/src/mock/images.ts +++ b/src/mock/images.ts @@ -4,11 +4,11 @@ */ // 首页 Banner -export const IMG_HOME_BANNER = 'https://aliyunoss.hntgov.net/image/2026/04/14/d2bf03167e484ba59f7c2d62879ad07f.jpg' +export const IMG_HOME_BANNER = 'https://aliyunoss.hn12301.net/image/2026/04/14/d2bf03167e484ba59f7c2d62879ad07f.jpg' // 年卡购买页图片 -export const IMG_CARD_BUY_1 = 'https://aliyunoss.hntgov.net/image/2026/06/23/70e9f4b3b5fd49adb1ff06edcb8fa032.jpg' -export const IMG_CARD_BUY_2 = 'https://aliyunoss.hntgov.net/image/2026/06/25/f3e45bcb3b4f4a2997f107cc6335a1bc.jpg' +export const IMG_CARD_BUY_1 = 'https://aliyunoss.hn12301.net/image/2026/06/23/70e9f4b3b5fd49adb1ff06edcb8fa032.jpg' +export const IMG_CARD_BUY_2 = 'https://aliyunoss.hn12301.net/image/2026/06/25/f3e45bcb3b4f4a2997f107cc6335a1bc.jpg' // 入园码页面 export const IMG_QRCODE_LOGO = 'https://hn12301.oss-cn-shenzhen.aliyuncs.com/hn12301/%E5%88%9D%E5%BF%83%E6%BA%90%20%E6%B9%98%E9%84%82%E8%B5%A3%E6%96%87%E6%97%85%E4%B8%80%E5%8D%A1%E9%80%9A_1777447994254.png' diff --git a/src/packages/content/pages/notice-detail.vue b/src/packages/content/pages/notice-detail.vue new file mode 100644 index 0000000..bd22e3d --- /dev/null +++ b/src/packages/content/pages/notice-detail.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/src/packages/content/pages/notice-list.vue b/src/packages/content/pages/notice-list.vue index 6ca31ee..4442d4e 100644 --- a/src/packages/content/pages/notice-list.vue +++ b/src/packages/content/pages/notice-list.vue @@ -8,25 +8,17 @@ :style="{ animationDelay: index * 60 + 'ms' }" @click="openDetail(item)" > - - - - {{ item.title }} - {{ item.content }} + {{ item.title }} + + 发布时间:{{ item.date }} + + 查看详情 + - {{ item.date }} - - - - @@ -34,7 +26,6 @@ @@ -144,63 +136,55 @@ function openDetail(item: NoticeItem) { } } -/* ====== 卡片内容行 ====== */ -.card-header { - display: flex; - align-items: center; -} - -/* 左侧文字区(标题 + 摘要) */ -.header-text { - flex: 1; - min-width: 0; - margin-right: 16rpx; -} - /* 标题 */ .card-title { display: block; font-size: $font-size-base; font-weight: $font-weight-bold; color: $uv-main-color; - line-height: 1.3; + line-height: 1.4; letter-spacing: -0.3rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - margin-bottom: 8rpx; } -/* 摘要 */ -.card-summary { - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - font-size: $font-size-sm; - font-weight: $font-weight-normal; - color: $uv-tips-color; - line-height: 1.6; +/* 发布行:时间 + 查看详情按钮在一排 */ +.card-footer { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 20rpx; } -/* 日期 */ +/* 发布时间 */ .card-date { font-size: 22rpx; font-weight: $font-weight-normal; color: $uv-placeholder-color; - flex-shrink: 0; letter-spacing: 0.5rpx; } +.card-action-row { + display: flex; + align-items: center; +} + +.card-action { + font-size: $font-size-sm; + font-weight: $font-weight-medium; + color: $uv-primary; +} + /* 右箭头 */ .card-arrow { width: 14rpx; height: 14rpx; - border-right: 3rpx solid #dadbde; - border-bottom: 3rpx solid #dadbde; + border-right: 3rpx solid $uv-primary; + border-bottom: 3rpx solid $uv-primary; transform: rotate(-45deg); flex-shrink: 0; - margin-left: 16rpx; + margin-left: 12rpx; } /* ====== 底部安全区 ====== */ diff --git a/src/packages/content/pages/scenic-detail.vue b/src/packages/content/pages/scenic-detail.vue index a8d74b2..aebfe86 100644 --- a/src/packages/content/pages/scenic-detail.vue +++ b/src/packages/content/pages/scenic-detail.vue @@ -95,7 +95,9 @@ - {{ card.remainingCount > 0 ? '全年剩余' + card.remainingCount + '次' : '全年可用' + card.freeCount + '次' }} + + + {{ card.bookingDeadline }} @@ -129,10 +131,10 @@ - + - + @@ -145,7 +147,7 @@ {{ storeNotice.title }} - + @@ -166,7 +168,7 @@ import { onLoad, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app' import { post, getToken } from '../../../api/request' interface NoticeItem { title: string; content: string } -interface CardBenefit { type: string; cardName: string; skuName: string; remainingCount: number; freeCount: number; bookingDeadline: string; cardModelId: string; resourceId: string; goodsId: string } +interface CardBenefit { type: string; cardName: string; skuName: string; remainingCount: number; freeCount: number; bookingDeadline: string; cardModelId: string; resourceId: string; goodsId: string; preferential: string; discountPercentage: number; discountAmount: number } interface ScenicDetail { id: number; name: string; price: number; freeCount: number; level: string hours: string; needReservation: string; bookingDeadline: string @@ -176,6 +178,23 @@ interface ScenicDetail { } const scenic = ref({ tags: [], images: [], cards: [], bookingNotice: [] } as unknown as ScenicDetail) + +/** 富文本 HTML 清洗:给所有 img 加 max-width:100%,防止超出容器边界 */ +function fixRichHtml(html: string): string { + if (!html) return '' + const style = 'max-width:100%;height:auto;display:block;' + return html.replace(/]*max-width)[^>]*>/gi, (tag: string) => { + if (/style="[^"]*"/i.test(tag)) { + return tag.replace(/style="([^"]*)"/i, (_: string, s: string) => `style="${s};${style}"`) + } + return tag.replace(/ fixRichHtml(scenic.value.introduction)) +const bookingNoticeHtml = computed(() => fixRichHtml(scenic.value.bookingNoticeHtml)) +const storeNoticeHtml = computed(() => fixRichHtml(storeNotice.value.content)) + const activeTab = ref<'notice' | 'intro'>('notice') const currentSlide = ref(0) const loading = ref(true) @@ -303,7 +322,7 @@ async function onBookClick(card: CardBenefit) { if (res?.hasValidCard) { uni.navigateTo({ - url: `/packages/user/pages/reserve/index?cardNumber=${res.cardNumber}&resourceId=${res.resourceId}&cardModelId=${card.cardModelId}`, + url: `/packages/user/pages/reserve/index?resourceId=${res.resourceId || card.resourceId}&cardModelId=${card.cardModelId}`, }) } else { if (String(card.cardModelId) === '820093340659013') { @@ -716,7 +735,7 @@ $icon-crown: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' w margin: 0 $spacing-3; border-radius: 0 0 $radius-lg $radius-lg; box-shadow: $shadow-sm; - padding: $spacing-3; + padding: 24rpx; } .content-section { diff --git a/src/packages/content/pages/scenic-list.vue b/src/packages/content/pages/scenic-list.vue index 04a7bb4..63b06fe 100644 --- a/src/packages/content/pages/scenic-list.vue +++ b/src/packages/content/pages/scenic-list.vue @@ -1,20 +1,7 @@