272 lines
9.4 KiB
JavaScript
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 || "-";
|
|
}
|