Some checks failed
Build and Release / Build (push) Has been cancelled
- 去掉所有 Link search 中的 String() 包装(7处),修复 URL 引号问题 - View Owner 改用 useNavigate 强制导航,解决同页面跳转不生效 - 设备组详情成员列表添加 auth_type Badge 和 device_type Badge - 设备组列表 owner 列统一为 [AUTH_TYPE Badge] + identifier 格式 - UserDetail 组件统一设备标识逻辑,去掉 shortenDeviceIdentifier Co-Authored-By: claude-flow <ruv@ruv.net>
150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
import { Badge } from "@workspace/ui/components/badge";
|
|
import { Button } from "@workspace/ui/components/button";
|
|
import {
|
|
ProTable,
|
|
type ProTableActions,
|
|
} from "@workspace/ui/composed/pro-table/pro-table";
|
|
import { getFamilyList } from "@workspace/ui/services/admin/user";
|
|
import { useRef } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { formatDate } from "@/utils/common";
|
|
import { getFamilyStatusLabel, isFamilyStatusActive } from "./enums";
|
|
import { FamilyDetailSheet } from "./family-detail-sheet";
|
|
|
|
interface FamilyManagementProps {
|
|
initialFamilyId?: number;
|
|
initialUserId?: number;
|
|
onChanged?: () => void;
|
|
}
|
|
|
|
export default function FamilyManagement({
|
|
initialFamilyId,
|
|
initialUserId,
|
|
onChanged,
|
|
}: Readonly<FamilyManagementProps>) {
|
|
const { t } = useTranslation("user");
|
|
const ref = useRef<ProTableActions>(null);
|
|
|
|
const initialFilters = {
|
|
family_id: initialFamilyId || undefined,
|
|
user_id: initialUserId || undefined,
|
|
};
|
|
|
|
return (
|
|
<ProTable<API.FamilySummary, API.GetFamilyListParams>
|
|
action={ref}
|
|
actions={{
|
|
render: (row) => [
|
|
<FamilyDetailSheet
|
|
familyId={row.family_id}
|
|
key={`detail-${row.family_id}`}
|
|
onChanged={() => {
|
|
ref.current?.refresh();
|
|
onChanged?.();
|
|
}}
|
|
trigger={<Button>{t("familyDetail", "Family Detail")}</Button>}
|
|
/>,
|
|
],
|
|
}}
|
|
columns={[
|
|
{
|
|
accessorKey: "family_id",
|
|
header: t("familyId", "Family ID"),
|
|
},
|
|
{
|
|
accessorKey: "owner_identifier",
|
|
header: t("owner", "Owner"),
|
|
cell: ({ row }) => (
|
|
<div className="flex items-center gap-1">
|
|
{row.original.owner_auth_type ? (
|
|
<Badge className="uppercase">
|
|
{row.original.owner_auth_type}
|
|
</Badge>
|
|
) : null}
|
|
<span>{row.original.owner_identifier}</span>
|
|
<span className="text-muted-foreground text-xs">
|
|
(ID: {row.original.owner_user_id})
|
|
</span>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
accessorKey: "status",
|
|
header: t("status", "Status"),
|
|
cell: ({ row }) => {
|
|
const status = row.getValue("status") as string;
|
|
return isFamilyStatusActive(status) ? (
|
|
<Badge>{t("statusActive", "Active")}</Badge>
|
|
) : (
|
|
<Badge variant="secondary">
|
|
{getFamilyStatusLabel(t, status)}
|
|
</Badge>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "active_member_count",
|
|
header: t("memberCount", "Member Count"),
|
|
cell: ({ row }) =>
|
|
`${row.original.active_member_count}/${row.original.max_members}`,
|
|
},
|
|
{
|
|
accessorKey: "max_members",
|
|
header: t("familyMaxMembers", "Max Members"),
|
|
},
|
|
{
|
|
accessorKey: "created_at",
|
|
header: t("createdAt", "Created At"),
|
|
cell: ({ row }) => formatDate(row.getValue("created_at")),
|
|
},
|
|
{
|
|
accessorKey: "updated_at",
|
|
header: t("updatedAt", "Updated At"),
|
|
cell: ({ row }) => formatDate(row.getValue("updated_at")),
|
|
},
|
|
]}
|
|
header={{
|
|
title: t("familyManagement", "Family Group Management"),
|
|
}}
|
|
initialFilters={initialFilters}
|
|
key={String(initialFamilyId || initialUserId || "all")}
|
|
params={[
|
|
{
|
|
key: "keyword",
|
|
placeholder: t("search", "Search"),
|
|
},
|
|
{
|
|
key: "status",
|
|
placeholder: t("status", "Status"),
|
|
options: [
|
|
{ label: getFamilyStatusLabel(t, "active"), value: "active" },
|
|
{ label: getFamilyStatusLabel(t, "disabled"), value: "disabled" },
|
|
],
|
|
},
|
|
{
|
|
key: "owner_user_id",
|
|
placeholder: t("familyOwnerUserId", "Owner User ID"),
|
|
},
|
|
{
|
|
key: "family_id",
|
|
placeholder: t("familyId", "Family ID"),
|
|
},
|
|
{
|
|
key: "user_id",
|
|
placeholder: t("userId", "User ID"),
|
|
},
|
|
]}
|
|
request={async (pagination, filter) => {
|
|
const { data } = await getFamilyList({
|
|
...pagination,
|
|
...filter,
|
|
});
|
|
return {
|
|
list: data.data?.list || [],
|
|
total: data.data?.total || 0,
|
|
};
|
|
}}
|
|
/>
|
|
);
|
|
}
|