fix: 优化后台工单工作区布局
This commit is contained in:
@@ -304,7 +304,7 @@ export default function AdminLayout() {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box component="main" sx={{ flexGrow: 1, p: { xs: 2, md: 3 }, minWidth: 0 }}>
|
<Box component="main" sx={{ flex: '1 1 auto', width: { xs: '100%', md: 'calc(100vw - 240px)' }, maxWidth: { xs: '100%', md: 'calc(100vw - 240px)' }, boxSizing: 'border-box', p: { xs: 2, md: 3 }, minWidth: 0, overflowX: 'hidden' }}>
|
||||||
{/* AppBar 占位:桌面 64 / 移动 56 + 搜索行 48 */}
|
{/* AppBar 占位:桌面 64 / 移动 56 + 搜索行 48 */}
|
||||||
<Box sx={{ height: isMobile ? 104 : 64 }} />
|
<Box sx={{ height: isMobile ? 104 : 64 }} />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|||||||
@@ -146,13 +146,13 @@ export default function TicketManage() {
|
|||||||
], [stats, total]);
|
], [stats, total]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box component="main" aria-labelledby="ticket-page-title">
|
<Box component="main" className="ticket-workspace" aria-labelledby="ticket-page-title">
|
||||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 2 }}>
|
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 2 }}>
|
||||||
<Box><Typography id="ticket-page-title" variant="h5" component="h1">工单管理</Typography><Typography variant="body2" color="text.secondary">集中处理论坛和站内问题反馈</Typography></Box>
|
<Box><Typography id="ticket-page-title" variant="h5" component="h1">工单管理</Typography><Typography variant="body2" color="text.secondary">集中处理论坛和站内问题反馈</Typography></Box>
|
||||||
<IconButton aria-label="刷新工单" title="刷新" onClick={refresh} disabled={loading || saving}><RefreshIcon /></IconButton>
|
<IconButton aria-label="刷新工单" title="刷新" onClick={refresh} disabled={loading || saving}><RefreshIcon /></IconButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack direction="row" spacing={1.25} useFlexGap flexWrap="wrap" sx={{ mb: 2 }}>
|
<Stack className="ticket-stats" direction="row" spacing={1.25} useFlexGap flexWrap="wrap" sx={{ mb: 2 }}>
|
||||||
{statItems.map(([label, value, tone]) => <StatCard key={label} label={label} value={value} tone={tone} />)}
|
{statItems.map(([label, value, tone]) => <StatCard key={label} label={label} value={value} tone={tone} />)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
@@ -167,8 +167,8 @@ export default function TicketManage() {
|
|||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
{error && <Alert severity="error" role="alert" action={<Button color="inherit" size="small" onClick={loadList}>重试</Button>} sx={{ mb: 2 }}>{error}</Alert>}
|
{error && <Alert severity="error" role="alert" action={<Button color="inherit" size="small" onClick={loadList}>重试</Button>} sx={{ mb: 2 }}>{error}</Alert>}
|
||||||
<Grid container spacing={2} alignItems="stretch">
|
<Box className="ticket-work-area">
|
||||||
<Grid item xs={12} lg={5} sx={{ minWidth: 0 }}>
|
<Box className="ticket-list-pane">
|
||||||
<Paper variant="outlined" sx={{ height: '100%', overflow: 'hidden' }}>
|
<Paper variant="outlined" sx={{ height: '100%', overflow: 'hidden' }}>
|
||||||
<Box sx={{ p: 1.5, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}><Typography variant="subtitle1" fontWeight={700}>最近工单</Typography><Typography variant="caption" color="text.secondary">共 {total} 条</Typography></Box>
|
<Box sx={{ p: 1.5, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}><Typography variant="subtitle1" fontWeight={700}>最近工单</Typography><Typography variant="caption" color="text.secondary">共 {total} 条</Typography></Box>
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -179,9 +179,9 @@ export default function TicketManage() {
|
|||||||
)}
|
)}
|
||||||
<Stack direction="row" alignItems="center" justifyContent="center" spacing={1} sx={{ p: 1.25 }}><IconButton aria-label="上一页" size="small" disabled={page <= 1 || loading} onClick={() => setPage(page - 1)}><NavigateBeforeIcon /></IconButton><Typography variant="caption">第 {page} / {totalPages} 页</Typography><IconButton aria-label="下一页" size="small" disabled={page >= totalPages || loading} onClick={() => setPage(page + 1)}><NavigateNextIcon /></IconButton></Stack>
|
<Stack direction="row" alignItems="center" justifyContent="center" spacing={1} sx={{ p: 1.25 }}><IconButton aria-label="上一页" size="small" disabled={page <= 1 || loading} onClick={() => setPage(page - 1)}><NavigateBeforeIcon /></IconButton><Typography variant="caption">第 {page} / {totalPages} 页</Typography><IconButton aria-label="下一页" size="small" disabled={page >= totalPages || loading} onClick={() => setPage(page + 1)}><NavigateNextIcon /></IconButton></Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Box>
|
||||||
|
|
||||||
<Grid item xs={12} lg={7} sx={{ minWidth: 0 }}>
|
<Box className="ticket-detail-pane">
|
||||||
<Paper variant="outlined" sx={{ p: { xs: 2, md: 2.5 }, minHeight: 420 }}>
|
<Paper variant="outlined" sx={{ p: { xs: 2, md: 2.5 }, minHeight: 420 }}>
|
||||||
{!selectedId ? <Box sx={{ py: 10, textAlign: 'center' }}><Typography variant="h6" color="text.secondary">选择一个工单开始处理</Typography><Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>工单详情、回复和状态操作会显示在这里</Typography></Box> : detailLoading ? <Box role="status" aria-label="正在加载工单详情" sx={{ py: 10, textAlign: 'center' }}><CircularProgress /></Box> : selectedTicket ? (
|
{!selectedId ? <Box sx={{ py: 10, textAlign: 'center' }}><Typography variant="h6" color="text.secondary">选择一个工单开始处理</Typography><Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>工单详情、回复和状态操作会显示在这里</Typography></Box> : detailLoading ? <Box role="status" aria-label="正在加载工单详情" sx={{ py: 10, textAlign: 'center' }}><CircularProgress /></Box> : selectedTicket ? (
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
@@ -194,8 +194,8 @@ export default function TicketManage() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
) : <Alert severity="error">工单详情不存在或加载失败。</Alert>}
|
) : <Alert severity="error">工单详情不存在或加载失败。</Alert>}
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Box>
|
||||||
</Grid>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,77 @@ body {
|
|||||||
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #49454f; }
|
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #49454f; }
|
||||||
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #938f99; }
|
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #938f99; }
|
||||||
|
|
||||||
|
/* 工单工作区:占满 AdminLayout 内容区,桌面保持列表/详情主次比例。 */
|
||||||
|
.ticket-workspace {
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: calc(100vh - 112px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-workspace .ticket-stats {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-work-area {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(280px, 0.55fr) minmax(0, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: calc(100vh - 280px);
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-list-pane,
|
||||||
|
.ticket-detail-pane {
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-list-pane > .MuiPaper-root,
|
||||||
|
.ticket-detail-pane > .MuiPaper-root {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-list-pane > .MuiPaper-root {
|
||||||
|
min-height: calc(100vh - 280px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-detail-pane > .MuiPaper-root {
|
||||||
|
min-height: calc(100vh - 280px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1199px) and (min-width: 700px) {
|
||||||
|
.ticket-work-area {
|
||||||
|
grid-template-columns: minmax(250px, 0.62fr) minmax(0, 1fr);
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 699px) {
|
||||||
|
.ticket-workspace {
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-work-area {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
min-height: 0;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-list-pane > .MuiPaper-root,
|
||||||
|
.ticket-detail-pane > .MuiPaper-root {
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-detail-pane > .MuiPaper-root {
|
||||||
|
min-height: 480px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 减弱动效偏好 */
|
/* 减弱动效偏好 */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
*, *::before, *::after {
|
*, *::before, *::after {
|
||||||
|
|||||||
Reference in New Issue
Block a user