import AddCircleOutlineOutlined from "@mui/icons-material/AddCircleOutlineOutlined"; import AutoAwesomeOutlined from "@mui/icons-material/AutoAwesomeOutlined"; import EditOutlined from "@mui/icons-material/EditOutlined"; import RestartAltOutlined from "@mui/icons-material/RestartAltOutlined"; import SendOutlined from "@mui/icons-material/SendOutlined"; import SettingsOutlined from "@mui/icons-material/SettingsOutlined"; import MenuItem from "@mui/material/MenuItem"; import TextField from "@mui/material/TextField"; import Tooltip from "@mui/material/Tooltip"; import { AdminFormDialog, AdminFormSection } from "@/shared/ui/AdminFormDialog.jsx"; import { Button } from "@/shared/ui/Button.jsx"; import { DataState } from "@/shared/ui/DataState.jsx"; import { DataTable } from "@/shared/ui/DataTable.jsx"; import { IconButton } from "@/shared/ui/IconButton.jsx"; import { useAppUserDetail } from "@/features/app-users/components/AppUserDetailContext.jsx"; import { formatMillis } from "@/shared/utils/time.js"; import { prettyIdSourceLabels, prettyIdSourceOptions, prettyIdStatusLabels, prettyIdStatusOptions, prettyLevelTrackOptions, prettyPoolStatusLabels, prettyPoolStatusOptions, prettyRuleOptions, } from "@/features/app-users/constants.js"; import { usePrettyIdsPage } from "@/features/app-users/hooks/usePrettyIdsPage.js"; import styles from "@/features/app-users/app-users.module.css"; export function AppUserPrettyIdsPage() { const page = usePrettyIdsPage(); const pools = page.poolQuery.data.items || []; const prettyIds = page.idQuery.data.items || []; return (
{page.abilities.canPrettyGenerate ? ( ) : null} {page.abilities.canPrettyUpdate ? ( ) : null} } count={page.poolQuery.data.total} title="靓号池" />
page.changePoolTrack(event.target.value)} > 全部等级轨道 {prettyLevelTrackOptions.map(([value, label]) => ( {label} ))} page.changePoolStatus(event.target.value)} > {prettyPoolStatusOptions.map(([value, label]) => ( {label} ))}
0 ? { page: page.poolPage, pageSize: page.poolQuery.data.pageSize || 20, total: page.poolQuery.data.total, onPageChange: page.setPoolPage, } : undefined } rowKey={(pool) => pool.poolId} />
} variant="primary" onClick={page.openGrant} > 后台发放 ) : null } count={page.idQuery.data.total} title="靓号列表" />
page.changeIDKeyword(event.target.value)} /> page.changeIDPool(event.target.value)} > 全部靓号池 {page.poolOptions.map((option) => ( {option.label} ))} page.changeIDSource(event.target.value)} > {prettyIdSourceOptions.map(([value, label]) => ( {label} ))} page.changeIDStatus(event.target.value)} > {prettyIdStatusOptions.map(([value, label]) => ( {label} ))} page.changeAssignedUserId(event.target.value)} />
0 ? { page: page.idPage, pageSize: page.idQuery.data.pageSize || 20, total: page.idQuery.data.total, onPageChange: page.setIdPage, } : undefined } rowKey={(item) => item.prettyId} />
); } function PaneHeader({ actions, count, title }) { return (

{title}

共 {Number(count || 0)} 条
{actions}
); } function poolColumns(page) { return [ { key: "pool", label: "靓号池", width: "minmax(220px, 1.2fr)", render: (pool) => (
{pool.name || "-"} {pool.poolId} 更新 {formatMillis(pool.updatedAtMs || pool.createdAtMs)}
), }, { key: "rule", label: "规则 / 等级", width: "minmax(160px, 0.9fr)", render: (pool) => (
{ruleLabel(pool.ruleType)} {trackLabel(pool.levelTrack)} {pool.minLevel}-{pool.maxLevel}
), }, { key: "status", label: "状态", width: "minmax(110px, 0.6fr)", render: (pool) => , }, { key: "actions", label: "操作", width: "104px", render: (pool) => (
{page.abilities.canPrettyUpdate ? ( page.openEditPool(pool)}> ) : null} {page.abilities.canPrettyGenerate ? ( page.openGenerate(pool)}> ) : null}
), }, ]; } function idColumns(page) { return [ { key: "display", label: "靓号", width: "minmax(190px, 1fr)", render: (item) => (
{item.displayUserId || "-"}
{item.prettyId}
), }, { key: "pool", label: "来源 / 池", width: "minmax(180px, 0.9fr)", render: (item) => (
{prettyIdSourceLabels[item.source] || item.source || "-"} {item.pool?.name || item.poolId || "-"}
), }, { key: "status", label: "状态", width: "minmax(110px, 0.6fr)", render: (item) => , }, { key: "assigned", label: "占用 / 时间", width: "minmax(190px, 0.9fr)", render: (item) => (
{item.assignedAtMs ? formatMillis(item.assignedAtMs) : formatMillis(item.createdAtMs)} {item.releasedAtMs ? `释放 ${formatMillis(item.releasedAtMs)}` : "-"}
), }, { key: "actions", label: "操作", width: "minmax(96px, 0.5fr)", render: (item) => page.abilities.canPrettyUpdate && canChangePrettyStatus(item) ? (
page.openStatus(item)}>
) : ( "-" ), }, ]; } function AssignedUserCell({ item }) { const { openAppUserDetail } = useAppUserDetail(); const assignedUserId = formatEntityID(item.assignedUserId); if (!item.assignedUserId || !openAppUserDetail) { return {assignedUserId}; } return ( ); } function PoolDialog({ page }) { const editing = Boolean(page.activePool); return ( page.setPoolForm({ ...page.poolForm, name: event.target.value })} /> page.setPoolForm({ ...page.poolForm, levelTrack: event.target.value })} > {prettyLevelTrackOptions.map(([value, label]) => ( {label} ))}
page.setPoolForm({ ...page.poolForm, minLevel: event.target.value })} /> page.setPoolForm({ ...page.poolForm, maxLevel: event.target.value })} />
page.setPoolForm({ ...page.poolForm, ruleType: event.target.value })} > {prettyRuleOptions.map(([value, label]) => ( {label} ))} page.setPoolForm({ ...page.poolForm, status: event.target.value })} > {prettyPoolStatusOptions .filter(([value]) => value) .map(([value, label]) => ( {label} ))}
page.setPoolForm({ ...page.poolForm, sortOrder: event.target.value })} /> page.setPoolForm({ ...page.poolForm, ruleConfigJson: event.target.value })} />
); } function GenerateDialog({ page }) { return ( page.setGenerateForm({ ...page.generateForm, poolId: event.target.value })} > {page.poolOptions.map((option) => ( {option.label} ))} page.setGenerateForm({ ...page.generateForm, ruleType: event.target.value })} > {prettyRuleOptions.map(([value, label]) => ( {label} ))} page.setGenerateForm({ ...page.generateForm, count: event.target.value })} /> page.setGenerateForm({ ...page.generateForm, ruleConfigJson: event.target.value }) } /> ); } function GrantDialog({ page }) { return ( page.setGrantForm({ ...page.grantForm, targetUserId: event.target.value })} /> page.setGrantForm({ ...page.grantForm, displayUserId: event.target.value })} /> page.setGrantForm({ ...page.grantForm, durationDays: event.target.value })} /> page.setGrantForm({ ...page.grantForm, reason: event.target.value })} /> ); } function StatusDialog({ page }) { return ( page.setStatusForm({ ...page.statusForm, status: event.target.value })} > {prettyIdStatusOptions .filter(([value]) => ["available", "disabled", "reserved"].includes(value)) .map(([value, label]) => ( {label} ))} page.setStatusForm({ ...page.statusForm, reason: event.target.value })} /> ); } function ActionIcon({ children, label, onClick }) { return ( {children} ); } function StatusBadge({ labels, status }) { return ( {labels[status] || status || "-"} ); } function statusTone(status) { if (status === "active" || status === "available") { return "running"; } if (status === "assigned" || status === "reserved") { return "warning"; } if (status === "released" || status === "deleted") { return "stopped"; } return "danger"; } function trackLabel(track) { return prettyLevelTrackOptions.find(([value]) => value === track)?.[1] || track || "-"; } function ruleLabel(ruleType) { return prettyRuleOptions.find(([value]) => value === ruleType)?.[1] || ruleType || "-"; } function formatEntityID(value) { if (value === 0 || value === "0" || value === "" || value === undefined || value === null) { return "-"; } return String(value); } function canChangePrettyStatus(item) { const assigned = item.assignedUserId; const unassigned = assigned === 0 || assigned === "0" || assigned === "" || assigned === undefined || assigned === null; return ["available", "disabled", "reserved"].includes(item.status) && unassigned; }