diff --git a/.gitignore b/.gitignore index bfeaeff..0bce61e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ unpackage/ node_modules/ .DS_Store .playwright-mcp/ + +# xuchao: 本地 agent 说明文档,不入库(与 CLAUDE.md 均保留在本地) +AGENTS.md diff --git a/App.vue b/App.vue index 2f80017..c79112e 100644 --- a/App.vue +++ b/App.vue @@ -23,4 +23,23 @@ Arial, Helvetica, sans-serif; -webkit-font-smoothing: antialiased; } + + /* xuchao: 修复默认导航栏在微信 WebView 内顶部超宽空白(参加/使用指南、协议等页)—— + uni-app 内置 H5 导航栏高度为 calc(44px + env(safe-area-inset-top)),页面模板带 + viewport-fit=cover 时,部分 Android 微信 WebView 会误报状态栏高度(而 H5 视口本 + 就位于微信原生标题栏下方、并未被遮挡),导致导航栏被垫高。强制回退固定 44px。 + 标准浏览器/ iOS 中该 env 值为 0,此覆盖无副作用 */ + uni-page-head .uni-page-head { + height: 44px !important; + padding-top: 7px !important; + } + uni-page-head .uni-page-head ~ .uni-placeholder { + height: 44px !important; + } + uni-page-head[uni-page-head-type='default'] ~ uni-page-wrapper { + height: calc(100% - 44px) !important; + } + .uni-app--showtabbar uni-page-head[uni-page-head-type='default'] ~ uni-page-wrapper { + height: calc(100% - 44px) !important; + } diff --git a/common/account.js b/common/account.js new file mode 100644 index 0000000..b394963 --- /dev/null +++ b/common/account.js @@ -0,0 +1,15 @@ +// xuchao: 账号级本地缓存集中管理。权益页首屏会读这些缓存做兜底展示, +// 换账号/退出时漏清就会把上一个账号的中奖状态、卡号、到期时间当成当前账号的数据展示。 +const ACCOUNT_KEYS = ['token', 'phone', 'isAuth', 'hasWin', 'cardNumber', 'expiresTime', + 'rightsCount', 'totalValueFen', 'authFlowStarted', 'authName', 'authIdNo'] + +export default { + // 清空当前账号的本地会话与权益缓存(定位 lng/lat 属于设备信息,不在此列) + clearAccountCache() { + ACCOUNT_KEYS.forEach(key => uni.removeStorageSync(key)) + }, + // 账号标识(手机号) + setAccountPhone(phone) { + uni.setStorageSync('phone', phone) + } +} diff --git a/common/config.js b/common/config.js new file mode 100644 index 0000000..cbe0328 --- /dev/null +++ b/common/config.js @@ -0,0 +1,12 @@ +// xuchao: 全站集中配置项 —— 后端基址/客服电话等只在这里维护一处 +const config = { + // 后端 API 基址。当前指向 UAT 测试环境(见 AGENTS.md 部署信息),切生产改这一行即可 + baseUrl: 'https://dscp-uat.hn12301.net', + // 对外统一客服电话,与《用户协议》《隐私协议》公示号码保持一致 + servicePhone: '0731-88912301', + // xuchao: open-api/hhService/login 强制校验固定 password 字段(后端为 H5 开的旁路, + // 前端去掉即登录失败,故集中存放并在此说明;待后端改造 H5 免密登录后删除。 + loginFixedPassword: '1232321' +} + +export default config diff --git a/common/district.js b/common/district.js new file mode 100644 index 0000000..f353d3c --- /dev/null +++ b/common/district.js @@ -0,0 +1,10 @@ +// xuchao: 卡片角标用的区县简称。后端 districtName 返回的是 region.name 行政区划全称 +// (如「芷江侗族自治县」「怀化高新技术产业开发区」),列表缩略图只有 75px,必须缩短显示 +export function shortDistrict(name) { + if (!name) return '' + return name + .replace('高新技术产业开发区', '高新区') + .replace(/(苗族|侗族|瑶族|回族|土家族|各族)*自治县$/, '') + .replace(/(苗族|侗族|瑶族|回族|土家族|各族)*自治州$/, '') + .replace(/([^市])县$/, '$1') +} diff --git a/common/http.api.js b/common/http.api.js index 1d02815..fd4fe31 100644 --- a/common/http.api.js +++ b/common/http.api.js @@ -1,87 +1,89 @@ -// 如果没有通过拦截器配置域名的话,可以在这里写上完整的URL(加上域名部分) -let LoginUrl = 'open-api/pingXiang/login'; -let SendVerifyCodeUrl = 'open-api/pingXiang/sendLoginVerifyCode'; -let VenueListUrl = 'mp-api/hhrs/venue/list'; -let VenueDetailUrl = 'mp-api/hhrs/venue/detail'; -let MerchantListUrl = 'mp-api/hhrs/merchant/list'; -let MerchantDetailUrl = 'mp-api/hhrs/merchant/detail'; -let RightsInfoUrl = 'mp-api/hhrs/rights/info'; -let RightsDetailUrl = 'mp-api/hhrsRights/detail'; -let RightsAuthUrl = 'mp-api/hhrs/rights/auth'; -let EligibilityUrl = 'mp-api/hhrsRights/eligibility'; -let RightsBookUrl = 'mp-api/hhrs/rights/book'; -let InitFaceVerifyUrl = 'open-api/aliyun/face/initFaceVerify'; -let DescribeFaceVerifyUrl = 'open-api/aliyun/face/describeFaceVerify'; -let RightsListUrl = 'mp-api/hhrsRights/list'; -let AppointmentListUrl = 'mp-api/hhrsRights/appointment/list'; -let CheckListUrl = 'mp-api/hhrsRights/check/list'; -let StoreListUrl = 'mp-api/hhrsStore/list'; -let StoreDetailUrl = 'mp-api/hhrsStore/detail'; -let WinnerDatesUrl = 'mp-api/hhrsWinner/dates'; -let WinnerListUrl = 'mp-api/hhrsWinner/list'; -let AppointUrl = 'zhy-api/cardBag/appoint'; -let TokenDecodeUrl = 'open-api/hhService/tokenDecode'; - +// xuchao: 怀化人社 H5 接口清单,与 docs/hhrs-api-doc.md 一一对应 +// 基址由 common/http.interceptor.js 统一注入(common/config.js.baseUrl) +// 登录 / 云闪付入口 +// xuchao: hhrs 专属登录端点(旧地址 open-api/pingXiang/* 由后端兼容层转发,已弃用) +const LoginUrl = 'open-api/hhService/login' +const SendVerifyCodeUrl = 'open-api/hhService/sendLoginVerifyCode' +const TokenDecodeUrl = 'open-api/hhService/tokenDecode' +// 门店(文旅场馆 typeId=1 / 商户折扣 typeId=2) +const StoreListUrl = 'mp-api/hhrsStore/list' +const StoreDetailUrl = 'mp-api/hhrsStore/detail' +// 权益包 +const RightsListUrl = 'mp-api/hhrsRights/list' +const RightsDetailUrl = 'mp-api/hhrsRights/detail' +const EligibilityUrl = 'mp-api/hhrsRights/eligibility' +const AppointmentListUrl = 'mp-api/hhrsRights/appointment/list' +const CheckListUrl = 'mp-api/hhrsRights/check/list' +// 实名人脸认证(阿里云) +const InitFaceVerifyUrl = 'open-api/aliyun/face/initFaceVerify' +const DescribeFaceVerifyUrl = 'open-api/aliyun/face/describeFaceVerify' +// 中奖公示 +const WinnerDatesUrl = 'mp-api/hhrsWinner/dates' +const WinnerListUrl = 'mp-api/hhrsWinner/list' +// 预约下单(智慧游卡包) +const AppointUrl = 'zhy-api/cardBag/appoint' +// xuchao: 怀化石油汽油券(下单/预支付/最新订单查询,后端 HhVoucherController) +const VoucherCreateUrl = 'open-api/hhService/voucher/create' +const VoucherPrepayUrl = 'open-api/hhService/voucher/prepay' +const VoucherLatestUrl = 'open-api/hhService/voucher/latest' +const VoucherCheckCodeUrl = 'open-api/hhService/voucher/checkCode' // 此处第二个参数vm,就是我们在页面使用的this const install = (Vue, vm) => { - let checkerLogin = (params = {}) => vm.$u.post(LoginUrl, params); - let sendLoginVerifyCode = (params = {}) => vm.$u.post(SendVerifyCodeUrl, params); + // 登录与凭证 + const checkerLogin = (params = {}) => vm.$u.post(LoginUrl, params) + const sendLoginVerifyCode = (params = {}) => vm.$u.post(SendVerifyCodeUrl, params) // xuchao: 云闪付入口 token 解码 - let tokenDecode = (params = {}) => vm.$u.post(TokenDecodeUrl, params); + const tokenDecode = (params = {}) => vm.$u.post(TokenDecodeUrl, params) - // 文旅场馆 - let getVenueList = (params = {}) => vm.$u.get(VenueListUrl, params); - let getVenueDetail = (params = {}) => vm.$u.post(VenueDetailUrl, params); - - // 商户折扣 - let getMerchantList = (params = {}) => vm.$u.get(MerchantListUrl, params); - let getMerchantDetail = (params = {}) => vm.$u.post(MerchantDetailUrl, params); - - // 中奖名单 - let getWinnerDates = (params = {}) => vm.$u.get(WinnerDatesUrl, params); - let getWinnerList = (params = {}) => vm.$u.post(WinnerListUrl, params); - let doAppoint = (params = {}) => vm.$u.post(AppointUrl, params); + // 门店列表/详情 + const getStoreList = (params = {}) => vm.$u.post(StoreListUrl, params) + const getStoreDetail = (params = {}) => vm.$u.post(StoreDetailUrl, params) // 权益包 - let getRightsInfo = (params = {}) => vm.$u.get(RightsInfoUrl, params); - let getRightsDetail = (params = {}) => vm.$u.post(RightsDetailUrl, params); - let doRightsAuth = (params = {}) => vm.$u.post(RightsAuthUrl, params); - let doRightsBook = (params = {}) => vm.$u.post(RightsBookUrl, params); - let getEligibility = (params = {}) => vm.$u.post(EligibilityUrl, params); - let initFaceVerify = (params = {}) => vm.$u.post(InitFaceVerifyUrl, params); - let describeFaceVerify = (params = {}) => vm.$u.post(DescribeFaceVerifyUrl, params); - let getRightsList = (params = {}) => vm.$u.post(RightsListUrl, params); - let getAppointmentList = (params = {}) => vm.$u.post(AppointmentListUrl, params); - let getCheckList = (params = {}) => vm.$u.post(CheckListUrl, params); - let getStoreList = (params = {}) => vm.$u.post(StoreListUrl, params); - let getStoreDetail = (params = {}) => vm.$u.post(StoreDetailUrl, params); + const getRightsList = (params = {}) => vm.$u.post(RightsListUrl, params) + const getRightsDetail = (params = {}) => vm.$u.post(RightsDetailUrl, params) + // xuchao: 注意 identityNo 会触发后端“被动认证”回写,仅在认证流程中传 + const getEligibility = (params = {}) => vm.$u.post(EligibilityUrl, params) + const getAppointmentList = (params = {}) => vm.$u.post(AppointmentListUrl, params) + const getCheckList = (params = {}) => vm.$u.post(CheckListUrl, params) + const doAppoint = (params = {}) => vm.$u.post(AppointUrl, params) + + // 人脸核身 + const initFaceVerify = (params = {}) => vm.$u.post(InitFaceVerifyUrl, params) + const describeFaceVerify = (params = {}) => vm.$u.post(DescribeFaceVerifyUrl, params) + + // 中奖名单 + const getWinnerDates = (params = {}) => vm.$u.get(WinnerDatesUrl, params) + const getWinnerList = (params = {}) => vm.$u.post(WinnerListUrl, params) + + // xuchao: 石油汽油券 + const voucherCreate = (params = {}) => vm.$u.post(VoucherCreateUrl, params) + const voucherPrepay = (params = {}) => vm.$u.post(VoucherPrepayUrl, params) + const voucherLatest = (params = {}) => vm.$u.post(VoucherLatestUrl, params) + const voucherCheckCode = (params = {}) => vm.$u.post(VoucherCheckCodeUrl, params) vm.$u.api = { checkerLogin, sendLoginVerifyCode, tokenDecode, - getVenueList, - getVenueDetail, - getMerchantList, - getMerchantDetail, - getWinnerList, - getRightsInfo, - getRightsDetail, - doRightsAuth, - doRightsBook, - getEligibility, - initFaceVerify, - describeFaceVerify, - getRightsList, - getAppointmentList, - getCheckList, getStoreList, getStoreDetail, + getRightsList, + getRightsDetail, + getEligibility, + getAppointmentList, + getCheckList, + doAppoint, + initFaceVerify, + describeFaceVerify, getWinnerDates, getWinnerList, - doAppoint, - }; + voucherCreate, + voucherPrepay, + voucherLatest, + voucherCheckCode + } } export default { diff --git a/common/http.interceptor.js b/common/http.interceptor.js index 0f824c3..4d8e988 100644 --- a/common/http.interceptor.js +++ b/common/http.interceptor.js @@ -1,8 +1,11 @@ +import config from '@/common/config.js' + // 这里的vm,就是我们在vue文件里面的this,所以我们能在这里获取vuex的变量,比如存放在里面的token // 同时,我们也可以在此使用getApp().globalData,如果你把token放在getApp().globalData的话,也是可以使用的 const install = (Vue, vm) => { Vue.prototype.$u.http.setConfig({ - baseUrl: 'https://dscp-uat.hn12301.net', + // xuchao: 基址统一取 common/config.js,避免多处硬编码 + baseUrl: config.baseUrl, // loadingText: '努力加载中~', // loadingTime: 18800, // 如果将此值设置为true,拦截回调中将会返回服务端返回的所有数据response,而不是response.data @@ -41,10 +44,17 @@ const install = (Vue, vm) => { // 如果把originalData设置为了true,这里return回什么,this.$u.post的then回调中就会得到什么 return res; - }else if(res.errcode==-99){ - uni.navigateTo({ - url:'/pages/index/login' - }) + }else if(res.errcode==-99 || res.errcode==30002){ + // xuchao: 未登录/会话失效(-99 自定义、30002 框架 SESSION_AUTH_FAIL)—— 已在登录页则不再入栈 + const stack = getCurrentPages() || [] + const top = stack.length ? stack[stack.length - 1].route : '' + if (top !== 'pages/index/login') { + uni.navigateTo({ + url:'/pages/index/login' + }) + } + // xuchao: 必须把 res 交回调用方,否则页面 .then(res => res.errcode) 会因 undefined 抛错 + return res }else { // uni.showToast({ diff --git a/common/petrolVoucher.js b/common/petrolVoucher.js new file mode 100644 index 0000000..dc13b84 --- /dev/null +++ b/common/petrolVoucher.js @@ -0,0 +1,66 @@ +// xuchao: 怀化石油汽油减免券——前端常量与工具(全写死,只服务这一个门店,决策 1/10/15) +// 价格真相=后端配置 hh.voucher.price-fen 经 latest 下发;此处 200.00 仅为接口未返回时的展示兜底 + +export const PETROL_SHOP_ID = '851219003520709' +export const VOUCHER_PRICE_TEXT = '200.00' + +export const VOUCHER_NAME = '怀化石油汽油电子券' + +export const VOUCHER_GUIDE_TEXT = '请在「云闪付 App」里的「湖南社保卡」小程序首页进入「怀化社保卡」活动中完成购买' +export const VOUCHER_CANCEL_TEXT = '支付已取消,请重新支付' + +// 券详情页「使用规则 / 使用流程 / 重要须知」文案,来自石油侧材料(决策 14) +export const VOUCHER_USE_RULES = [ + '请加油站收银员以“中石油汽油券”通道扫码核销', + '汽油券单日限用 1 张,多张可叠加使用', + '自购买日起 90 天内有效', + '券一经兑换不可退换' +] +export const VOUCHER_USE_FLOW = [ + '加油后至收银台出示二维码核销', + '支付差额可选:油卡 / 现金等' +] + +// xuchao: 云闪付 SDK 前置预热注入。HBuilderX 的 H5 构建不吃项目根 index.html(静态标签会被丢), +// 只能在 main.js 最早期(document-start、App 挂载前)动态注入,逼近 xghmall 的 head 静态加载时机, +// 让云闪付原生控件桥在首屏就注册,避免到确认订单页才注入导致 upsdk.pay 唤不起。 +// 与 orderConfirm 页的 loadUpSdk 共用同一 script[data-upsdk] 标记,全局只注入一次。 +export function injectUpSdk() { + if (typeof document === 'undefined' || typeof window === 'undefined') return + if (window.upsdk || document.querySelector('script[data-upsdk]')) return + const s = document.createElement('script') + s.src = 'https://open.95516.com/s/open/js/upsdk.js' + s.setAttribute('data-upsdk', '1') + document.head.appendChild(s) +} + + +// xuchao: open-api/hhService/voucher/* 为双层壳:外层 errcode,内层 data.code 才是业务码 +// (同 login.vue 的 isBizOk 判定,提到公共层复用) +export function bizOk(res) { + if (!res || res.errcode !== 0) return false + const d = res.data + if (!d || d.code === undefined || d.code === null) { + return !d || (d.status === undefined && d.error === undefined) + } + return d.code === 200 +} + +export function bizMsg(res) { + return (res && res.data && res.data.msg) || (res && res.errmsg) || '' +} + +export function bizData(res) { + return (res && res.data && res.data.data) || {} +} + +// statusCode 含义与后端 HhVoucherService.toView 对齐:-1无单 0待支付 1发券中 2已发券 3已退款 4退款处理中 5已关闭 +export const VOUCHER_STATUS_TEXT = { + '-1': '', + 0: '待支付', + 1: '发券中', + 2: '有效', + 3: '已退款', + 4: '退款处理中', + 5: '已关闭' +} diff --git a/components/TabBar/TabBar.vue b/components/TabBar/TabBar.vue deleted file mode 100644 index 8dc7d3d..0000000 --- a/components/TabBar/TabBar.vue +++ /dev/null @@ -1,81 +0,0 @@ - - - - - diff --git a/components/hhrs-filter-bar/hhrs-filter-bar.vue b/components/hhrs-filter-bar/hhrs-filter-bar.vue new file mode 100644 index 0000000..d0d6ec9 --- /dev/null +++ b/components/hhrs-filter-bar/hhrs-filter-bar.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/docs/2026-09-29-第一期中奖名单导入记录.md b/docs/2026-09-29-第一期中奖名单导入记录.md new file mode 100644 index 0000000..c111c5d --- /dev/null +++ b/docs/2026-09-29-第一期中奖名单导入记录.md @@ -0,0 +1,52 @@ +# 第一期中奖名单导入记录(2026-09-29) + +## 背景 + +怀化市社保卡千万好礼促消费活动第一期开奖名单产生后,需导入 UAT 库 `dscp_business_uat.hhrs_winner` 表,供公示页 https://hh.hn12301.net/#/pages/winners/winners 展示。 + +## 数据来源 + +| 文件 | 内容 | +| --- | --- | +| `抽奖-中奖数据.xlsx`(2026-09-29 10:21 导出) | 第一期中奖名单原始文件:2000 人(姓名+脱敏身份证号) | +| `抽奖-中奖数据-匹配hhrs_lottery_pool-batch1.csv` | 与抽奖池 `hhrs_lottery_pool`(batch_no=1)匹配结果:2001 行(1 人双卡) | + +## 导入内容与校验 + +- 导入通道:直连 UAT MySQL,事务内导入,前后计数复核通过。 +- 导入行数:**2000**(batch1 CSV 2001 行按 姓名+证件号 去重;会同县「杨明 431225********4219」池中有两条卡记录,保留 pool_id 较小的一条,业务侧如需明确以哪张卡中奖需另行核实)。 +- 表结构:UAT 库 `hhrs_winner` 实际为抽奖池版结构(`id, pool_id, member_name, county, member_identity_no, member_phone, created_time, updated_time`),无奖品/开奖日期列。 +- 字段取值:`id` 与 `pool_id` 均取抽奖池记录 id(一一对应、可溯源);`county` 取自池表;证件/手机号为池表脱敏值(库内即脱敏,公示展示不受影响);`created_time=NOW()`(2026-09-29 14:27)。 +- 同步操作:对应 2000 条池记录 `won` 置 1(与抽奖台「公布即回写」语义一致)。 +- 旧数据:导入前表为空,无清理动作。 + +## 已知问题(导入前即存在) + +dscp-uat 当前部署的后端与上表结构不匹配: + +- `mp-api/hhrsWinner/dates`、`mp-api/hhrsWinner/list` 均返回 `errcode 99999`(部署代码按旧 prize 版 schema 查询,`draw_date/card_model_id` 列已不存在); +- `open-api/hhrsDraw/*`(抽奖台后台)在该服务上为 404,抽奖台实际使用的后端未部署在此环境。 + +因此公示页当前显示「暂无数据/接口失败」,**与本次导入的数据无关**;待与现表结构匹配的新版后端部署后,第一期名单即可展示,数据无需重导。 + +## 补充排查发现(2026-09-29 下午) + +1. UAT 库中还存在抽奖后台配套表 `hhrs_draw_activity` / `hhrs_draw_round`(2026-09-28 建),即抽奖台新版后端的排期数据: + - **第一期官方开奖日期 = 2026-09-29**(「2026 金秋千万好礼 · 第一期(9·29 专场)」,活动 status=1 已发布); + - 排期设计:9·29 专场三场 600+700+700=2000 人,分别绑定 batch 1/2/3;全部轮次 status=0(待开奖)、seed/drawn_time 为空 → **抽奖台自动回写链路从未成功跑通**(与 dscp-uat 上 hhrsDraw 接口 404 相符); + - 实际交付的第一期名单是「batch1 一次抽 2000 人」,与排期表的三场拆分不一致——若后续场次仍按排期表取 batch2/3,不受本次导入影响(批次天然互斥)。 +2. 公示页要立即显示名单,零部署方案为:`hhrs_winner` 增加旧接口所需 8 列(card_model_id/member_id/prize_*/draw_date/remark,均可空,兼容新版写入),并回填:card_model_id=747609734826757、draw_date='2026-09-29'、prize_name='怀化市社保卡千万好礼促消费千元权益包'、prize_type='权益包'、prize_amount=100000(分,即 1000 元)。**待用户批准后执行**。 +3. 前端「隐藏手机号」改动(本地已完成)生效路径:HBuilderX CLI 可本地构建,产物上传 121.43.239.220:/home/hh/html 需要 SSH 权限(凭据在 Obsidian 运维手册)。 + +## 前端配套改动(本地已改,未发布) + +`hhrs/pages/winners/winners.vue`: + +1. 按业务要求移除「手机号码」列(表头、行、样式、按手机号过滤逻辑),搜索框改为仅按姓名。 +2. 修复「名单未翻到的人物搜索无结果」(如 王球莲):搜索原本只在前端已加载的 10 条/页内过滤,后端列表接口无姓名检索参数;现改为输入关键字/点搜索时按 500 条大页自动拉全当期名单(实测第一期 4 次请求共 2000 条)再本地过滤,全量结果按期缓存;拉取失败静默降级为已加载部分可搜。 + +需 HBuilderX 构建后上传 121.43.239.220:/home/hh/html 生效(`sh h5-release.sh` → 产物 scp 原子切换)。 + +## 发布结果(2026-09-29 16:07 线上实测) + +已发布生效:入口 `index.8ec4f995.js` → `index.e438708b.js`,修复分片 `pages-winners-winners.a875331e.js`(含 loadAll 全量搜索)公网 200。浏览器实测:不翻页直接搜「王球莲」命中 1 条(4 个 pageSize=500 请求自动拉全),姓名/身份证/手机号三列正常。四站点回归 hh/pxdy/mkh5/api/dw 全 200。发布过程偏差(目录切换替代覆盖式)已按手册补救:旧 hash 资源全量还原、`._*` AppleDouble 清理、webroot 备份 `/root/hh-html-backup-20260929-presearchfix.tar.gz`。winners.vue 源码改动尚未 commit。 diff --git a/h5-release.sh b/h5-release.sh new file mode 100755 index 0000000..bc762ff --- /dev/null +++ b/h5-release.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# xuchao: hhrs H5 发布脚本 —— HBuilderX 构建不吃项目根 index.html(静态标签会被丢), +# 云闪付控件(upsdk)必须静态标签加载才能注册控件桥(路线B,2026-09-28 定), +# 故构建后把标签注入产物 index.html 再打包上传。发布 = sh h5-release.sh +set -e +cd "$(dirname "$0")" +rm -rf unpackage/dist/build/web +/Applications/HBuilderX.app/Contents/MacOS/cli publish web --project hhrs +BUILT=unpackage/dist/build/web/index.html +# 注入云闪付 SDK 静态标签(幂等:已有则跳过) +grep -q "open.95516.com" "$BUILT" || sed -i '' 's#怀化人社#怀化人社#' "$BUILT" +grep -q "open.95516.com" "$BUILT" && echo "[h5-release] upsdk 静态标签已在产物 index.html" +tar czf /tmp/hh-voucher/web_release.tgz -C unpackage/dist/build/web . +echo "[h5-release] 产物就绪:/tmp/hh-voucher/web_release.tgz —— 用 expect rsh.exp scp 上传后原子切换" diff --git a/index.html b/index.html index 750e6f5..2591403 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,8 @@ (coverSupport ? ', viewport-fit=cover' : '') + '" />') + + diff --git a/main.js b/main.js index bde1deb..b8308bb 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,9 @@ import App from './App' +import { injectUpSdk } from '@/common/petrolVoucher.js' + +// xuchao: 云闪付控件 SDK 预热——HBuilderX 构建不吃根 index.html,静态标签无效, +// 在 App 挂载前(document-start 最早 JS 点)注入,逼近静态 head 加载时机(石油券支付修复) +injectUpSdk() // #ifndef VUE3 import Vue from 'vue' diff --git a/pages.json b/pages.json index a86941f..7eee50d 100644 --- a/pages.json +++ b/pages.json @@ -51,6 +51,18 @@ "navigationStyle": "custom" } }, + { + "path": "pages/petrol/orderConfirm", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/petrol/voucherDetail", + "style": { + "navigationStyle": "custom" + } + }, { "path": "pages/winners/winners", "style": { diff --git a/pages/discount/discount.vue b/pages/discount/discount.vue index 829bbe0..929fb0e 100644 --- a/pages/discount/discount.vue +++ b/pages/discount/discount.vue @@ -13,12 +13,19 @@ 搜索 + + - + + + + {{ shortDistrict(item.districtName) }} + {{ item.name }} {{ item.category }} @@ -40,7 +47,13 @@ diff --git a/pages/index/login.vue b/pages/index/login.vue index b5efb86..7c8cacf 100644 --- a/pages/index/login.vue +++ b/pages/index/login.vue @@ -43,6 +43,8 @@ + + diff --git a/pages/petrol/voucherDetail.vue b/pages/petrol/voucherDetail.vue new file mode 100644 index 0000000..405c9b8 --- /dev/null +++ b/pages/petrol/voucherDetail.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/pages/rights/detail.vue b/pages/rights/detail.vue index 1899ce1..909c0fb 100644 --- a/pages/rights/detail.vue +++ b/pages/rights/detail.vue @@ -1,6 +1,8 @@