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 ? (
}
onClick={() => page.openGenerate(null)}
>
批量生成
) : null}
{page.abilities.canPrettyUpdate ? (
}
variant="primary"
onClick={page.openCreatePool}
>
新增池
) : null}
>
}
count={page.poolQuery.data.total}
title="靓号池"
/>
page.changePoolTrack(event.target.value)}
>
{prettyLevelTrackOptions.map(([value, label]) => (
))}
page.changePoolStatus(event.target.value)}
>
{prettyPoolStatusOptions.map(([value, label]) => (
))}
} onClick={page.resetPoolFilters}>
重置
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) => (
))}
page.changeIDSource(event.target.value)}
>
{prettyIdSourceOptions.map(([value, label]) => (
))}
page.changeIDStatus(event.target.value)}
>
{prettyIdStatusOptions.map(([value, label]) => (
))}
page.changeAssignedUserId(event.target.value)}
/>
} onClick={page.resetIDFilters}>
重置
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) ? (
) : (
"-"
),
},
];
}
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]) => (
))}
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]) => (
))}
page.setPoolForm({ ...page.poolForm, status: event.target.value })}
>
{prettyPoolStatusOptions
.filter(([value]) => value)
.map(([value, 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) => (
))}
page.setGenerateForm({ ...page.generateForm, ruleType: event.target.value })}
>
{prettyRuleOptions.map(([value, 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]) => (
))}
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;
}