import Add from "@mui/icons-material/Add"; import CategoryOutlined from "@mui/icons-material/CategoryOutlined"; import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined"; import EditOutlined from "@mui/icons-material/EditOutlined"; import Inventory2Outlined from "@mui/icons-material/Inventory2Outlined"; import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined"; import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx"; import TextField from "@mui/material/TextField"; import { AdminFormDialog, AdminFormFieldGrid, AdminFormInlineActions, AdminFormList, AdminFormListRow, AdminFormSection, AdminFormSwitchField, } 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 { AdminActionIconButton, AdminListBody, AdminListPage, AdminListToolbar, AdminRowActions, } from "@/shared/ui/AdminListLayout.jsx"; import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js"; import { formatMillis } from "@/shared/utils/time.js"; import { ResourceSelectField } from "@/features/resources/components/ResourceSelectDrawer.jsx"; import { resourceGroupAssetLabels, resourceStatusFilters, resourceTypeLabels } from "@/features/resources/constants.js"; import { useResourceGroupListPage } from "@/features/resources/hooks/useResourcePages.js"; import styles from "@/features/resources/resources.module.css"; const dayMillis = 24 * 60 * 60 * 1000; const baseColumns = [ { key: "group", label: "资源组", width: "minmax(260px, 1.5fr)", render: (group) => , }, { key: "items", label: "组内资源", width: "minmax(320px, 1.7fr)", render: (group) => , }, { key: "sort", label: "排序", width: "minmax(80px, 0.45fr)", render: (group) => group.sortOrder ?? 0, }, { key: "status", label: "状态", width: "minmax(92px, 0.55fr)", }, { key: "time", label: "更新时间", width: "minmax(170px, 0.9fr)", render: (group) => formatMillis(group.updatedAtMs || group.createdAtMs), }, { key: "actions", label: "操作", width: "minmax(76px, 0.4fr)", }, ]; export function ResourceGroupListPage() { const page = useResourceGroupListPage(); const items = page.data.items || []; const total = page.data.total || 0; const columns = baseColumns.map((column) => column.key === "group" ? { ...column, filter: createTextColumnFilter({ placeholder: "搜索资源组名称、资源组编码", value: page.query, onChange: page.changeQuery, }), } : column.key === "status" ? { ...column, filter: createOptionsColumnFilter({ options: resourceStatusFilters, placeholder: "搜索状态", value: page.status, onChange: page.changeStatus, }), render: (group) => , } : column.key === "actions" ? { ...column, render: (group) => , } : column, ); return ( ) : null } /> 0 ? { page: page.page, pageSize: page.data.pageSize || 50, total, onPageChange: page.setPage, } : undefined } rowKey={(group) => group.groupId} /> ); } function ResourceGroupRowActions({ group, page }) { return ( page.openEditGroup(group)} > ); } function ResourceGroupStatusSwitch({ group, page }) { const checked = group.status === "active"; return ( page.toggleGroup(group, event.target.checked)} /> ); } function ResourceGroupFormDialog({ disabled, form, loading, mode, onClose, onSubmit, open, page }) { const submitDisabled = disabled || loading || page.resourceOptionsLoading; return ( page.setForm({ ...form, name: event.target.value })} /> page.setForm({ ...form, groupCode: event.target.value })} /> page.setForm({ ...form, sortOrder: event.target.value })} /> page.setForm({ ...form, description: event.target.value })} /> page.setForm({ ...form, enabled: checked })} /> } > {form.items.map((item, index) => ( ))} ); } function ResourceGroupItemEditor({ disabled, index, item, page }) { if (item.itemType === "wallet_asset") { const label = resourceGroupAssetLabels[item.walletAssetType] || "钱包资产"; return ( page.updateGroupItem(index, { walletAssetAmount: event.target.value })} /> page.updateGroupItem(index, { sortOrder: event.target.value })} /> page.removeGroupItem(index)}> ); } return ( page.updateGroupItem(index, { resourceId })} /> page.updateGroupItem(index, { durationDays: event.target.value })} /> page.updateGroupItem(index, { sortOrder: event.target.value })} /> page.removeGroupItem(index)}> ); } function GroupIdentity({ group }) { return (
{group.name || "-"} {group.groupCode || group.groupId}
); } function GroupItems({ group }) { const items = group.items || []; if (!items.length) { return "-"; } return (
{items.slice(0, 4).map((item) => { if (item.itemType === "wallet_asset") { const label = resourceGroupAssetLabels[item.walletAssetType] || item.walletAssetType || "钱包资产"; return ( {label} {formatNumber(item.walletAssetAmount)} ); } const resource = item.resource || {}; const type = resourceTypeLabels[resource.resourceType] || resource.resourceType || "资源"; return ( {resource.name || item.resourceId} · {formatDurationDays(item.durationMs)}天 · {type} ); })} {items.length > 4 ? +{items.length - 4} : null}
); } function formatDurationDays(durationMs) { const days = Number(durationMs || 0) / dayMillis; return Number.isInteger(days) ? days : days.toFixed(1); } function formatNumber(value) { return Number(value || 0).toLocaleString("zh-CN"); }