import { useMemo, useState } from "react";
import { AdminFilterResetButton, AdminFilterSelect, AdminListToolbar, AdminSearchBox } from "@/shared/ui/AdminListLayout.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { TimeText } from "@/shared/ui/TimeText.jsx";
import { OpsStatusBadge } from "./OpsStatusBadge.jsx";
export function AppsView({ apps }) {
const [keyword, setKeyword] = useState("");
const [status, setStatus] = useState("");
// 应用主数据总量很小(个位数),筛选全部在前端完成,不回源。
const items = useMemo(() => {
const normalizedKeyword = keyword.trim().toLowerCase();
return apps.filter((item) => {
const code = String(item.app_code ?? item.appCode ?? "").toLowerCase();
const name = String(item.app_name ?? item.appName ?? "").toLowerCase();
if (normalizedKeyword && !code.includes(normalizedKeyword) && !name.includes(normalizedKeyword)) {
return false;
}
if (status && String(item.status || "").toLowerCase() !== status) {
return false;
}
return true;
});
}, [apps, keyword, status]);
return (
{
setKeyword("");
setStatus("");
}}
/>
>
}
/>
item.app_code ?? item.appCode}
title="应用列表"
total={items.length}
/>
);
}
const appColumns = [
{ key: "app_code", label: "应用编码", render: (item) => item.app_code ?? item.appCode, width: "minmax(100px, 0.8fr)" },
{ key: "app_name", label: "应用名称", render: (item) => item.app_name ?? item.appName },
{ key: "platform", label: "平台", render: (item) => item.platform || "-", width: "minmax(80px, 0.6fr)" },
{ key: "package_name", label: "包名", render: (item) => item.package_name ?? item.packageName ?? "-", width: "minmax(180px, 1.4fr)" },
{
key: "status",
label: "状态",
render: (item) =>
String(item.status || "").toLowerCase() === "active" ? (
) : (
),
width: "minmax(112px, 0.6fr)"
},
{
key: "source",
label: "来源",
// fixed 来源是 admin-server 为外部幸运礼物接入硬编码补齐的白名单 App(yumi/aslan),
// 不在 app registry 主数据里,运营需要知道它们没有包名/平台等完整信息。
render: (item) =>
item.source === "fixed" ? : ,
width: "minmax(124px, 0.7fr)"
},
{
key: "updated_at_ms",
label: "更新时间",
render: (item) => (item.source === "fixed" ? "-" : ),
width: "minmax(150px, 1fr)"
}
];