From c2f0ec3b3891bc177bdc58c2a111ab9c4fea911d Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期五, 18 九月 2026 17:13:38 +0800
Subject: [PATCH] 更新....

---
 rencaika_merchant/services/agreement.uts |   39 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/rencaika_merchant/services/agreement.uts b/rencaika_merchant/services/agreement.uts
index 0ccac8e..57764bf 100644
--- a/rencaika_merchant/services/agreement.uts
+++ b/rencaika_merchant/services/agreement.uts
@@ -1,4 +1,4 @@
-import { getApiEndpoint } from '../config/api.uts'
+import { getApiBaseUrl, getApiEndpoint } from '../config/api.uts'
 import { HttpError, request } from './http.uts'
 
 export type MerchantAgreement = {
@@ -9,6 +9,37 @@
 	state: string
 	message: string
 	contentHtml: string
+}
+
+/**
+ * 后台富文本落库时图片/链接存的是相对路径(`/uploads/xxx.png`)。小程序 rich-text 不认相对路径,
+ * 直接渲染就是破图(只显示 alt 文字),所以这里统一补成接口域名下的绝对地址。
+ *
+ * 顺带处理两件后台内容与小程序渲染能力对不齐的事:
+ * 1. 去掉 script/style、内联事件属性和 `javascript:` 协议——后台内容不该在小程序里执行脚本;
+ * 2. `<s>/<strike>/<u>` 换成 rich-text 支持的 `<del>/<ins>`,并给 `<img>` 补内联样式——
+ *    小程序的 rich-text 不继承页面样式,后台图片按原图尺寸会把卡片撑破。
+ *
+ * 规则与人才端 `rencaika/services/business.uts` 的 sanitizeRichText 保持一致,两端表现不要分叉。
+ */
+export const sanitizeAgreementHtml = (html: string): string => {
+	if (html == null) return ''
+	const base = getApiBaseUrl().replace(/\/+$/, '')
+	const content = ('' + html)
+		.replace(/<script[\s\S]*?<\/script>/gi, '')
+		.replace(/<style[\s\S]*?<\/style>/gi, '')
+		.replace(/\son[a-z]+\s*=\s*(['"]).*?\1/gi, '')
+		.replace(/\s(href|src)\s*=\s*(['"])\s*javascript:[^'"]*\2/gi, '')
+	if (base == '') return content
+	return content
+		.replace(/<\s*(\/?)\s*s(?=[\s>/])([^>]*)>/gi, '<$1del$2>')
+		.replace(/<\s*(\/?)\s*strike(?=[\s>/])([^>]*)>/gi, '<$1del$2>')
+		.replace(/<\s*(\/?)\s*u(?=[\s>/])([^>]*)>/gi, '<$1ins$2>')
+		.replace(/(src|href)=(["'])\/\//gi, '$1=$2https://')
+		.replace(/(\s(?:src|href)\s*=\s*(['"]))\/+/gi, '$1' + base + '/')
+		.replace(/(\s(?:src|href)\s*=\s*(['"]))(?!https?:|\/\/|\/|data:|javascript:)/gi, '$1' + base + '/')
+		.replace(/(<img\b[^>]*?\sstyle=(["']))([^"']*)(\2)/gi, '$1$3max-width:100%;height:auto;display:block;margin:10px auto;$4')
+		.replace(/<img\b(?![^>]*\sstyle=)/gi, '<img style="max-width:100%;height:auto;display:block;margin:10px auto;"')
 }
 
 export const loadMerchantAgreement = (
@@ -22,5 +53,9 @@
 		skipAuth: true,
 		skipStoreContext: true,
 		skipUnauthorizedRedirect: true
-	}, onSuccess, onError)
+	}, (agreement: MerchantAgreement) => {
+		// 页面拿到的是可直接喂给 rich-text 的内容,不必各自再处理一遍相对路径与标签差异。
+		if (agreement != null) agreement.contentHtml = sanitizeAgreementHtml(agreement.contentHtml)
+		onSuccess(agreement)
+	}, onError)
 }

--
Gitblit v1.7.1