接线1.10实名认证提醒弹窗到真实消息首页(第1章遗留项,此前一直是孤立demo路由)

auth-onboarding-view.jsx 的 RealnameReminder 组件此前是完全孤立的demo:自己画一套
假会话列表背景,只能靠手动改hash访问,没有任何真实入口会导航过去。核对参考图
"实名认证(安卓).png"确认过的弹窗文案本身是对的,只是从来没有接上真实触发条件。

抽出弹窗内容(不带假背景)做成 RealnameReminderModal,挂到真实 MessageHome 挂载时
按 bootstrap.security.realname 的真实状态判断——这个字段本来就在 MessageHome 已经
在用的同一个 bootstrap 请求里,不需要额外接口调用。

参考图本身画的是不可跳过的单按钮强制态,但真实核对 im_be 源码发现这只是
required:true 那个分支的样子;这个环境的真实配置(也是目前后端唯一会返回的默认值)
是 required:false / allow_skip:true。如果照抄参考图做成完全关不掉的弹层,等于把
"实名认证目前是可选的"这个真实产品配置,实现成挡住所有人使用消息功能的强制墙——
按这两个字段分叉:允许跳过时加一个参考图没画、但后端字段明确允许的关闭按钮;且
遵守后端给的 remind_after(当前值24h),关闭后在这个时长内不重复弹,不是每次进
消息首页都弹一次。

联调中发现关闭按钮初版样式是个跟全局 button 选一样宽的圆角方块(漏了覆盖
min-width/box-shadow/margin 这几个全局 button 规则),已修正为纯图标按钮。

真实验证(账号 asn494180,真实 status:"unverified"):弹窗内容与参考图逐句一致;
点击关闭按钮弹窗消失且 localStorage 正确记录时间戳;刷新页面重新连接后,24小时
窗口内弹窗不会重复出现;未清除记录时保持不弹,符合"提醒而非骚扰"的预期。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-04 16:40:27 +08:00
co-authored by Claude Opus 5
parent d21d046443
commit 542aca3dc2
4 changed files with 114 additions and 2 deletions
+57 -1
View File
@@ -13036,6 +13036,42 @@ function QuickMenu({
}, void 0, false)
}, void 0, false);
}
function parseRemindAfter(text) {
const m = /^(\d+)\s*([hdm])$/i.exec(String(text || '').trim());
if (!m) return 24 * 60 * 60 * 1000;
const n = Number(m[1]);
return m[2].toLowerCase() === 'd' ? n * 86400000 : m[2].toLowerCase() === 'h' ? n * 3600000 : n * 60000;
}
function RealnameReminderModal({
allowSkip,
onDismiss
}) {
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("div", {
className: "auth-modal-backdrop",
onClick: allowSkip ? onDismiss : undefined,
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("div", {
className: "auth-modal",
onClick: e => e.stopPropagation(),
children: [allowSkip ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("button", {
type: "button",
className: "auth-modal-close",
"aria-label": "关闭",
onClick: onDismiss,
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)(Icon, {
children: "close"
}, void 0, false)
}, void 0, false) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("h2", {
children: "实名认证提醒"
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("p", {
children: "根据国家法律法规要求,您需先进行实名认证才能使用该项 APP"
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("button", {
className: "auth-primary",
onClick: () => navigate('realname'),
children: "去实名认证"
}, void 0, false)]
}, void 0, true)
}, void 0, false);
}
function MessageHome({
view,
connected,
@@ -13052,6 +13088,23 @@ function MessageHome({
const conversations = entryConversations(bootstrap).concat(normalizeConversations(chatList, myUserId));
const filtered = conversations.filter(item => `${item.title}${item.summary}`.toLowerCase().includes(query.trim().toLowerCase()));
const frequent = frequentContacts(chatList);
const realname = bootstrap && bootstrap.security && bootstrap.security.realname;
const [reminderDismissed, setReminderDismissed] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
const dismissKey = myUserId ? 'realname-reminder-dismissed:' + myUserId : null;
let lastDismissedAt = 0;
try {
lastDismissedAt = dismissKey ? Number(localStorage.getItem(dismissKey) || 0) : 0;
} catch (_) {}
const withinSnooze = lastDismissedAt > 0 && Date.now() - lastDismissedAt < parseRemindAfter(realname && realname.remind_after);
const showRealnameReminder = !!realname && !reminderDismissed && !withinSnooze && (realname.status === 'unverified' || realname.status === 'rejected');
const dismissRealnameReminder = () => {
if (dismissKey) {
try {
localStorage.setItem(dismissKey, String(Date.now()));
} catch (_) {}
}
setReminderDismissed(true);
};
const selectConversation = item => {
if (item.system) {
navigate('system-messages');
@@ -13162,7 +13215,10 @@ function MessageHome({
}, void 0, false) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)(Toast, {
message: toast,
onDone: () => setToast('')
}, void 0, false)]
}, void 0, false), showRealnameReminder ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)(RealnameReminderModal, {
allowSkip: !!realname.allow_skip,
onDismiss: dismissRealnameReminder
}, void 0, false) : null]
}, void 0, true);
}
function MessageActions() {