fix(vip): preserve safe HTML in VIP copy
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
7a0445fc4a
commit
573040381d
15 files changed
+155
-118
No files matched your search
@@ -69,9 +69,9 @@ function vipProductFields() {
|
||||
function vipLevelTabFields(level) {
|
||||
const dep = { key: `pay_user_vip_${level}_s`, value: true };
|
||||
return [
|
||||
{ key: `pay_user_vip_${level}_name`, label: '会员显示名称', type: 'input', default: level === 1 ? '黄金会员' : '钻石会员', dependsOn: dep, help: '会员名称(例如“黄金会员”、“超级会员”)' },
|
||||
{ key: `pay_user_vip_${level}_desc`, label: '一句话简介', type: 'input', default: '尊享专属特权', dependsOn: dep },
|
||||
{ key: `pay_user_vip_${level}_equity`, label: '会员权益 HTML', type: 'textarea', sanitize_type: 'html', default: VIP_EQUITY_DEFAULT, rows: 4, dependsOn: dep, help: '建议使用 <li> 列表项' },
|
||||
{ key: `pay_user_vip_${level}_name`, label: '会员显示名称', type: 'input', sanitize_type: 'html', default: level === 1 ? '黄金会员' : '钻石会员', dependsOn: dep, help: '支持HTML,请注意控制长度' },
|
||||
{ key: `pay_user_vip_${level}_desc`, label: '一句话简介', type: 'input', sanitize_type: 'html', default: '尊享专属特权', dependsOn: dep, help: '支持HTML' },
|
||||
{ key: `pay_user_vip_${level}_equity`, label: '会员权益 HTML', type: 'textarea', sanitize_type: 'html', default: VIP_EQUITY_DEFAULT, rows: 4, dependsOn: dep, help: '支持安全HTML,建议使用 <li> 列表项' },
|
||||
{ key: `vip_${level}_product_s`, label: '购买会员', type: 'switch', default: true, dependsOn: dep, help: '关闭后则不能付费购买会员,但可通过积分兑换会员,请确保已开启积分以及积分兑换会员功能' },
|
||||
{
|
||||
key: `vip_${level}_product`,
|
||||
@@ -290,9 +290,10 @@ export const vipSchema = {
|
||||
key: 'vip_renew_desc',
|
||||
label: '续费介绍',
|
||||
type: 'input',
|
||||
sanitize_type: 'html',
|
||||
default: '立即续费会员,畅享VIP权益',
|
||||
dependsOn: { key: 'vip_renew', value: true },
|
||||
help: '续费会员的一句话简介',
|
||||
help: '续费会员的一句话简介,支持HTML',
|
||||
},
|
||||
{
|
||||
key: 'vip_renew_price_type',
|
||||
@@ -371,7 +372,7 @@ export const vipSchema = {
|
||||
title: '会员升级',
|
||||
fields: [
|
||||
{ key: 'vip_upgrade', label: '允许升级', type: 'switch', default: true },
|
||||
{ key: 'vip_upgrade_desc', label: '升级介绍', type: 'input', default: '升级VIP会员,享更多会员权益', dependsOn: { key: 'vip_upgrade', value: true }, help: '升级会员的一句话简介' },
|
||||
{ key: 'vip_upgrade_desc', label: '升级介绍', type: 'input', sanitize_type: 'html', default: '升级VIP会员,享更多会员权益', dependsOn: { key: 'vip_upgrade', value: true }, help: '升级会员的一句话简介,支持HTML' },
|
||||
{
|
||||
key: 'vip_upgrade_product',
|
||||
label: '升级价格',
|
||||
@@ -478,9 +479,10 @@ export const vipSchema = {
|
||||
key: 'pay_user_vip_desc',
|
||||
label: '会员介绍',
|
||||
type: 'input',
|
||||
sanitize_type: 'html',
|
||||
default: '开通VIP会员,享受会员专属折扣以及多项特权',
|
||||
dependsOn: { any: [{ key: 'pay_user_vip_1_s', value: true }, { key: 'pay_user_vip_2_s', value: true }] },
|
||||
help: '显示在开通界面顶部一句话简介,可以为会员权益简介或者活动介绍',
|
||||
help: '显示在开通界面顶部一句话简介,可以为会员权益简介或者活动介绍,支持HTML',
|
||||
},
|
||||
{
|
||||
key: 'pay_user_vip_more',
|
||||
|
||||
+9
-13
@@ -17,8 +17,7 @@
|
||||
return el;
|
||||
}
|
||||
|
||||
// 服务端已按 post 级 HTML 净化的富文本字段(more / 卡密说明)走 innerHTML;
|
||||
// node() 的 textContent 会把标签当字面文本显示。
|
||||
// Server-side schema sanitization limits these configured rich-text fields to post-safe HTML.
|
||||
function htmlNode(tag, className, value) {
|
||||
var el = document.createElement(tag);
|
||||
if (className) el.className = className;
|
||||
@@ -70,7 +69,7 @@
|
||||
if (levelInfo && levelInfo.img_icon) {
|
||||
var img = node("img", "img-icon");
|
||||
img.src = text(levelInfo.img_icon);
|
||||
img.alt = text(levelInfo.name || "");
|
||||
img.alt = text(levelInfo.name_text || levelInfo.name || "");
|
||||
img.decoding = "async";
|
||||
return img;
|
||||
}
|
||||
@@ -125,7 +124,7 @@
|
||||
// (右上 tag + 价格行 + 时长 badge,无标题行)。
|
||||
var product = node("div", "zib-widget vip-product relative text-center product-box");
|
||||
// 标签颜色取后台「标签颜色」配置,未配置时回退参考主题默认的 jb-yellow。
|
||||
if (item.discount_tag) append(product, node("div", "abs-right vip-tag badg " + (item.tag_class || "jb-yellow"), item.discount_tag));
|
||||
if (item.discount_tag) append(product, htmlNode("div", "abs-right vip-tag badg " + (item.tag_class || "jb-yellow"), item.discount_tag));
|
||||
append(product, priceRow(mark, item.price_label || "", item.show_price_label || ""));
|
||||
if (item.days_label) append(product, node("div", "muted-2-color c-blue em09 p2-10 badg radius", item.days_label));
|
||||
append(label, product);
|
||||
@@ -408,7 +407,7 @@
|
||||
} else if (member.state === "expired") {
|
||||
append(userInfo, node("div", "muted-2-color em09", "已过期"));
|
||||
} else if (catalog.desc) {
|
||||
append(userInfo, node("div", "muted-2-color em09", catalog.desc));
|
||||
append(userInfo, htmlNode("div", "muted-2-color em09", catalog.desc));
|
||||
}
|
||||
append(userBox, userInfo);
|
||||
append(modal, userBox);
|
||||
@@ -444,8 +443,8 @@
|
||||
append(miniIcon, vipIcon(levelInfo));
|
||||
append(miniIconbox, miniIcon);
|
||||
var miniInfo = node("div", "v-info");
|
||||
append(miniInfo, node("div", "v-name", actionLabel(action) + (levelInfo.name || group.name || "VIP" + level)));
|
||||
append(miniInfo, node("div", "v-desc em09", levelInfo.desc || ""));
|
||||
append(miniInfo, htmlNode("div", "v-name", actionLabel(action) + (levelInfo.name || group.name || "VIP" + level)));
|
||||
append(miniInfo, htmlNode("div", "v-desc em09", levelInfo.desc || ""));
|
||||
append(miniIconbox, miniInfo);
|
||||
append(miniCard, miniIconbox);
|
||||
append(tab, miniCard);
|
||||
@@ -471,15 +470,12 @@
|
||||
append(vicon, vipIcon(levelInfo));
|
||||
append(iconbox, vicon);
|
||||
var vinfo = node("div", "v-info");
|
||||
append(vinfo, node("div", "v-name", levelInfo.name || group.name || "VIP" + level));
|
||||
append(vinfo, node("div", "v-desc em09", levelInfo.desc || ""));
|
||||
append(vinfo, htmlNode("div", "v-name", levelInfo.name || group.name || "VIP" + level));
|
||||
append(vinfo, htmlNode("div", "v-desc em09", levelInfo.desc || ""));
|
||||
append(iconbox, vinfo);
|
||||
append(info, iconbox);
|
||||
if (levelInfo.equity) {
|
||||
var equity = document.createElement("ul");
|
||||
equity.className = "v-equity";
|
||||
equity.innerHTML = text(levelInfo.equity);
|
||||
append(info, equity);
|
||||
append(info, htmlNode("div", "", levelInfo.equity));
|
||||
}
|
||||
var infoBa = node("div", "abs-center vip-baicon");
|
||||
append(infoBa, vipIcon(levelInfo));
|
||||
|
||||
Reference in new issue
Block a user