diff --git a/src/api/order.ts b/src/api/order.ts deleted file mode 100644 index cda5d76..0000000 --- a/src/api/order.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { post } from './request' -import { BASE_URL } from '../config' -import type { CreateOrderParams, CreateOrderResult, PrepayParams, PrepayResult } from './types' - -export function createOrder(params: CreateOrderParams) { - return post(`${BASE_URL}/open-api/pingXiang/createOrder`, params) -} - -export function prepay(params: PrepayParams) { - return post(`${BASE_URL}/open-api/pingXiang/prepay`, params) -} diff --git a/src/packages/content/pages/scenic-detail.vue b/src/packages/content/pages/scenic-detail.vue index ab58a58..e3687a5 100644 --- a/src/packages/content/pages/scenic-detail.vue +++ b/src/packages/content/pages/scenic-detail.vue @@ -193,7 +193,25 @@ function fixRichHtml(html: string): string { const introductionHtml = computed(() => fixRichHtml(scenic.value.introduction)) const bookingNoticeHtml = computed(() => fixRichHtml(scenic.value.bookingNoticeHtml)) -const storeNoticeHtml = computed(() => fixRichHtml(storeNotice.value.content)) + +/** 富文本标签特征(管理端公告内容为 textarea 纯文本,含标签才视为 HTML) */ +// xuchao: 判断公告正文是否为编辑器产出的 HTML +const HTML_TAG_RE = /<(?:p|br|div|span|strong|em|i|b|u|h[1-6]|img|ul|ol|li|a|table|tr|td|video|section)[^>]*>/i + +// xuchao: 纯文本转 rich-text 可渲染的 HTML:转义特殊字符 + 换行转
,保留后台录入的段落格式 +function plainTextToHtml(text: string): string { + return text + .replace(/&(?!(?:#\d+|#x[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);)/g, '&') + .replace(//g, '>') + .replace(/\n/g, '
') +} + +const storeNoticeHtml = computed(() => { + const content = storeNotice.value.content + if (!content) return '' + return HTML_TAG_RE.test(content) ? fixRichHtml(content) : plainTextToHtml(content) +}) const activeTab = ref<'notice' | 'intro'>('notice') const currentSlide = ref(0) @@ -862,13 +880,14 @@ $icon-crown: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' w text-align: center; } +/* xuchao: 正文区固定 45vh 高度——微信要求 scroll-view 有确定高度才能竖向滚动;flex-shrink:0 防止被弹窗整体高度压缩 */ .notice-popup-body { + height: 45vh; + flex-shrink: 0; padding: $spacing-3 $spacing-5 $spacing-3; font-size: $font-size-sm; color: $uv-tips-color; line-height: 1.9; - max-height: 45vh; - overflow-y: auto; } .notice-popup-footer { diff --git a/src/packages/user/api/pingxiang-order.ts b/src/packages/user/api/pingxiang-order.ts new file mode 100644 index 0000000..fc6108a --- /dev/null +++ b/src/packages/user/api/pingxiang-order.ts @@ -0,0 +1,13 @@ +// xuchao: 萍乡超级玩家卡下单/预支付接口(open-api 渠道)。原为主包 api/order.ts, +// 因仅被本分包页面引用导致主包整包扫描告警,迁入分包;与本地 order.ts(/order/* 旧接口)不是同一组接口,勿混用。 +import { post } from '../../../api/request' +import { BASE_URL } from '../../../config' +import type { CreateOrderParams, CreateOrderResult, PrepayParams, PrepayResult } from '../../../api/types' + +export function createOrder(params: CreateOrderParams) { + return post(`${BASE_URL}/open-api/pingXiang/createOrder`, params) +} + +export function prepay(params: PrepayParams) { + return post(`${BASE_URL}/open-api/pingXiang/prepay`, params) +} diff --git a/src/packages/user/pages/buy.vue b/src/packages/user/pages/buy.vue index 44f6042..e56f2bf 100644 --- a/src/packages/user/pages/buy.vue +++ b/src/packages/user/pages/buy.vue @@ -50,7 +50,7 @@ import { onLoad, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app' import { post, getToken } from '../../../api/request' import { BASE_URL } from '../../../config' import { useUserStore } from '../../../store/user' -import { createOrder, prepay } from '../../../api/order' +import { createOrder, prepay } from '../api/pingxiang-order' import type { BannerItem } from '../../../api/types' const userStore = useUserStore() diff --git a/src/packages/user/pages/reserve/index.vue b/src/packages/user/pages/reserve/index.vue index cfbd5f5..a74b16c 100644 --- a/src/packages/user/pages/reserve/index.vue +++ b/src/packages/user/pages/reserve/index.vue @@ -32,7 +32,7 @@ > {{ d.week }} {{ d.label }} - 不可约 + {{ d.expired ? '已过预约时间' : '不可约' }} 无限库存 可预约 余{{ d.stock }}位 @@ -155,6 +155,8 @@ interface DateOption { cards: CardOption[] disabled?: boolean reason?: string + // xuchao: 已过预约截止时间(后端置灰补显的日期,不可点) + expired?: boolean } const scenic = ref({ name: '', address: '', hours: '', image: '' }) @@ -269,7 +271,8 @@ onLoad(async (query: any) => { userIdCard.value = res.userIdCard || '' bookingNotice.value = Array.isArray(res.bookingNotice) ? res.bookingNotice.map((n: any) => (typeof n === 'string' ? n : n?.content || n?.text || '')).join('
') : (res.bookingNotice || '') cardModelName.value = res.cardModelName || '' - appointmentDays.value = (res.dates || []).length + // xuchao: 近N日提示不含过截止置灰补显的日期 + appointmentDays.value = (res.dates || []).filter((d: any) => !d.expired).length reserveParams.value = { scenicId: parseInt(resourceId), channel: 'Channel_SZH', @@ -287,6 +290,7 @@ onLoad(async (query: any) => { cards: d.cards || [], disabled: d.disabled, reason: d.reason, + expired: d.expired, })) const firstAvailable = dateOptions.value.find(d => d.stock == null || d.stock > 0) if (firstAvailable) selectedDate.value = firstAvailable.key diff --git a/src/packages/user/pages/reserve/list.vue b/src/packages/user/pages/reserve/list.vue index e8f7fa4..ee2b6c3 100644 --- a/src/packages/user/pages/reserve/list.vue +++ b/src/packages/user/pages/reserve/list.vue @@ -238,9 +238,6 @@ let countdownTimer: ReturnType | null = null onUnmounted(() => { clearTimer() - // #ifdef MP-WEIXIN - wx.offUserCaptureScreen() - // #endif }) const records = ref([]) @@ -303,15 +300,6 @@ async function fetchRecords(append = false) { } onLoad(() => { - // #ifdef MP-WEIXIN - wx.setVisualEffectOnCapture({ visualEffect: 'hidden' }) - wx.onUserCaptureScreen(() => { - uni.showToast({ title: '该页面截图无效,请不要截图', icon: 'none' }) - if (currentRecord.value) { - fetchCode(currentRecord.value) - } - }) - // #endif fetchRecords() }) diff --git a/src/packages/user/pages/reserve/success.vue b/src/packages/user/pages/reserve/success.vue index eb026d9..5b80929 100644 --- a/src/packages/user/pages/reserve/success.vue +++ b/src/packages/user/pages/reserve/success.vue @@ -106,21 +106,9 @@ let countdownTimer: ReturnType | null = null onUnmounted(() => { clearTimer() - // #ifdef MP-WEIXIN - wx.offUserCaptureScreen() - // #endif }) onLoad(async (query: any) => { - // #ifdef MP-WEIXIN - wx.setVisualEffectOnCapture({ visualEffect: 'hidden' }) - wx.onUserCaptureScreen(() => { - uni.showToast({ title: '该页面截图无效,请不要截图', icon: 'none' }) - if (codePopup.value) { - fetchCode() - } - }) - // #endif const appointId = query?.appointId if (!appointId) return const phone = (uni.getStorageSync('phone') as string) || ''