fix(导航): 排查全项目后修复其余同类tab切换污染历史记录问题
上一提交(e61eb402)只修了"我的收藏"/"查找聊天记录"两处,用户要求排查其他页面是否
也有同样问题。全项目排查<nav>/tabbar/active态切换元素,逐一确认onClick是否直接调用
HashNavigation.navigateTo()(每次都push一条历史记录),找到5处同类实例并修复:
- message-center-view.jsx / workplace-collaboration-view.jsx:底部导航"工作台"<->"消息"
两个tab——这是全应用唯一的根级tab bar,也是点击频率最高的一处,之前同样每次切换都
push一条历史记录。
- workplace-collaboration-view.jsx:日报/月报列表页的"我的xx"<->"团队统计"切换(同一个
组件、同一个页面,只是team boolean不同),同样的问题。
- new-topic-view.jsx:"开始新会话"页的搜索/新群组/通过id三个tab。
- wallpapers.jsx:"壁纸"设置页的图案/图片两个tab。
均改用上一提交新增的HashNavigation.navigateReplace()。已在浏览器逐一实测:连续切换
多次tab后,无论真实浏览器返回还是应用自己的返回按钮,都能一次性返回到进入该页面之前
的真实上一页。
以下经排查确认不受影响,未改动:group-management-view.jsx的群聊分类tab(我创建的/
管理的/加入的)和contact-management-view.jsx的字母索引锚点均只用本地state/scrollIntoView,
不涉及hash跳转;auth-onboarding-view.jsx的登录<->注册切换、new-topic-view.jsx提交后的
三处跳转是真实的"离开当前页"操作,保留push语义符合预期。
This commit is contained in:
@@ -20,6 +20,15 @@ const navigate = (view, topic) => {
|
||||
HashNavigation.navigateTo(hash);
|
||||
};
|
||||
|
||||
// BottomNavigation's 消息<->工作台 switch is the app's root-level tab bar, not a navigation to a
|
||||
// "different page" in the back-stack sense -- same bug/fix as content-library-view.jsx's
|
||||
// navigateReplace (see its comment): navigate() here pushed a history entry on every tab click, so
|
||||
// bouncing between 消息 and 工作台 a few times (a completely normal usage pattern for the app's only
|
||||
// two bottom tabs) made the back button just cycle through past tab switches instead of leaving the
|
||||
// app, exactly like a standard bottom-tab-bar app's back button should not have to unwind every past
|
||||
// tab switch to back out.
|
||||
const navigateReplace = (view) => HashNavigation.navigateReplace(HashNavigation.setUrlSidePanel(window.location.hash, view));
|
||||
|
||||
// Was a hardcoded FREQUENT_CONTACTS mock (5 fake names, always clicking through to the same
|
||||
// direct-message-view.jsx demo regardless of which avatar was tapped -- confirmed independently by
|
||||
// a user screenshot showing every contact opening the identical "接语彤" script). Real "frequently
|
||||
@@ -183,7 +192,7 @@ function normalizeConversations(chatList, myUserId) {
|
||||
|
||||
function BottomNavigation() {
|
||||
return <nav className="messages-bottom-nav" aria-label="主导航">
|
||||
<button type="button" onClick={() => navigate('workbench')}><Icon>dashboard</Icon><span>工作台</span></button>
|
||||
<button type="button" onClick={() => navigateReplace('workbench')}><Icon>dashboard</Icon><span>工作台</span></button>
|
||||
<button type="button" className="active"><Icon>person</Icon><span>消息</span></button>
|
||||
</nav>;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,11 @@ class NewTopicView extends React.Component {
|
||||
|
||||
handleTabClick(e) {
|
||||
e.preventDefault();
|
||||
HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
// Same-page tab switch (find user / new group / find by id), not a navigation to a different
|
||||
// page -- navigateTo() pushed a history entry per click purely to keep the `tab` url param in
|
||||
// sync, so repeatedly switching tabs made the back button cycle through past tabs instead of
|
||||
// leaving this page. navigateReplace() keeps the param in sync without that side effect.
|
||||
HashNavigation.navigateReplace(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
this.setState({tabSelected: e.currentTarget.dataset.id});
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ export default class WallpapersView extends React.PureComponent {
|
||||
|
||||
handleTabClick(e) {
|
||||
e.preventDefault();
|
||||
HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
// Same-page tab switch (pattern / image), not a navigation to a different page -- see the same
|
||||
// fix/comment in new-topic-view.jsx's handleTabClick.
|
||||
HashNavigation.navigateReplace(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
this.setState({tab: e.currentTarget.dataset.id});
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,14 @@ const navigate = (view, params) => {
|
||||
HashNavigation.navigateTo(hash);
|
||||
};
|
||||
|
||||
// Same bug/fix as content-library-view.jsx's navigateReplace: DailyReportList/MonthlyReportList's
|
||||
// 我的日报|月报 <-> 团队统计 switch is a same-page tab toggle (same component, just a `team` boolean),
|
||||
// not a navigation to a different page -- using navigate() here pushed a history entry per click, so
|
||||
// switching back and forth a few times made the system back button (and this app's own Header back
|
||||
// button, gated on HashNavigation.goBack()) cycle through past toggle states instead of leaving the
|
||||
// report page. replaceState-based navigateReplace keeps the hash in sync without that side effect.
|
||||
const navigateReplace = (view) => HashNavigation.navigateReplace(HashNavigation.setUrlSidePanel(window.location.hash, view));
|
||||
|
||||
export const WORKPLACE_COLLABORATION_VIEWS = [
|
||||
'workbench', 'organization-directory', 'meeting-organizer', 'meeting-attendee', 'meeting-create', 'meeting-detail',
|
||||
'daily-report-editor', 'daily-report-mine', 'daily-report-team', 'daily-report-detail',
|
||||
@@ -166,7 +174,7 @@ function Workbench({onToast}) {
|
||||
</button>)}</section>
|
||||
</main><nav className="workplace-bottom-nav" aria-label="主导航">
|
||||
<button type="button" className="active"><Icon>dashboard</Icon><span>工作台</span></button>
|
||||
<button type="button" onClick={() => navigate('messages-home')}><Icon>chat_bubble_outline</Icon><span>消息</span></button>
|
||||
<button type="button" onClick={() => navigateReplace('messages-home')}><Icon>chat_bubble_outline</Icon><span>消息</span></button>
|
||||
</nav></div>;
|
||||
}
|
||||
|
||||
@@ -756,7 +764,7 @@ function DailyReportList({team, myUserId, onToast}) {
|
||||
<main>
|
||||
{team && stats ? <section className="report-statistics">
|
||||
<header><span><small>{formatMeetingDate(new Date())}</small><strong>全公司</strong></span>
|
||||
<button type="button" onClick={() => navigate('daily-report-mine')}>我的日报</button></header>
|
||||
<button type="button" onClick={() => navigateReplace('daily-report-mine')}>我的日报</button></header>
|
||||
<div><span><b>{stats.expected_count || 0}</b><small>应提交</small></span>
|
||||
<span><b>{stats.submitted_count || 0}</b><small>已提交</small></span>
|
||||
<span><b>{(stats.expected_count || 0) - (stats.submitted_count || 0)}</b><small>未提交</small></span></div>
|
||||
@@ -766,7 +774,7 @@ function DailyReportList({team, myUserId, onToast}) {
|
||||
<input value={query} onChange={e => setQuery(e.target.value)} placeholder={team ? '搜索姓名或内容' : '搜索日期'} /></label>
|
||||
{!team ? <nav className="report-role-switch">
|
||||
<button type="button" className="active">我的日报</button>
|
||||
<button type="button" onClick={() => navigate('daily-report-team')}>团队统计</button>
|
||||
<button type="button" onClick={() => navigateReplace('daily-report-team')}>团队统计</button>
|
||||
</nav> : null}
|
||||
<section className="report-cards">
|
||||
{reports == null ? <p className="organization-loading">加载中…</p> :
|
||||
@@ -954,7 +962,7 @@ function MonthlyReportList({team, myUserId, onToast}) {
|
||||
<main>
|
||||
{team && stats ? <section className="report-statistics">
|
||||
<header><span><small>{formatMonthLabel(toMonthInputValue(new Date()))}</small><strong>全公司</strong></span>
|
||||
<button type="button" onClick={() => navigate('monthly-report-mine')}>我的月报</button></header>
|
||||
<button type="button" onClick={() => navigateReplace('monthly-report-mine')}>我的月报</button></header>
|
||||
<div><span><b>{stats.expected_count || 0}</b><small>应提交</small></span>
|
||||
<span><b>{stats.submitted_count || 0}</b><small>已提交</small></span>
|
||||
<span><b>{(stats.expected_count || 0) - (stats.submitted_count || 0)}</b><small>未提交</small></span></div>
|
||||
@@ -963,7 +971,7 @@ function MonthlyReportList({team, myUserId, onToast}) {
|
||||
<input value={query} onChange={e => setQuery(e.target.value)} placeholder={team ? '搜索姓名或内容' : '搜索月份或内容'} /></label>
|
||||
{!team ? <nav className="report-role-switch">
|
||||
<button type="button" className="active">我的月报</button>
|
||||
<button type="button" onClick={() => navigate('monthly-report-team')}>团队统计</button>
|
||||
<button type="button" onClick={() => navigateReplace('monthly-report-team')}>团队统计</button>
|
||||
</nav> : null}
|
||||
<section className="report-cards">
|
||||
{reports == null ? <p className="organization-loading">加载中…</p> :
|
||||
|
||||
+9
-7
@@ -13206,6 +13206,7 @@ const navigate = (view, topic) => {
|
||||
hash = topic ? _lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].addUrlParam(hash, 'topic', topic) : _lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].removeUrlParam(hash, 'topic');
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateTo(hash);
|
||||
};
|
||||
const navigateReplace = view => _lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateReplace(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].setUrlSidePanel(window.location.hash, view));
|
||||
function frequentContacts(chatList) {
|
||||
if (!chatList || chatList.length === 0) return [];
|
||||
return chatList.filter(item => item.topic && tinode_sdk__WEBPACK_IMPORTED_MODULE_1__.Tinode.isP2PTopicName(item.topic)).slice().sort((a, b) => new Date(b.touched || 0).getTime() - new Date(a.touched || 0).getTime()).slice(0, 8).map(item => ({
|
||||
@@ -13392,7 +13393,7 @@ function BottomNavigation() {
|
||||
"aria-label": "主导航",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('workbench'),
|
||||
onClick: () => navigateReplace('workbench'),
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)(Icon, {
|
||||
children: "dashboard"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("span", {
|
||||
@@ -14897,7 +14898,7 @@ class NewTopicView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
||||
}
|
||||
handleTabClick(e) {
|
||||
e.preventDefault();
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__["default"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__["default"].addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__["default"].navigateReplace(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__["default"].addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
this.setState({
|
||||
tabSelected: e.currentTarget.dataset.id
|
||||
});
|
||||
@@ -20570,6 +20571,7 @@ const navigate = (view, params) => {
|
||||
});
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateTo(hash);
|
||||
};
|
||||
const navigateReplace = view => _lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateReplace(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].setUrlSidePanel(window.location.hash, view));
|
||||
const WORKPLACE_COLLABORATION_VIEWS = ['workbench', 'organization-directory', 'meeting-organizer', 'meeting-attendee', 'meeting-create', 'meeting-detail', 'daily-report-editor', 'daily-report-mine', 'daily-report-team', 'daily-report-detail', 'monthly-report-editor', 'monthly-report-mine', 'monthly-report-team', 'monthly-report-detail', 'executive-mailbox', 'executive-mailbox-notice'];
|
||||
function Icon({
|
||||
children
|
||||
@@ -20805,7 +20807,7 @@ function Workbench({
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('messages-home'),
|
||||
onClick: () => navigateReplace('messages-home'),
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Icon, {
|
||||
children: "chat_bubble_outline"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
|
||||
@@ -21836,7 +21838,7 @@ function DailyReportList({
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('daily-report-mine'),
|
||||
onClick: () => navigateReplace('daily-report-mine'),
|
||||
children: "我的日报"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("div", {
|
||||
@@ -21883,7 +21885,7 @@ function DailyReportList({
|
||||
children: "我的日报"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('daily-report-team'),
|
||||
onClick: () => navigateReplace('daily-report-team'),
|
||||
children: "团队统计"
|
||||
}, void 0, false)]
|
||||
}, void 0, true) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", {
|
||||
@@ -22178,7 +22180,7 @@ function MonthlyReportList({
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('monthly-report-mine'),
|
||||
onClick: () => navigateReplace('monthly-report-mine'),
|
||||
children: "我的月报"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("div", {
|
||||
@@ -22219,7 +22221,7 @@ function MonthlyReportList({
|
||||
children: "我的月报"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('monthly-report-team'),
|
||||
onClick: () => navigateReplace('monthly-report-team'),
|
||||
children: "团队统计"
|
||||
}, void 0, false)]
|
||||
}, void 0, true) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -46,7 +46,7 @@ class WallpapersView extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureC
|
||||
}
|
||||
handleTabClick(e) {
|
||||
e.preventDefault();
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].navigateReplace(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_2__["default"].addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||
this.setState({
|
||||
tab: e.currentTarget.dataset.id
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user