修复日报/月报详情页返回目标写死,团队视角进入会被送回"我的"列表

DailyReportCard/月报列表的报告条目在 team=true(团队统计)和 team=false(我的日报/月报)两种
模式下渲染的是同一个组件、同一个"查看详情"跳转,但 DailyReportDetail/MonthlyReportDetail
的返回目标写死成 daily-report-mine/monthly-report-mine——管理者从"团队统计"点进某条下属的
报告,返回却被送到自己的"我的日报/月报"而不是刚才浏览的团队列表。跳转时带上 team 参数,
详情页据此选择正确的返回目标,和同文件里 DailyReportList/MonthlyReportList 自己的
`team ? 'x' : 'workbench'` 返回逻辑保持一致模式。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-05 15:20:04 +08:00
co-authored by Claude Sonnet 5
parent 290fc80f3e
commit 5e173c55e8
3 changed files with 26 additions and 13 deletions
+15 -6
View File
@@ -695,7 +695,7 @@ function DailyReportCard({report, names, team}) {
<em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></header> <em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></header>
<p>{report.content_short || '(未填写内容)'}</p> <p>{report.content_short || '(未填写内容)'}</p>
<footer><span><Icon>schedule</Icon>{report.report_date}</span> <footer><span><Icon>schedule</Icon>{report.report_date}</span>
<button type="button" onClick={() => navigate('daily-report-detail', {report_id: report.report_id})}>查看详情<Icon>chevron_right</Icon></button></footer> <button type="button" onClick={() => navigate('daily-report-detail', {report_id: report.report_id, team: team ? '1' : ''})}>查看详情<Icon>chevron_right</Icon></button></footer>
</article>; </article>;
} }
@@ -768,6 +768,11 @@ function DailyReportList({team, myUserId, onToast}) {
function DailyReportDetail({hashParams, myUserId, onToast}) { function DailyReportDetail({hashParams, myUserId, onToast}) {
const reportId = hashParams && hashParams.report_id; const reportId = hashParams && hashParams.report_id;
// DailyReportCard renders identically for DailyReportList's team=true (团队统计) and team=false
// (我的日报) modes and always links here -- backTarget hardcoded to daily-report-mine used to send
// a manager who'd been browsing 团队统计 back to their own report list instead of the team roster
// they'd actually come from.
const backTarget = hashParams && hashParams.team ? 'daily-report-team' : 'daily-report-mine';
const [report, setReport] = React.useState(() => (reportId && readCachedData('daily-report:' + reportId)) || null); const [report, setReport] = React.useState(() => (reportId && readCachedData('daily-report:' + reportId)) || null);
const [loadError, setLoadError] = React.useState(false); const [loadError, setLoadError] = React.useState(false);
const names = useUserNames(report ? [report.author_id] : [], myUserId); const names = useUserNames(report ? [report.author_id] : [], myUserId);
@@ -779,9 +784,9 @@ function DailyReportDetail({hashParams, myUserId, onToast}) {
setReport(readCachedData('daily-report:' + reportId) || null); setReport(readCachedData('daily-report:' + reportId) || null);
getDailyReport(reportId).then(r => { writeCachedData('daily-report:' + reportId, r); setReport(r); }).catch(err => { onToast(err.message || '日报加载失败'); setLoadError(true); }); getDailyReport(reportId).then(r => { writeCachedData('daily-report:' + reportId, r); setReport(r); }).catch(err => { onToast(err.message || '日报加载失败'); setLoadError(true); });
}, [reportId]); }, [reportId]);
if (!report) return <div className="workplace-page"><Header title="查看详情" back="daily-report-mine" /><main><p className="organization-loading">{loadError ? '日报加载失败' : '加载中…'}</p></main></div>; if (!report) return <div className="workplace-page"><Header title="查看详情" back={backTarget} /><main><p className="organization-loading">{loadError ? '日报加载失败' : '加载中…'}</p></main></div>;
return <div className="workplace-page"><Header title="查看详情" back="daily-report-mine" /> return <div className="workplace-page"><Header title="查看详情" back={backTarget} />
<main className="report-detail"> <main className="report-detail">
<section className="report-author"><span><strong>{names[report.author_id] || '…'}</strong><small className="role-badge">员工</small></span> <section className="report-author"><span><strong>{names[report.author_id] || '…'}</strong><small className="role-badge">员工</small></span>
<em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></section> <em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></section>
@@ -953,7 +958,7 @@ function MonthlyReportList({team, myUserId, onToast}) {
{reports == null ? <p className="organization-loading">加载中…</p> : {reports == null ? <p className="organization-loading">加载中…</p> :
filtered.length === 0 ? <p className="organization-loading">{loadError ? '月报列表加载失败' : '暂无月报'}</p> : filtered.length === 0 ? <p className="organization-loading">{loadError ? '月报列表加载失败' : '暂无月报'}</p> :
filtered.map(r => <button type="button" key={r.report_id} filtered.map(r => <button type="button" key={r.report_id}
onClick={() => navigate((r.action || (r.status === 'submitted' ? 'view' : 'edit')) === 'view' ? 'monthly-report-detail' : 'monthly-report-editor', {report_id: r.report_id})}> onClick={() => navigate((r.action || (r.status === 'submitted' ? 'view' : 'edit')) === 'view' ? 'monthly-report-detail' : 'monthly-report-editor', {report_id: r.report_id, team: team ? '1' : ''})}>
<span className="report-month"><Icon>calendar_month</Icon></span> <span className="report-month"><Icon>calendar_month</Icon></span>
<span><strong>{team ? (names[r.author_id] || r.author_id) : formatMonthLabel(r.month)}</strong> <span><strong>{team ? (names[r.author_id] || r.author_id) : formatMonthLabel(r.month)}</strong>
<small>{team ? formatMonthLabel(r.month) : '工作总结与下月计划'}</small></span> <small>{team ? formatMonthLabel(r.month) : '工作总结与下月计划'}</small></span>
@@ -967,6 +972,10 @@ function MonthlyReportList({team, myUserId, onToast}) {
function MonthlyReportDetail({hashParams, myUserId, onToast}) { function MonthlyReportDetail({hashParams, myUserId, onToast}) {
const reportId = hashParams && hashParams.report_id; const reportId = hashParams && hashParams.report_id;
// Same fix as DailyReportDetail's backTarget: the list row that links here renders identically for
// team=true (团队统计) and team=false (我的月报), so a hardcoded 'monthly-report-mine' sent a manager
// who'd been browsing 团队统计 back to their own list instead of the team roster they came from.
const backTarget = hashParams && hashParams.team ? 'monthly-report-team' : 'monthly-report-mine';
const [report, setReport] = React.useState(() => (reportId && readCachedData('monthly-report:' + reportId)) || null); const [report, setReport] = React.useState(() => (reportId && readCachedData('monthly-report:' + reportId)) || null);
const [loadError, setLoadError] = React.useState(false); const [loadError, setLoadError] = React.useState(false);
const [reopening, setReopening] = React.useState(false); const [reopening, setReopening] = React.useState(false);
@@ -977,7 +986,7 @@ function MonthlyReportDetail({hashParams, myUserId, onToast}) {
setReport(readCachedData('monthly-report:' + reportId) || null); setReport(readCachedData('monthly-report:' + reportId) || null);
getMonthlyReport(reportId).then(r => { writeCachedData('monthly-report:' + reportId, r); setReport(r); }).catch(err => { onToast(err.message || '月报加载失败'); setLoadError(true); }); getMonthlyReport(reportId).then(r => { writeCachedData('monthly-report:' + reportId, r); setReport(r); }).catch(err => { onToast(err.message || '月报加载失败'); setLoadError(true); });
}, [reportId]); }, [reportId]);
if (!report) return <div className="workplace-page"><Header title="查看详情" back="monthly-report-mine" /><main><p className="organization-loading">{loadError ? '月报加载失败' : '加载中…'}</p></main></div>; if (!report) return <div className="workplace-page"><Header title="查看详情" back={backTarget} /><main><p className="organization-loading">{loadError ? '月报加载失败' : '加载中…'}</p></main></div>;
// reopenMonthlyReport is self-service only (server keys the UPDATE off the caller's own uid -- // reopenMonthlyReport is self-service only (server keys the UPDATE off the caller's own uid --
// see the comment on the im-api.js export), so this button only ever makes sense for the report's // see the comment on the im-api.js export), so this button only ever makes sense for the report's
@@ -991,7 +1000,7 @@ function MonthlyReportDetail({hashParams, myUserId, onToast}) {
.finally(() => setReopening(false)); .finally(() => setReopening(false));
}; };
return <div className="workplace-page"><Header title="查看详情" back="monthly-report-mine" /> return <div className="workplace-page"><Header title="查看详情" back={backTarget} />
<main className="report-detail"> <main className="report-detail">
<section className="report-author"><span><strong>{names[report.author_id] || '…'}</strong><small className="role-badge">员工</small></span> <section className="report-author"><span><strong>{names[report.author_id] || '…'}</strong><small className="role-badge">员工</small></span>
<em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></section> <em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></section>
+10 -6
View File
@@ -21600,7 +21600,8 @@ function DailyReportCard({
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", { }, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
type: "button", type: "button",
onClick: () => navigate('daily-report-detail', { onClick: () => navigate('daily-report-detail', {
report_id: report.report_id report_id: report.report_id,
team: team ? '1' : ''
}), }),
children: ["查看详情", (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Icon, { children: ["查看详情", (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Icon, {
children: "chevron_right" children: "chevron_right"
@@ -21741,6 +21742,7 @@ function DailyReportDetail({
onToast onToast
}) { }) {
const reportId = hashParams && hashParams.report_id; const reportId = hashParams && hashParams.report_id;
const backTarget = hashParams && hashParams.team ? 'daily-report-team' : 'daily-report-mine';
const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('daily-report:' + reportId) || null); const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('daily-report:' + reportId) || null);
const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false); const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
const names = useUserNames(report ? [report.author_id] : [], myUserId); const names = useUserNames(report ? [report.author_id] : [], myUserId);
@@ -21759,7 +21761,7 @@ function DailyReportDetail({
className: "workplace-page", className: "workplace-page",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
title: "查看详情", title: "查看详情",
back: "daily-report-mine" back: backTarget
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", { }, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", {
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", { children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
className: "organization-loading", className: "organization-loading",
@@ -21771,7 +21773,7 @@ function DailyReportDetail({
className: "workplace-page", className: "workplace-page",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
title: "查看详情", title: "查看详情",
back: "daily-report-mine" back: backTarget
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", { }, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", {
className: "report-detail", className: "report-detail",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", {
@@ -22064,7 +22066,8 @@ function MonthlyReportList({
}, void 0, false) : filtered.map(r => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", { }, void 0, false) : filtered.map(r => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
type: "button", type: "button",
onClick: () => navigate((r.action || (r.status === 'submitted' ? 'view' : 'edit')) === 'view' ? 'monthly-report-detail' : 'monthly-report-editor', { onClick: () => navigate((r.action || (r.status === 'submitted' ? 'view' : 'edit')) === 'view' ? 'monthly-report-detail' : 'monthly-report-editor', {
report_id: r.report_id report_id: r.report_id,
team: team ? '1' : ''
}), }),
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
className: "report-month", className: "report-month",
@@ -22094,6 +22097,7 @@ function MonthlyReportDetail({
onToast onToast
}) { }) {
const reportId = hashParams && hashParams.report_id; const reportId = hashParams && hashParams.report_id;
const backTarget = hashParams && hashParams.team ? 'monthly-report-team' : 'monthly-report-mine';
const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('monthly-report:' + reportId) || null); const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('monthly-report:' + reportId) || null);
const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false); const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
const [reopening, setReopening] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false); const [reopening, setReopening] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
@@ -22113,7 +22117,7 @@ function MonthlyReportDetail({
className: "workplace-page", className: "workplace-page",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
title: "查看详情", title: "查看详情",
back: "monthly-report-mine" back: backTarget
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", { }, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", {
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", { children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
className: "organization-loading", className: "organization-loading",
@@ -22133,7 +22137,7 @@ function MonthlyReportDetail({
className: "workplace-page", className: "workplace-page",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
title: "查看详情", title: "查看详情",
back: "monthly-report-mine" back: backTarget
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", { }, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("main", {
className: "report-detail", className: "report-detail",
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", { children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", {
+1 -1
View File
File diff suppressed because one or more lines are too long