import AddOutlined from "@mui/icons-material/AddOutlined";
import CloseOutlined from "@mui/icons-material/CloseOutlined";
import MeetingRoomOutlined from "@mui/icons-material/MeetingRoomOutlined";
import PersonOutlineOutlined from "@mui/icons-material/PersonOutlineOutlined";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import { Button } from "@/shared/ui/Button.jsx";
import { AdminFormDialog } from "@/shared/ui/AdminFormDialog.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { IconButton } from "@/shared/ui/IconButton.jsx";
import { AdminFilterResetButton } from "@/shared/ui/AdminListLayout.jsx";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { createRegionColumnFilter } from "@/shared/ui/RegionFilterControl.jsx";
import { formatMillis } from "@/shared/utils/time.js";
import { useRoomPinsPage } from "@/features/rooms/hooks/useRoomPinsPage.js";
import styles from "@/features/rooms/rooms.module.css";
const pinStatusOptions = [
{ label: "有效", value: "active" },
{ label: "已过期", value: "expired" },
{ label: "已取消", value: "cancelled" },
{ label: "全部", value: "all" },
];
const columns = [
{
key: "room",
label: "房间信息",
width: "minmax(280px, 1.5fr)",
render: (pin) => ,
},
{
key: "user",
label: "用户信息",
width: "minmax(240px, 1.2fr)",
render: (pin) => ,
},
{
key: "region",
label: "区域",
width: "minmax(140px, 0.7fr)",
render: (pin) => pin.room?.regionName || (pin.room?.visibleRegionId ? `区域 ${pin.room.visibleRegionId}` : "-"),
},
{
key: "weight",
label: "权重",
width: "minmax(100px, 0.5fr)",
render: (pin) => Number(pin.weight || 0).toLocaleString("zh-CN"),
},
{
key: "remaining",
label: "剩余时间",
width: "minmax(150px, 0.8fr)",
render: (pin) => formatRemaining(pin),
},
{
key: "expiresAt",
label: "到期时间",
width: "minmax(170px, 0.9fr)",
render: (pin) => formatMillis(pin.expiresAtMs),
},
];
export function RoomPinsPage() {
const page = useRoomPinsPage();
const items = page.data.items || [];
const total = page.data.total || 0;
const tableColumns = [
...columns.map((column) =>
column.key === "room"
? {
...column,
filter: createTextColumnFilter({
placeholder: "搜索房间 ID",
value: page.query,
onChange: page.changeQuery,
}),
}
: column.key === "region"
? {
...column,
filter: createRegionColumnFilter({
loading: page.loadingRegions,
options: page.regionOptions,
value: page.regionId,
onChange: page.changeRegionId,
}),
}
: column.key === "remaining"
? {
...column,
filter: createOptionsColumnFilter({
options: pinStatusOptions,
placeholder: "置顶状态",
value: page.status,
onChange: page.changeStatus,
}),
}
: column,
),
{
key: "actions",
label: "操作",
width: "minmax(104px, 0.6fr)",
render: (pin) => ,
},
];
return (
{page.abilities.canPinCreate ? (
} variant="primary" onClick={page.openCreate}>
新增置顶
) : null}
pin.id}
pagination={
total > 0
? {
page: page.page,
pageSize: page.data.pageSize || 50,
total,
onPageChange: page.setPage,
}
: undefined
}
/>
options}
getOptionLabel={(option) => roomOptionLabel(option)}
isOptionEqualToValue={(option, value) => option.roomId === value.roomId}
loading={page.roomOptionsLoading}
noOptionsText="当前无数据"
inputValue={page.roomInput}
options={page.roomOptions}
renderInput={(params) => (
)}
renderOption={(props, option) => (
)}
size="small"
value={page.selectedRoom}
onChange={(_, option) => page.selectRoom(option)}
onInputChange={(_, value, reason) => {
if (reason === "input") {
page.changeRoomInput(value);
}
if (reason === "clear") {
page.selectRoom(null);
}
}}
/>
page.setForm({ ...page.form, weight: event.target.value })}
/>
page.setForm({ ...page.form, durationDays: event.target.value })}
/>
);
}
function PinRoomIdentity({ room = {} }) {
return (
{room.coverUrl ?
: }
{room.title || "-"}
长ID {room.roomId || "-"}
短ID {room.roomShortId || "-"}
);
}
function PinUserIdentity({ user = {} }) {
return (
{user.avatar ?
: }
{user.username || "-"}
长ID {user.userId || "-"}
短ID {user.displayUserId || "-"}
);
}
function RoomPinActions({ page, pin }) {
const canCancel = page.abilities.canPinCancel && pin.status === "active" && Number(pin.remainingMs || 0) > 0;
if (!canCancel) {
return -;
}
return (
page.cancelPin(pin)}
>
);
}
function roomOptionLabel(room) {
if (!room) {
return "";
}
return [room.title, room.roomShortId, room.roomId].filter(Boolean).join(" / ");
}
function formatRemaining(pin) {
if (pin.status === "cancelled") {
return "-";
}
const ms = Number(pin.remainingMs || 0);
if (ms <= 0) {
return "0天";
}
const dayMs = 24 * 60 * 60 * 1000;
const days = Math.floor(ms / dayMs);
const hours = Math.floor((ms % dayMs) / (60 * 60 * 1000));
if (days > 0) {
return `${days}天${hours > 0 ? `${hours}小时` : ""}`;
}
return `${Math.max(hours, 1)}小时`;
}