diff --git a/apps/admin-web/src/admin.css b/apps/admin-web/src/admin.css
index b8bc382..f312640 100644
--- a/apps/admin-web/src/admin.css
+++ b/apps/admin-web/src/admin.css
@@ -74,6 +74,50 @@ body.admin-col-resizing * {
user-select: none !important;
}
+/* 列表页顶栏:标题左、主操作右、列设置最右 */
+.admin-list-header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 16px;
+ margin-bottom: 16px;
+}
+
+.admin-list-header-left {
+ min-width: 0;
+}
+
+.admin-list-header-desc {
+ margin-top: 4px;
+ color: rgba(0, 0, 0, 0.45);
+ line-height: 1.5;
+}
+
+.admin-list-header-right {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 8px;
+ flex-shrink: 0;
+ margin-left: auto;
+}
+
+.admin-list-settings-slot {
+ display: inline-flex;
+ margin-left: auto;
+ order: 99;
+ flex-shrink: 0;
+}
+
+.admin-list-settings-btn.ant-btn {
+ color: rgba(0, 0, 0, 0.55);
+ padding-inline: 8px;
+}
+
+.admin-list-settings-btn.ant-btn:hover {
+ color: rgba(0, 0, 0, 0.88);
+}
+
/* 操作列保持可见 */
.admin-layout .ant-table-cell:has(.ant-btn),
.ant-drawer .ant-table-cell:has(.ant-btn),
diff --git a/apps/admin-web/src/components/AdminListHeader.tsx b/apps/admin-web/src/components/AdminListHeader.tsx
new file mode 100644
index 0000000..983143a
--- /dev/null
+++ b/apps/admin-web/src/components/AdminListHeader.tsx
@@ -0,0 +1,36 @@
+import type { ReactNode } from 'react';
+import { Space, Typography } from 'antd';
+
+/** 列表页顶栏:标题在左,主操作在右,列设置永远最右 */
+export function AdminListHeader({
+ title,
+ description,
+ actions,
+ settings,
+}: {
+ title?: ReactNode;
+ description?: ReactNode;
+ actions?: ReactNode;
+ settings?: ReactNode;
+}) {
+ return (
+
+
+ {title == null || title === '' ? null : typeof title === 'string' || typeof title === 'number' ? (
+
+ {title}
+
+ ) : (
+ title
+ )}
+ {description ? (
+
{description}
+ ) : null}
+
+
+ {actions ? {actions} : null}
+ {settings}
+
+
+ );
+}
diff --git a/apps/admin-web/src/lib/useAdminListColumns.tsx b/apps/admin-web/src/lib/useAdminListColumns.tsx
index 46e3f1c..ac0ebb3 100644
--- a/apps/admin-web/src/lib/useAdminListColumns.tsx
+++ b/apps/admin-web/src/lib/useAdminListColumns.tsx
@@ -153,9 +153,11 @@ export function useAdminListColumns(
}, [configured, serialCol, pref?.widths, localWidths, persistWidth]);
const settingsButton = (
- } onClick={() => setOpen(true)}>
- 列设置
-
+
+ } className="admin-list-settings-btn" onClick={() => setOpen(true)}>
+ 列设置
+
+
);
const settingsModal = (
diff --git a/apps/admin-web/src/pages/BenefitCouponsPage.tsx b/apps/admin-web/src/pages/BenefitCouponsPage.tsx
index 4ed800e..19e4b31 100644
--- a/apps/admin-web/src/pages/BenefitCouponsPage.tsx
+++ b/apps/admin-web/src/pages/BenefitCouponsPage.tsx
@@ -23,6 +23,7 @@ import { COUPON_STATUS_LABELS, DELIVERY_TYPE_LABELS, fmtTime } from '../lib/cons
import RedeemRecordDetailDescriptions from '../components/RedeemRecordDetailDescriptions';
import { useAdminList } from '../lib/useAdminList';
import { useAdminListColumns } from '../lib/useAdminListColumns';
+import { AdminListHeader } from '../components/AdminListHeader';
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';
type CouponOrder = {
@@ -248,17 +249,15 @@ export default function BenefitCouponsPage() {
return (
{settingsModal}
-
-
- 好客权益券
-
-
- {settingsButton}
+ setGrantOpen(true)}>
手动发放
-
-
+ }
+ />
diff --git a/apps/admin-web/src/pages/BenefitLedgersPage.tsx b/apps/admin-web/src/pages/BenefitLedgersPage.tsx
index 588434f..028335f 100644
--- a/apps/admin-web/src/pages/BenefitLedgersPage.tsx
+++ b/apps/admin-web/src/pages/BenefitLedgersPage.tsx
@@ -4,6 +4,7 @@ import type { ColumnsType } from 'antd/es/table';
import { LEDGER_TYPE_LABELS, fmtTime } from '../lib/constants';
import { useAdminList } from '../lib/useAdminList';
import { useAdminListColumns } from '../lib/useAdminListColumns';
+import { AdminListHeader } from '../components/AdminListHeader';
type Row = {
@@ -41,8 +42,7 @@ export default function BenefitLedgersPage() {
return (
{settingsModal}
-
权益流水
- {settingsButton}
+
diff --git a/apps/admin-web/src/pages/CitiesPage.tsx b/apps/admin-web/src/pages/CitiesPage.tsx
index efbe032..b1dc8ff 100644
--- a/apps/admin-web/src/pages/CitiesPage.tsx
+++ b/apps/admin-web/src/pages/CitiesPage.tsx
@@ -25,6 +25,7 @@ import { useAdminList } from '../lib/useAdminList';
import CityPartnersPanel from '../components/CityPartnersPanel';
import ChinaProvinceCityCascader from '../components/ChinaProvinceCityCascader';
import { useAdminListColumns } from '../lib/useAdminListColumns';
+import { AdminListHeader } from '../components/AdminListHeader';
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';
@@ -326,11 +327,11 @@ export default function CitiesPage() {
return (
{settingsModal}
-
- 城市
- {settingsButton}
-
-
+
新建城市}
+ />
diff --git a/apps/admin-web/src/pages/CityPartnersPage.tsx b/apps/admin-web/src/pages/CityPartnersPage.tsx
index 24b10b7..d97ea96 100644
--- a/apps/admin-web/src/pages/CityPartnersPage.tsx
+++ b/apps/admin-web/src/pages/CityPartnersPage.tsx
@@ -37,6 +37,7 @@ import { useAdminList } from '../lib/useAdminList';
import CityDistrictMultiSelect from '../components/CityDistrictMultiSelect';
import PartnerSubAccountList, { type PartnerSubAccountRow } from '../components/PartnerSubAccountList';
import { useAdminListColumns } from '../lib/useAdminListColumns';
+import { AdminListHeader } from '../components/AdminListHeader';
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';
@@ -350,29 +351,29 @@ export default function CityPartnersPage() {
return (
{settingsModal}
-
-
- 城市合伙人
-
- {settingsButton}
-
-
+
{
+ createForm.resetFields();
+ createForm.setFieldsValue({
+ orderCommissionRate: 0,
+ redeemCommissionRate: 3,
+ scopeType: CityPartnerScopeType.CITY_WIDE,
+ });
+ setCreateScopeType(CityPartnerScopeType.CITY_WIDE);
+ setCreateMaxRate(0.05);
+ setCreateCityCode(undefined);
+ setCreateOpen(true);
+ }}
+ >
+ 新建合伙人
+
+ }
+ />
{settingsModal}
-
- 仓库
- {settingsButton}
-
-
+ {
+ createForm.resetFields();
+ setCreateManagerType(WarehouseManagerType.HQ);
+ setCreateCityId(undefined);
+ setCreateFulfillmentMode(WarehouseFulfillmentMode.MANUAL);
+ createForm.setFieldsValue({
+ managerType: WarehouseManagerType.HQ,
+ status: WarehouseStatus.ACTIVE,
+ fulfillmentMode: WarehouseFulfillmentMode.MANUAL,
+ });
+ setCreateOpen(true);
+ }}
+ >
+ 新增仓库
+
+ }
+ />
v || '—' },
+ {
+ title: '运费',
+ dataIndex: 'logisticsFee',
+ width: 90,
+ render: (v: number | null | undefined) => (v == null ? '—' : `¥${Number(v).toFixed(2)}`),
+ },
{ title: '第三方单号', dataIndex: 'providerOrderNo', width: 140, render: (v) => v || '—' },
{ title: '订单状态', dataIndex: ['order', 'status'], width: 100, render: (s) => ORDER_STATUS_LABELS[s] || s },
{ title: '收货人', dataIndex: ['order', 'receiverName'], width: 90 },
@@ -107,8 +116,7 @@ export default function DeliveriesPage() {
return (