2026-05-29 19:56:45 +08:00

272 lines
9.4 KiB
JavaScript

import Add from "@mui/icons-material/Add";
import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined";
import EditOutlined from "@mui/icons-material/EditOutlined";
import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import {
AdminActionIconButton,
AdminFilterResetButton,
AdminFilterSelect,
AdminListBody,
AdminListToolbar,
} from "@/shared/ui/AdminListLayout.jsx";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { formatMillis } from "@/shared/utils/time.js";
import { TeamSalaryPolicyDrawer } from "@/features/host-agency-policy/components/TeamSalaryPolicyDrawer.jsx";
import { useTeamSalaryPolicyPage } from "@/features/host-agency-policy/hooks/useTeamSalaryPolicyPage.js";
import styles from "@/features/host-agency-policy/host-agency-policy.module.css";
const statusOptions = [
["", "全部状态"],
["active", "启用"],
["disabled", "停用"],
];
const settlementTriggerOptions = [
["", "全部触发"],
["automatic", "自动结算"],
["manual", "手动结算"],
];
const columnsBase = [
{
key: "policy",
label: "政策",
width: "minmax(260px, 1.2fr)",
render: (item, _rowIndex, context) => (
<PolicyIdentity item={item} policyType={context.policyType} regionLabels={context.regionLabels} />
),
},
{
key: "settlement",
label: "触发与周期",
width: "minmax(180px, 0.8fr)",
render: (item) => <SettlementSummary item={item} />,
},
{
key: "levels",
label: "等级",
width: "minmax(220px, 0.95fr)",
render: (item, _rowIndex, context) => <LevelSummary item={item} policyType={context.policyType} />,
},
{
key: "effective",
label: "生效时间",
width: "minmax(220px, 1fr)",
render: (item) => <EffectiveTime item={item} />,
},
{
key: "status",
label: "状态",
width: "minmax(110px, 0.5fr)",
},
{
key: "updatedAt",
label: "更新时间",
width: "minmax(170px, 0.75fr)",
render: (item) => formatMillis(item.updatedAtMs || item.createdAtMs),
},
{
key: "actions",
label: "操作",
width: "112px",
resizable: false,
},
];
export function TeamSalaryPolicyPanel({ policyType }) {
const page = useTeamSalaryPolicyPage(policyType);
const items = page.data.items || [];
const total = page.data.total || 0;
const regionFilterOptions = [["", "全部区域"], ...page.regionOptions.map((region) => [region.value, region.label])];
const columns = columnsBase.map((column) => {
if (column.key === "policy") {
return {
...column,
filter: createTextColumnFilter({
placeholder: "搜索政策名称",
value: page.query,
onChange: page.changeQuery,
}),
};
}
if (column.key === "settlement") {
return {
...column,
filter: createOptionsColumnFilter({
options: settlementTriggerOptions,
placeholder: "搜索触发方式",
value: page.settlementTriggerMode,
onChange: page.changeSettlementTriggerMode,
}),
};
}
if (column.key === "status") {
return {
...column,
filter: createOptionsColumnFilter({
options: statusOptions,
placeholder: "搜索状态",
value: page.status,
onChange: page.changeStatus,
}),
render: (item) => <PolicyStatusSwitch item={item} page={page} />,
};
}
if (column.key === "actions") {
return {
...column,
render: (item) => <PolicyActions item={item} page={page} />,
};
}
return column;
});
return (
<>
<AdminListToolbar
actions={
page.abilities.canTeamCreate ? (
<AdminActionIconButton
label={`新增${policyTitle(policyType)}政策`}
primary
onClick={page.openCreate}
>
<Add fontSize="small" />
</AdminActionIconButton>
) : null
}
filters={
<div className={styles.toolbarFilters}>
<AdminFilterSelect
label="区域"
options={regionFilterOptions}
value={page.regionId}
onChange={page.changeRegionId}
/>
<AdminFilterResetButton
disabled={!page.query && !page.regionId && !page.status && !page.settlementTriggerMode}
onClick={page.resetFilters}
/>
</div>
}
/>
<DataState error={page.error} loading={page.loading} onRetry={page.reload}>
<AdminListBody>
<DataTable
columns={columns}
context={{ policyType, regionLabels: page.regionLabels }}
items={items}
minWidth="1240px"
pagination={
total > 0
? {
page: page.page,
pageSize: page.data.pageSize || 50,
total,
onPageChange: page.setPage,
}
: undefined
}
rowKey={(item) => item.id}
/>
</AdminListBody>
</DataState>
<TeamSalaryPolicyDrawer page={page} />
</>
);
}
function PolicyIdentity({ item, policyType, regionLabels }) {
const labels = regionLabels || {};
return (
<div className={styles.stack}>
<span className={styles.name}>{item.name}</span>
<span className={styles.meta}>
{policyTitle(policyType)} · {labels[item.regionId] || `区域 ${item.regionId}`}
</span>
</div>
);
}
function SettlementSummary({ item }) {
return (
<div className={styles.stack}>
<span>{settlementTriggerLabel(item.settlementTriggerMode)}</span>
<span className={styles.meta}>完整自然月</span>
<span className={styles.meta}>次月 5 日可结算</span>
</div>
);
}
function LevelSummary({ item, policyType }) {
const first = item.levels?.[0];
const last = item.levels?.[item.levels.length - 1];
return (
<div className={styles.stack}>
<span>{item.levels?.length || 0} 个等级</span>
<span className={styles.meta}>
{first && last ? `$${first.thresholdUsd} - $${last.thresholdUsd} ${thresholdUnit(policyType)}` : "-"}
</span>
<span className={styles.meta}>{last ? `最高工资 $${last.salaryUsd}` : ""}</span>
</div>
);
}
function EffectiveTime({ item }) {
return (
<div className={styles.stack}>
<span>{item.effectiveFromMs ? formatMillis(item.effectiveFromMs) : "立即生效"}</span>
<span className={styles.meta}>{item.effectiveToMs ? formatMillis(item.effectiveToMs) : "长期有效"}</span>
</div>
);
}
function PolicyStatusSwitch({ item, page }) {
const disabled = !page.abilities.canTeamUpdate || page.loadingAction === `team-policy-status-${item.id}`;
return (
<AdminSwitch
checked={item.status === "active"}
checkedLabel="启用"
disabled={disabled}
label="切换政策状态"
uncheckedLabel="停用"
onChange={(event) => page.togglePolicyStatus(item, event.target.checked)}
/>
);
}
function PolicyActions({ item, page }) {
return (
<div className={styles.rowActions}>
<AdminActionIconButton
disabled={!page.abilities.canTeamUpdate}
label="编辑工资政策"
onClick={() => page.openEdit(item)}
>
<EditOutlined fontSize="small" />
</AdminActionIconButton>
<AdminActionIconButton
disabled={!page.abilities.canTeamDelete || page.loadingAction === `team-policy-delete-${item.id}`}
label="删除工资政策"
onClick={() => page.removePolicy(item)}
>
<DeleteOutlineOutlined fontSize="small" />
</AdminActionIconButton>
</div>
);
}
function policyTitle(policyType) {
return policyType === "bd" ? "BD" : "Admin";
}
function thresholdUnit(policyType) {
return policyType === "bd" ? "主播工资" : "BD工资";
}
function settlementTriggerLabel(value) {
return settlementTriggerOptions.find(([mode]) => mode === value)?.[1] || value || "-";
}