import Add from "@mui/icons-material/Add";
import EditOutlined from "@mui/icons-material/EditOutlined";
import Inventory2Outlined from "@mui/icons-material/Inventory2Outlined";
import FormControlLabel from "@mui/material/FormControlLabel";
import MenuItem from "@mui/material/MenuItem";
import Switch from "@mui/material/Switch";
import TextField from "@mui/material/TextField";
import { AdminFormDialog } from "@/shared/ui/AdminFormDialog.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { UploadField } from "@/shared/ui/UploadField.jsx";
import {
AdminActionIconButton,
AdminFilterResetButton,
AdminListBody,
AdminListPage,
AdminRowActions,
AdminListToolbar,
} from "@/shared/ui/AdminListLayout.jsx";
import { PaginationBar } from "@/shared/ui/PaginationBar.jsx";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { formatMillis } from "@/shared/utils/time.js";
import {
grantStrategyLabels,
resourceStatusFilters,
resourceTypeFilters,
resourceTypeLabels,
} from "@/features/resources/constants.js";
import { useResourceListPage } from "@/features/resources/hooks/useResourcePages.js";
import styles from "@/features/resources/resources.module.css";
const resourceTypeOptions = resourceTypeFilters.filter(([value]) => value);
const baseColumns = [
{
key: "resource",
label: "资源",
width: "minmax(260px, 1.5fr)",
render: (resource) => ,
},
{
key: "type",
label: "类型",
width: "minmax(120px, 0.7fr)",
render: (resource) => resourceTypeLabels[resource.resourceType] || resource.resourceType || "-",
},
{
key: "grant",
label: "发放规则",
width: "minmax(170px, 1fr)",
render: (resource) => ,
},
{
key: "scopes",
label: "使用范围",
width: "minmax(180px, 1fr)",
render: (resource) => ,
},
{
key: "status",
label: "状态",
width: "minmax(92px, 0.55fr)",
},
{
key: "time",
label: "更新时间",
width: "minmax(170px, 0.9fr)",
render: (resource) => formatMillis(resource.updatedAtMs || resource.createdAtMs),
},
{
key: "actions",
label: "操作",
width: "minmax(76px, 0.4fr)",
},
];
export function ResourceListPage() {
const page = useResourceListPage();
const items = page.data.items || [];
const total = page.data.total || 0;
const createDisabled = !page.abilities.canCreate || !page.abilities.canUpload;
const columns = baseColumns.map((column) =>
column.key === "resource"
? {
...column,
filter: createTextColumnFilter({
placeholder: "搜索资源名称、资源编码",
value: page.query,
onChange: page.changeQuery,
}),
}
: column.key === "type"
? {
...column,
filter: createOptionsColumnFilter({
options: resourceTypeFilters,
placeholder: "搜索类型",
value: page.resourceType,
onChange: page.changeResourceType,
}),
}
: column.key === "status"
? {
...column,
filter: createOptionsColumnFilter({
options: resourceStatusFilters,
placeholder: "搜索状态",
value: page.status,
onChange: page.changeStatus,
}),
render: (resource) => ,
}
: column.key === "actions"
? {
...column,
render: (resource) => ,
}
: column,
);
return (
}
actions={
page.abilities.canCreate ? (
) : null
}
/>
resource.resourceId}
/>
{total > 0 ? (
) : null}
);
}
function ResourceRowActions({ page, resource }) {
return (
page.openEditResource(resource)}
>
);
}
function ResourceFormDialog({ disabled, form, loading, mode, onClose, onSubmit, open, setForm, uploadDisabled }) {
const submitDisabled = disabled || loading;
return (
setForm({ ...form, name: event.target.value })}
/>
setForm({ ...form, resourceCode: event.target.value })}
/>
setForm({ ...form, resourceType: event.target.value, walletAssetAmount: "" })}
>
{resourceTypeOptions.map(([value, label]) => (
))}
{form.resourceType === "coin" ? (
setForm({ ...form, walletAssetAmount: event.target.value })}
/>
) : null}
setForm({ ...form, previewUrl })}
/>
setForm({ ...form, assetUrl })}
/>
setForm({ ...form, enabled: event.target.checked })}
/>
}
label={form.enabled ? "启用" : "禁用"}
/>
);
}
function ResourceIdentity({ resource }) {
const preview = imageURL(resource.previewUrl || resource.assetUrl);
return (
{preview ?
: }
{resource.name || "-"}
{resource.resourceCode || resource.resourceId}
);
}
function GrantInfo({ resource }) {
const strategy = grantStrategyLabels[resource.grantStrategy] || resource.grantStrategy || "-";
if (resource.walletAssetType || resource.walletAssetAmount) {
return (
{strategy}
{resource.walletAssetType || "-"} {formatNumber(resource.walletAssetAmount)}
);
}
return strategy;
}
function ResourceStatusSwitch({ page, resource }) {
const checked = resource.status === "active";
return (
page.toggleResource(resource, event.target.checked)}
/>
);
}
function TagList({ values = [] }) {
const items = values.filter(Boolean);
if (!items.length) {
return "-";
}
return (
{items.map((value) => (
{value}
))}
);
}
function imageURL(value) {
const url = String(value || "").trim();
if (!url) {
return "";
}
return /\.(avif|gif|jpe?g|png|webp)(\?|#|$)/i.test(url) ? url : "";
}
function formatNumber(value) {
return Number(value || 0).toLocaleString("zh-CN");
}