diff --git a/.env b/.env index d861b06..5226b5f 100644 --- a/.env +++ b/.env @@ -10,3 +10,7 @@ VITE_APP_DEV_SERVICE=https://dzc-test-1.fy.takin.cc # 生产环境后端地址;配置为空时由线上部署提供同源接口。 # VITE_APP_PROD_SERVICE=https://www.zianxin.com/api VITE_APP_PROD_SERVICE=/api + +# 图片基址沿用后台 VITE_IMAGE_BASE_PATH;相对 logoPic 通过同源 /api 访问文件网关。 +# 使用独立图片服务时可改成该服务完整地址,已是 HTTP(S) 的图片链接不会重复拼接。 +VITE_IMAGE_BASE_PATH=/api diff --git a/README.md b/README.md index f161f7d..3034b9b 100644 --- a/README.md +++ b/README.md @@ -86,3 +86,9 @@ tm-ui `3.2.0` 从参考项目的 `src/uni_modules/tm-ui` 原样引入 `tm-sheet` 结果页参考 App 的 `pay-complete.vue`,使用同版 `lottie-web 5.13.0` 和原始 `success/fail/loading` 矢量动画:成功、失败播放一次,查询中循环;减少动态效果时显示最终帧,后台暂停,销毁时清理。动画不可用时显示本地状态图标,文字与金额保持可读。 取消、网络错误和确认超时不会显示“支付失败”,而是保留待确认说明及只读重新查询入口。返回收银台仍使用同一票据,携带 `returned=1、resultViewed=1` 抑制再次自动付款及结果页往返跳转;该标记只影响导航,不改变服务端状态。确认成功或关闭后,线下商户入口可继续沿用原“再付一笔/重新输入金额”流程。 + +## 商户标识地址 + +收银页和付款结果页共用 `merchant-logo.vue`,原始 `logoPic` 保持后端返回值。相对图片路径(例如 `/admin/sys-file/oss/file?fileName=...`)按后台同名的 `.env` 配置 `VITE_IMAGE_BASE_PATH` 拼接,默认 `/api`,不追加 `/third`。生产同源 `/api` 代理应同时承接文件接口的 `/admin` 路径;也可把图片基址设为独立文件网关的完整地址。 + +完整 HTTP(S) 图片链接及其查询参数原样保留;缺少图片或加载失败时使用店铺占位图形。切换图片地址后重置失败状态,不影响商户信息或付款状态。修改 `.env` 后需重启开发服务,线上需要重新构建发布。 diff --git a/src/pages/pay/index.vue b/src/pages/pay/index.vue index 43fea6a..bda9aa2 100644 --- a/src/pages/pay/index.vue +++ b/src/pages/pay/index.vue @@ -5,8 +5,7 @@ 收款商户 @@ -59,7 +58,7 @@ import { computed, nextTick, ref, watch } from "vue" import PaymentKeyboard from "@@/components/payment-keyboard.vue" import PaymentUnavailable from "@@/components/payment-unavailable.vue" import { useMerchantPayment } from "@@/hooks/use-merchant-payment" -import { themeColors } from "@@/config/theme" +import MerchantLogo from "@@/components/merchant-logo.vue" import { hasViewedPaymentResult, paymentResultRoute, resolvePaymentResultPhase } from "@@/utils/payment-result" /** 页面与数字键盘共享真实收银状态,任何付款入口都经过同一个请求和金额守卫。 */ @@ -92,14 +91,9 @@ watch([context, ticket], () => { if (!hasViewedPaymentResult()) showResult() }) -/** 商户图片失败只切换占位标识,不影响真实商户名称和付款对象。 */ -const merchantLogoFailed = ref(false) /** 长金额按展示长度缩小字号,始终保留完整金额。 */ const amountSizeClass = computed(() => amount.value.length > 10 ? "text-56rpx" : amount.value.length > 7 ? "text-72rpx" : "text-104rpx") -/** 标识失败时使用 tm-ui 店铺图形。 */ -function handleLogoError() { merchantLogoFailed.value = true } - /** 保留 Tab 和按钮原生键盘语义;锁定金额时 Hook 会拒绝数字输入。 */ function handleKeyboard(event: KeyboardEvent) { if (event.defaultPrevented || event.ctrlKey || event.metaKey || event.altKey || event.isComposing) return diff --git a/src/pages/pay/pay-complete.vue b/src/pages/pay/pay-complete.vue index 1338a10..2a36757 100644 --- a/src/pages/pay/pay-complete.vue +++ b/src/pages/pay/pay-complete.vue @@ -25,7 +25,12 @@ 收款商户 - {{ merchantName }} + + + + + {{ merchantName }} + 支付方式 @@ -58,6 +63,7 @@ + + diff --git a/src/sheep/utils/image.ts b/src/sheep/utils/image.ts new file mode 100644 index 0000000..e8c61ef --- /dev/null +++ b/src/sheep/utils/image.ts @@ -0,0 +1,21 @@ +/** 图片基址沿用后台同名配置;未单独配置时复用当前环境的 API 前缀,不附加 /third。 */ +const imageBase = (import.meta.env.VITE_IMAGE_BASE_PATH + || (import.meta.env.DEV ? import.meta.env.VITE_API_URL || "/api" : import.meta.env.VITE_APP_PROD_SERVICE || "")) + .trim().replace(/\/+$/, "") + +/** + * 将后端 logoPic 相对文件路径拼成可访问地址,完整 HTTP(S) 链接保留原查询参数。 + * 图片地址不携带登录 Token;缺失或不支持的协议交给商户标识组件显示占位图形。 + */ +export function resolveImageUrl(source?: string | null): string { + if (typeof source !== "string") return "" + const path = source.trim() + if (!path) return "" + if (/^https?:\/\//i.test(path) || path.startsWith("//")) return path + if (/^[a-z][a-z0-9+.-]*:/i.test(path)) return "" + const relative = path.replace(/^\/+/, "") + if (!imageBase) return `/${relative}` + // 同源前缀已包含在文件地址时不再次拼接,例如 /api/admin/...。 + if (imageBase.startsWith("/") && (path === imageBase || path.startsWith(`${imageBase}/`))) return path + return `${imageBase}/${relative}` +}