| | |
| | | import { getApiEndpoint } from '../config/api.uts' |
| | | import { getApiBaseUrl, getApiEndpoint } from '../config/api.uts' |
| | | import { HttpError, request } from './http.uts' |
| | | |
| | | export type MerchantAgreement = { |
| | |
| | | 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 = ( |
| | |
| | | skipAuth: true, |
| | | skipStoreContext: true, |
| | | skipUnauthorizedRedirect: true |
| | | }, onSuccess, onError) |
| | | }, (agreement: MerchantAgreement) => { |
| | | // 页面拿到的是可直接喂给 rich-text 的内容,不必各自再处理一遍相对路径与标签差异。 |
| | | if (agreement != null) agreement.contentHtml = sanitizeAgreementHtml(agreement.contentHtml) |
| | | onSuccess(agreement) |
| | | }, onError) |
| | | } |