接线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:
co-authored by
Claude Opus 5
parent
d21d046443
commit
542aca3dc2
@@ -204,6 +204,30 @@ function QuickMenu({onClose, onAction, permissions}) {
|
||||
</div>;
|
||||
}
|
||||
|
||||
// 1.10 实名认证提醒:docs/images/实名认证(安卓).png 显示的是不可跳过的强制态(单按钮"去实名
|
||||
// 认证",没有关闭/稍后处理)——但那张图对应的是 bootstrap.security.realname.required===true 这个
|
||||
// 分支,这个环境(以及目前后端唯一会返回的默认配置)实际是 required:false / allow_skip:true。
|
||||
// 照抄参考图做成完全关不掉的弹层,等于把"实名认证目前是可选的"这个真实配置,实现成挡住所有人的
|
||||
// 强制墙——所以按这两个字段分叉:允许跳过时加一个参考图没画但后端明确允许的关闭按钮;且遵守
|
||||
// remind_after,跳过后在这个时长内不重复弹(不是每次进消息首页都弹一次)。
|
||||
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 <div className="auth-modal-backdrop" onClick={allowSkip ? onDismiss : undefined}>
|
||||
<div className="auth-modal" onClick={e => e.stopPropagation()}>
|
||||
{allowSkip ? <button type="button" className="auth-modal-close" aria-label="关闭" onClick={onDismiss}><Icon>close</Icon></button> : null}
|
||||
<h2>实名认证提醒</h2>
|
||||
<p>根据国家法律法规要求,您需先进行实名认证才能使用该项 APP</p>
|
||||
<button className="auth-primary" onClick={() => navigate('realname')}>去实名认证</button>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function MessageHome({view, connected, chatList, myUserId, onTopicSelected, onOpenScanner}) {
|
||||
const [query, setQuery] = React.useState('');
|
||||
const [menuOpen, setMenuOpen] = React.useState(view === 'messages-menu');
|
||||
@@ -217,6 +241,19 @@ function MessageHome({view, connected, chatList, myUserId, onTopicSelected, onOp
|
||||
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.useState(false);
|
||||
const dismissKey = myUserId ? 'realname-reminder-dismissed:' + myUserId : null;
|
||||
let lastDismissedAt = 0;
|
||||
try { lastDismissedAt = dismissKey ? Number(localStorage.getItem(dismissKey) || 0) : 0; } catch (_) { /* ignore */ }
|
||||
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 (_) { /* ignore */ } }
|
||||
setReminderDismissed(true);
|
||||
};
|
||||
|
||||
const selectConversation = item => {
|
||||
if (item.system) {
|
||||
navigate('system-messages');
|
||||
@@ -269,6 +306,7 @@ function MessageHome({view, connected, chatList, myUserId, onTopicSelected, onOp
|
||||
<BottomNavigation />
|
||||
{menuOpen ? <QuickMenu onClose={() => setMenuOpen(false)} onAction={runQuickAction} permissions={bootstrap && bootstrap.permissions} /> : null}
|
||||
<Toast message={toast} onDone={() => setToast('')} />
|
||||
{showRealnameReminder ? <RealnameReminderModal allowSkip={!!realname.allow_skip} onDismiss={dismissRealnameReminder} /> : null}
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user