diff --git a/src/components/cstb/SteamUsers.tsx b/src/components/cstb/SteamUsers.tsx index 4027802..134ce31 100644 --- a/src/components/cstb/SteamUsers.tsx +++ b/src/components/cstb/SteamUsers.tsx @@ -1,15 +1,41 @@ -import { Refresh, User, FolderFocusOne, Login, Check } from "@icon-park/react" +import { Refresh, User, FolderFocusOne, Login, Check, List, GridFour } from "@icon-park/react" import { Card, CardBody, CardHeader, CardIcon, CardTool } from "../window/Card" -import { addToast, Button, Chip } from "@heroui/react" +import { addToast, Button, Chip, Tabs, Tab, Tooltip } from "@heroui/react" import { useSteamStore } from "@/store/steam" +import { useAppStore } from "@/store/app" import { ToolButton } from "../window/ToolButton" import { useAutoAnimate } from "@formkit/auto-animate/react" import { invoke } from "@tauri-apps/api/core" +import { writeText } from "@tauri-apps/plugin-clipboard-manager" import path from "path" +import { useState, useMemo } from "react" +import type { SteamUser } from "@/types/steam" + +type ViewMode = "card" | "list" | "list-large" const SteamUsers = ({ className }: { className?: string }) => { const steam = useSteamStore() + const app = useAppStore() const [parent /* , enableAnimations */] = useAutoAnimate(/* optional config */) + const viewMode = app.state.steamUsersViewMode as ViewMode + const [mockUsers, setMockUsers] = useState(null) + + // 生成模拟用户数据 + const generateMockUsers = (): SteamUser[] => { + return Array.from({ length: 200 }, (_, i) => ({ + steam_id64: BigInt(76561198000000000 + i), + steam_id32: 1000000 + i, + account_name: `mockuser${i + 1}`, + persona_name: `模拟用户 ${i + 1}`, + recent: i < 3 ? 1 : 0, + avatar: "", + })) + } + + // 使用模拟数据或真实数据 + const displayUsers = useMemo(() => { + return mockUsers || steam.state.users + }, [mockUsers, steam.state.users]) const getUsers = async (toast?: boolean) => { if (!steam.state.steamDirValid) { @@ -21,81 +47,382 @@ const SteamUsers = ({ className }: { className?: string }) => { if (toast) addToast({ title: `已获取Steam用户` }) } + const handleMockToggle = () => { + if (mockUsers) { + setMockUsers(null) + addToast({ title: "已切换回真实数据" }) + } else { + setMockUsers(generateMockUsers()) + addToast({ title: "已切换到模拟数据(200个用户)" }) + } + } + + // 复制到剪贴板的辅助函数 + const handleCopy = async (text: string, label: string) => { + try { + await writeText(text) + addToast({ title: `已复制${label}` }) + } catch (error) { + addToast({ title: "复制失败", color: "danger" }) + } + } + + // 渲染用户项 - 列表-大样式(当前样式) + const renderListLargeItem = (user: SteamUser, id: number, isMock: boolean) => ( +
  • + avatar +
    +

    handleCopy(user.persona_name, "用户名")} + > + {user.persona_name} +

    +
    + handleCopy(user.account_name, "账号名")} + > + {user.account_name} + + handleCopy(user.steam_id32.toString(), "Steam32位ID")} + > + {user.steam_id32} + + handleCopy(user.steam_id64.toString(), "Steam64位ID")} + > + {user.steam_id64.toString()} + + {user.recent > 0 && ( + + 最近登录 + + )} +
    +
    +
    + + + +
    +
  • + ) + + // 渲染用户项 - 列表样式(缩小版) + const renderListItem = (user: SteamUser, id: number, isMock: boolean) => ( +
  • + avatar +
    +
    +

    handleCopy(user.persona_name, "用户名")} + > + {user.persona_name} +

    + {user.recent > 0 && ( + + 最近登录 + + )} +
    +
    + handleCopy(user.account_name, "账号名")} + > + {user.account_name} + + handleCopy(user.steam_id32.toString(), "Steam32位ID")} + > + {user.steam_id32} + + handleCopy(user.steam_id64.toString(), "Steam64位ID")} + > + {user.steam_id64.toString()} + +
    +
    +
    + + + +
    +
  • + ) + + // 渲染用户项 - 卡片样式(grid布局) + const renderCardItem = (user: SteamUser, id: number, isMock: boolean) => ( +
  • +
    + avatar +
    +
    +

    handleCopy(user.persona_name, "用户名")} + > + {user.persona_name} +

    + {user.recent > 0 && ( + + 最近登录 + + )} +
    +

    handleCopy(user.account_name, "账号名")} + > + {user.account_name} +

    +
    +
    +
    + + handleCopy(user.steam_id32.toString(), "Steam32位ID")} + > + {user.steam_id32} + + + + handleCopy(user.steam_id64.toString(), "Steam64位ID")} + > + {user.steam_id64.toString()} + + +
    +
    + + + +
    +
  • + ) + + // 根据视图模式渲染用户项 + const renderUserItem = (user: SteamUser, id: number) => { + const isMock = !!mockUsers + const realIndex = mockUsers + ? -1 + : steam.state.users.findIndex((u) => u.account_name === user.account_name) + const index = realIndex >= 0 ? realIndex : id + + switch (viewMode) { + case "card": + return renderCardItem(user, index, isMock) + case "list": + return renderListItem(user, index, isMock) + case "list-large": + default: + return renderListLargeItem(user, index, isMock) + } + } + return ( - + Steam用户 + + app.setSteamUsersViewMode(key as ViewMode)} + size="sm" + radius="full" + classNames={{ + base: "min-w-0", + tabList: "gap-0 p-0", + tab: "min-w-0 px-2", + tabContent: "text-xs", + }} + > + } /> + } /> + } /> + + + {/* {mockUsers ? "真实" : "模拟"} */} getUsers(true)}> 刷新 - -
      - {steam.state.users.map((user, id) => ( -
    • - avatar -
      -

      {user.persona_name}

      -
      - - {user.account_name} - - - {user.steam_id32} - - - {user.steam_id64.toString()} - - {user.recent > 0 && ( - - 最近登录 - - )} -
      -
      -
      - - - -
      -
    • - ))} -
    + + {viewMode === "card" ? ( +
      + {displayUsers.map((user, id) => renderUserItem(user, id))} +
    + ) : ( +
      + {displayUsers.map((user, id) => renderUserItem(user, id))} +
    + )}
    ) diff --git a/src/store/app.ts b/src/store/app.ts index d3f1cd7..6e3d37b 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -13,6 +13,7 @@ const defaultValue = { autoStart: false, startHidden: false, hiddenOnClose: false, + steamUsersViewMode: "list-large" as "card" | "list" | "list-large", } export const appStore = store("app", { ...defaultValue }, DEFAULT_STORE_CONFIG) @@ -32,6 +33,7 @@ export const useAppStore = () => { setAutoStart, setStartHidden, setHiddenOnClose, + setSteamUsersViewMode, resetAppStore, } } @@ -75,6 +77,10 @@ const setHiddenOnClose = (hiddenOnClose: boolean) => { appStore.state.hiddenOnClose = hiddenOnClose; } +const setSteamUsersViewMode = (viewMode: "card" | "list" | "list-large") => { + appStore.state.steamUsersViewMode = viewMode +} + const resetAppStore = () => { setVersion(defaultValue.version) setHasUpdate(defaultValue.hasUpdate) @@ -84,4 +90,5 @@ const resetAppStore = () => { setAutoStart(defaultValue.autoStart) void setStartHidden(defaultValue.startHidden) setHiddenOnClose(defaultValue.hiddenOnClose) + setSteamUsersViewMode(defaultValue.steamUsersViewMode) } \ No newline at end of file