feat(config): implement dynamic security blocklist and home marketing popup with admin controls
这个提交包含在:
@@ -686,6 +686,21 @@ async function seedInitialDataIfEmpty(conn: any): Promise<void> {
|
||||
}
|
||||
]);
|
||||
|
||||
const securityWordsVal = JSON.stringify([
|
||||
'加微信私聊', '私下走微信', '走线下免佣金', '线下给现金', '私下单',
|
||||
'联系方式v', 'vx号', '微信转账', '私加好友', '线下私约'
|
||||
]);
|
||||
|
||||
const homePopupVal = JSON.stringify({
|
||||
enabled: true,
|
||||
title: '新人专享同城陪伴好礼',
|
||||
subtitle: '注册即送20元无门槛立减券,首单专享特惠',
|
||||
imageUrl: 'https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?w=800',
|
||||
link: '/pages/activity/list',
|
||||
btnText: '立即领券组局',
|
||||
frequency: 'once_daily' // once_daily | always | once_ever
|
||||
});
|
||||
|
||||
const [cfgItemRows]: any = await conn.query('SELECT COUNT(*) as count FROM platform_configs');
|
||||
if (cfgItemRows[0].count === 0) {
|
||||
const customerServiceVal = JSON.stringify({
|
||||
@@ -720,10 +735,12 @@ async function seedInitialDataIfEmpty(conn: any): Promise<void> {
|
||||
('platform_protocol', '平台服务协议与合规规范', ?, '小程序端服务协议与隐私政策详情', 1),
|
||||
('community_topics', '友圈热门推荐话题库', ?, '友圈广场发帖推荐话题与热门标签', 1),
|
||||
('community_notice', '友圈社区置顶头条公告', ?, '友圈广场顶部置顶横幅公告与社区公约', 1),
|
||||
('faq_list', '帮助中心与常见问题FAQ', ?, '小程序端帮助中心常见问答与指引', 1);
|
||||
`, [customerServiceVal, safetyNoticeVal, protocolVal, communityTopicsVal, communityNoticeVal, faqListVal]);
|
||||
('faq_list', '帮助中心与常见问题FAQ', ?, '小程序端帮助中心常见问答与指引', 1),
|
||||
('security_words', '私下引流与违规自定义敏感词库', ?, '全平台发帖、评论及订单防私下交易关键词实时过滤', 1),
|
||||
('home_popup', '小程序首页运营全局弹窗', ?, '节日活动推广、新用户专享首单优惠全局浮层弹窗', 1);
|
||||
`, [customerServiceVal, safetyNoticeVal, protocolVal, communityTopicsVal, communityNoticeVal, faqListVal, securityWordsVal, homePopupVal]);
|
||||
} else {
|
||||
// 增量保证 community_topics, community_notice, faq_list 存在
|
||||
// 增量保证各核心配置项完整就绪
|
||||
const [existingRows]: any = await conn.query('SELECT config_key FROM platform_configs');
|
||||
const existingKeys = new Set(existingRows.map((r: any) => r.config_key));
|
||||
if (!existingKeys.has('community_topics')) {
|
||||
@@ -744,5 +761,17 @@ async function seedInitialDataIfEmpty(conn: any): Promise<void> {
|
||||
VALUES ('faq_list', '帮助中心与常见问题FAQ', ?, '小程序端帮助中心常见问答与指引', 1)
|
||||
`, [faqListVal]);
|
||||
}
|
||||
if (!existingKeys.has('security_words')) {
|
||||
await conn.query(`
|
||||
INSERT INTO platform_configs (config_key, name, value_json, description, status)
|
||||
VALUES ('security_words', '私下引流与违规自定义敏感词库', ?, '全平台发帖、评论及订单防私下交易关键词实时过滤', 1)
|
||||
`, [securityWordsVal]);
|
||||
}
|
||||
if (!existingKeys.has('home_popup')) {
|
||||
await conn.query(`
|
||||
INSERT INTO platform_configs (config_key, name, value_json, description, status)
|
||||
VALUES ('home_popup', '小程序首页运营全局弹窗', ?, '节日活动推广、新用户专享首单优惠全局浮层弹窗', 1)
|
||||
`, [homePopupVal]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,6 +1279,23 @@ export class MysqlRepository {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getPlatformConfigByKey(configKey: string): Promise<any> {
|
||||
const [rows]: any = await pool.query(`
|
||||
SELECT id, config_key as configKey, name, value_json as valueJson, description, status
|
||||
FROM platform_configs
|
||||
WHERE config_key = ?
|
||||
`, [configKey]);
|
||||
if (!rows || rows.length === 0) return null;
|
||||
const r = rows[0];
|
||||
let val = r.valueJson;
|
||||
if (typeof val === 'string') {
|
||||
try {
|
||||
val = JSON.parse(val);
|
||||
} catch (_) {}
|
||||
}
|
||||
return { ...r, valueJson: val };
|
||||
}
|
||||
|
||||
async getAdminPlatformConfigs(): Promise<any[]> {
|
||||
const [rows]: any = await pool.query(`
|
||||
SELECT id, config_key as configKey, name, value_json as valueJson, description, status,
|
||||
|
||||
在新工单中引用
屏蔽一个用户