diff --git a/apps/admin-web/src/admin.css b/apps/admin-web/src/admin.css
index 42e62cd..cd49eea 100644
--- a/apps/admin-web/src/admin.css
+++ b/apps/admin-web/src/admin.css
@@ -15,10 +15,74 @@ body,
display: none;
}
-.admin-table-nowrap .ant-table-cell {
+/*
+ * 后台内容行:不换行 + 超出省略
+ * 覆盖主内容区、Drawer、Modal 内的表格与描述列表
+ */
+.admin-layout .ant-table-cell,
+.ant-drawer .ant-table-cell,
+.ant-modal .ant-table-cell,
+.admin-layout .ant-descriptions-item-content,
+.ant-drawer .ant-descriptions-item-content,
+.ant-modal .ant-descriptions-item-content {
white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 0;
}
+.admin-layout .ant-descriptions-item-content,
+.ant-drawer .ant-descriptions-item-content,
+.ant-modal .ant-descriptions-item-content {
+ max-width: 100%;
+}
+
+/* 表头同样不换行 */
+.admin-layout .ant-table-thead > tr > th,
+.ant-drawer .ant-table-thead > tr > th,
+.ant-modal .ant-table-thead > tr > th {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* 操作列、含交互控件的不截断 */
+.admin-layout .ant-table-cell:has(.ant-btn),
+.ant-drawer .ant-table-cell:has(.ant-btn),
+.ant-modal .ant-table-cell:has(.ant-btn),
+.admin-layout .ant-table-cell:has(.ant-space),
+.ant-drawer .ant-table-cell:has(.ant-space),
+.ant-modal .ant-table-cell:has(.ant-space) {
+ overflow: visible;
+ text-overflow: clip;
+ max-width: none;
+}
+
+/* 代码块、表单区域保持原样 */
+.admin-layout pre,
+.ant-drawer pre,
+.ant-modal pre,
+.admin-layout .ant-form-item-control-input,
+.ant-drawer .ant-form-item-control-input,
+.ant-modal .ant-form-item-control-input {
+ white-space: pre-wrap;
+ overflow: auto;
+ text-overflow: unset;
+ max-width: none;
+}
+
+/* 表格单元格双行信息合并为单行省略 */
+.admin-cell-line {
+ display: block;
+ max-width: 100%;
+}
+
+.admin-cell-line-secondary {
+ color: rgba(0, 0, 0, 0.45);
+ font-size: 12px;
+}
+
+.admin-table-nowrap .ant-table-cell,
.admin-table-nowrap .ant-table-cell-ellipsis {
white-space: nowrap;
}
diff --git a/apps/admin-web/src/components/AdminCellLine.tsx b/apps/admin-web/src/components/AdminCellLine.tsx
new file mode 100644
index 0000000..ab210df
--- /dev/null
+++ b/apps/admin-web/src/components/AdminCellLine.tsx
@@ -0,0 +1,34 @@
+import { Typography } from 'antd';
+
+type AdminCellLineProps = {
+ primary?: string | null;
+ secondary?: string | null;
+ separator?: string;
+};
+
+/** 表格单元格:主/副信息同一行展示,超出省略,hover 显示全文 */
+export function AdminCellLine({
+ primary,
+ secondary,
+ separator = ' · ',
+}: AdminCellLineProps) {
+ const main = primary?.trim() || '—';
+ const sub = secondary?.trim();
+ const full = sub ? `${main}${separator}${sub}` : main;
+
+ return (
+
+ {main}
+ {sub ? (
+
+ {separator}
+ {sub}
+
+ ) : null}
+
+ );
+}
diff --git a/apps/admin-web/src/layouts/AdminLayout.tsx b/apps/admin-web/src/layouts/AdminLayout.tsx
index 5a71690..139d7b1 100644
--- a/apps/admin-web/src/layouts/AdminLayout.tsx
+++ b/apps/admin-web/src/layouts/AdminLayout.tsx
@@ -16,6 +16,7 @@ import {
FileTextOutlined,
} from '@ant-design/icons';
import { clearAuth, request, type HqProfile } from '../lib/api';
+import { bindAdminEllipsisTitle } from '../lib/ellipsis-title';
const { Header, Sider, Content } = Layout;
@@ -105,6 +106,10 @@ export default function AdminLayout() {
contentRef.current?.scrollTo({ top: 0, left: 0 });
}, [location.pathname]);
+ useEffect(() => {
+ return bindAdminEllipsisTitle();
+ }, []);
+
function logout() {
clearAuth();
navigate('/login');
@@ -164,6 +169,7 @@ export default function AdminLayout() {
diff --git a/apps/admin-web/src/lib/ellipsis-title.ts b/apps/admin-web/src/lib/ellipsis-title.ts
new file mode 100644
index 0000000..82d6045
--- /dev/null
+++ b/apps/admin-web/src/lib/ellipsis-title.ts
@@ -0,0 +1,37 @@
+const ELLIPSIS_TARGETS =
+ '.ant-table-cell, .ant-descriptions-item-content, .ant-typography';
+
+const ELLIPSIS_SKIP =
+ '.ant-btn, .ant-input, .ant-select, .ant-picker, .ant-checkbox, .ant-radio, pre, textarea, input, select, button, a.ant-btn';
+
+function isTruncated(el: HTMLElement): boolean {
+ return el.scrollWidth > el.clientWidth + 1;
+}
+
+function resolveEllipsisElement(target: EventTarget | null): HTMLElement | null {
+ if (!(target instanceof HTMLElement)) return null;
+ const cell = target.closest(ELLIPSIS_TARGETS);
+ if (!cell) return null;
+ if (cell.closest('.admin-cell-line')) return null;
+ if (cell.closest(ELLIPSIS_SKIP)) return null;
+ if (cell.querySelector(ELLIPSIS_SKIP)) return null;
+ return cell;
+}
+
+export function bindAdminEllipsisTitle(root: HTMLElement | Document = document) {
+ const onMouseOver = (event: MouseEvent) => {
+ const el = resolveEllipsisElement(event.target);
+ if (!el) return;
+ if (isTruncated(el)) {
+ const text = el.innerText.replace(/\s+/g, ' ').trim();
+ if (text && el.getAttribute('title') !== text) {
+ el.setAttribute('title', text);
+ }
+ } else {
+ el.removeAttribute('title');
+ }
+ };
+
+ root.addEventListener('mouseover', onMouseOver, true);
+ return () => root.removeEventListener('mouseover', onMouseOver, true);
+}
diff --git a/apps/admin-web/src/pages/HqLogsPage.tsx b/apps/admin-web/src/pages/HqLogsPage.tsx
index 16c32b9..bf552e5 100644
--- a/apps/admin-web/src/pages/HqLogsPage.tsx
+++ b/apps/admin-web/src/pages/HqLogsPage.tsx
@@ -5,6 +5,7 @@ import {
import type { ColumnsType } from 'antd/es/table';
import { useSearchParams } from 'react-router-dom';
import { request } from '../lib/api';
+import { AdminCellLine } from '../components/AdminCellLine';
import { fmtTime } from '../lib/constants';
import { HQ_OPERATION_ACTION_OPTIONS, resolveHqOperationLabel } from '../lib/hq-log';
import { useAdminList } from '../lib/useAdminList';
@@ -55,14 +56,13 @@ export default function HqLogsPage() {
{ title: '时间', dataIndex: 'createdAt', width: 160, render: fmtTime },
{
title: '操作人',
- width: 160,
+ width: 200,
+ ellipsis: true,
render: (_, r) => (
-
-
{r.hqName || '—'}
-
- {r.hqPhone || ''} {r.hqAccountId ? `(#${r.hqAccountId})` : ''}
-
-
+
),
},
{
@@ -170,7 +170,10 @@ export default function HqLogsPage() {
{detail.id}
{fmtTime(detail.createdAt)}
- {detail.hqName} / {detail.hqPhone} (ID: {detail.hqAccountId})
+
{detail.hqRole || '—'}
diff --git a/apps/admin-web/src/pages/PartnerLogsPage.tsx b/apps/admin-web/src/pages/PartnerLogsPage.tsx
index 9580874..02ba7a8 100644
--- a/apps/admin-web/src/pages/PartnerLogsPage.tsx
+++ b/apps/admin-web/src/pages/PartnerLogsPage.tsx
@@ -9,6 +9,7 @@ import {
type PartnerLogCategory,
} from '../lib/partner-log';
import { request } from '../lib/api';
+import { AdminCellLine } from '../components/AdminCellLine';
import { fmtTime } from '../lib/constants';
import { useAdminList } from '../lib/useAdminList';
@@ -71,21 +72,20 @@ export default function PartnerLogsPage() {
{
title: '合伙人',
width: 180,
+ ellipsis: true,
render: (_, r) => (
-
-
{r.companyName || '—'}
-
{r.partnerId}
-
+
),
},
{
title: '账号',
width: 150,
+ ellipsis: true,
render: (_, r) => (
-
-
{r.accountName || '—'}
-
{r.accountPhone || r.partnerAccountId || '—'}
-
+
),
},
{
diff --git a/apps/admin-web/src/pages/StoreLogsPage.tsx b/apps/admin-web/src/pages/StoreLogsPage.tsx
index 5f9e193..99fb995 100644
--- a/apps/admin-web/src/pages/StoreLogsPage.tsx
+++ b/apps/admin-web/src/pages/StoreLogsPage.tsx
@@ -9,6 +9,7 @@ import {
type StoreLogCategory,
} from '../lib/store-log';
import { request } from '../lib/api';
+import { AdminCellLine } from '../components/AdminCellLine';
import { fmtTime } from '../lib/constants';
import { useAdminList } from '../lib/useAdminList';
@@ -82,21 +83,16 @@ export default function StoreLogsPage() {
const columns: ColumnsType = [
{ title: '时间', dataIndex: 'createdAt', width: 160, render: fmtTime },
{
- title: '门店', width: 180,
- render: (_, r) => (
-
-
{r.storeName || '—'}
-
{r.storeId}
-
- ),
+ title: '门店', width: 180, ellipsis: true,
+ render: (_, r) => ,
},
{
- title: '账号', width: 150,
+ title: '账号', width: 150, ellipsis: true,
render: (_, r) => (
-
-
{r.accountName || '—'}
-
{r.accountPhone || r.storeAccountId || '系统/HQ'}
-
+
),
},
{
diff --git a/apps/admin-web/src/pages/UserLogsPage.tsx b/apps/admin-web/src/pages/UserLogsPage.tsx
index 7073bb5..c66044e 100644
--- a/apps/admin-web/src/pages/UserLogsPage.tsx
+++ b/apps/admin-web/src/pages/UserLogsPage.tsx
@@ -4,6 +4,7 @@ import type { ColumnsType } from 'antd/es/table';
import { USER_LOG_CATEGORY_OPTIONS, resolveUserLogCategory, USER_LOG_CATEGORY_LABELS, type UserLogCategory } from '../lib/user-log';
import { useSearchParams } from 'react-router-dom';
import { request } from '../lib/api';
+import { AdminCellLine } from '../components/AdminCellLine';
import { fmtTime } from '../lib/constants';
import { useAdminList } from '../lib/useAdminList';
@@ -63,12 +64,12 @@ export default function UserLogsPage() {
const columns: ColumnsType = [
{ title: '时间', dataIndex: 'createdAt', width: 160, render: fmtTime },
{
- title: '用户', width: 160,
+ title: '用户', width: 180, ellipsis: true,
render: (_, r) => (
-
-
{r.nickname || r.userNo || '—'}
-
{r.phone || r.userId || '—'}
-
+
),
},
{