diff --git a/src/App.tsx b/src/App.tsx index cdb050f..8a2abd3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,19 +1,3 @@ -import { - BarChartOutlined, - BranchesOutlined, - CustomerServiceOutlined, - DeleteOutlined, - FolderOpenOutlined, - GlobalOutlined, - HeartOutlined, - HomeOutlined, - LayoutOutlined, - RobotOutlined, - ShoppingOutlined, - SwapOutlined, - ToolOutlined, - WalletOutlined, -} from "@ant-design/icons"; import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useShallow } from "zustand/react/shallow"; import ErrorBoundary from "./components/ErrorBoundary"; @@ -37,6 +21,7 @@ import { webGenerationGateway, type CreatePreviewTaskInput } from "./api/webGene import { translateTaskError } from "./utils/translateTaskError"; import { recoverAndResumeTasks } from "./services/backgroundTaskRunner"; import AppShell from "./components/AppShell"; +import { ShellIcon } from "./components/ShellIcon"; const NotFoundPage = lazy(() => import("./components/NotFoundPage")); const CompliancePage = lazy(() => import("./features/compliance/CompliancePage")); import { cloneWorkflow, createBlankWorkflow } from "./data/workflows"; @@ -441,24 +426,24 @@ function App() { const navItems = useMemo( () => [ - { key: "home", label: "首页", hint: "项目入口", icon: }, - { key: "workbench", label: "生成", hint: "对话生成页面", icon: }, + { key: "home", label: "首页", hint: "项目入口", icon: }, + { key: "workbench", label: "生成", hint: "对话生成页面", icon: }, { key: "ecommerce", label: "电商生成", hint: "AI创作与海报生成", - icon: , + icon: , }, - { key: "canvas", label: "画布", hint: "进入自由画布编排", icon: }, - { key: "community", label: "社区", hint: "案例分享与导入", icon: }, - { key: "scriptTokens", label: "剧本评分", hint: "剧本评分系统", icon: }, - { key: "tokenUsage", label: "Token消耗", hint: "成员、服务与调用记录", icon: }, - { key: "providerHealth", label: "服务商健康", hint: "AI 服务商状态与监控", icon: }, - { key: "assets", label: "资产库", hint: "角色、场景、道具", icon: }, - { key: "agent", label: "Agent", hint: "拆解与规划", icon: }, - { key: "digitalHuman", label: "数字人", hint: "口播与人像生成", icon: }, - { key: "characterMix", label: "角色迁移", hint: "人物视频迁移", icon: }, - { key: "more", label: "工具盒", hint: "图像与镜头工具", icon: }, + { key: "canvas", label: "画布", hint: "进入自由画布编排", icon: }, + { key: "community", label: "社区", hint: "案例分享与导入", icon: }, + { key: "scriptTokens", label: "剧本评分", hint: "剧本评分系统", icon: }, + { key: "tokenUsage", label: "Token消耗", hint: "成员、服务与调用记录", icon: }, + { key: "providerHealth", label: "服务商健康", hint: "AI 服务商状态与监控", icon: }, + { key: "assets", label: "资产库", hint: "角色、场景、道具", icon: }, + { key: "agent", label: "Agent", hint: "拆解与规划", icon: }, + { key: "digitalHuman", label: "数字人", hint: "口播与人像生成", icon: }, + { key: "characterMix", label: "角色迁移", hint: "人物视频迁移", icon: }, + { key: "more", label: "工具盒", hint: "图像与镜头工具", icon: }, ], [], ); @@ -1455,7 +1440,7 @@ function App() { />
- +

删除项目

确认删除项目「{pendingDeleteProject.name}」?删除后将从服务器项目列表移除。

diff --git a/src/components/AppShell.tsx b/src/components/AppShell.tsx index 542bfff..2efa463 100644 --- a/src/components/AppShell.tsx +++ b/src/components/AppShell.tsx @@ -1,15 +1,3 @@ -import { - ArrowDownOutlined, - ArrowUpOutlined, - CheckCircleOutlined, - FlagOutlined, - InfoCircleOutlined, - LoginOutlined, - LogoutOutlined, - PlusCircleOutlined, - UserOutlined, - WalletOutlined, -} from "@ant-design/icons"; import { useEffect, useMemo, useRef, useState } from "react"; import type { ReactNode } from "react"; import { publicConfigClient, type WebPublicConfig } from "../api/publicConfigClient"; @@ -23,6 +11,7 @@ import { AnimatedPanel } from "./AnimatedPanel"; import AdminMonitor from "./AdminMonitor"; import CookieConsentBanner from "./CookieConsentBanner"; import { loadRechargeModal, type RechargeModalComponent } from "./RechargeModal/loadRechargeModal"; +import { ShellIcon } from "./ShellIcon"; import { loadDarkGreenTheme } from "../styles/loadDarkGreenTheme"; interface AppShellProps { @@ -330,7 +319,7 @@ function AppShell({ aria-label="返回页面顶部" onClick={() => scrollActivePage("top")} > - + ) : null} @@ -369,7 +358,7 @@ function AppShell({ aria-label="网站信息" onClick={() => setInfoOpen((c) => !c)} > - +
@@ -392,7 +381,7 @@ function AppShell({ aria-label={`积分余额 ${displayedBalanceLabel}`} onClick={() => toast.info("充值功能即将开放,敬请期待")} > - + {displayedBalanceLabel}
@@ -416,7 +405,7 @@ function AppShell({ ) : ( <> - + 登录 / 注册 )} @@ -444,7 +433,7 @@ function AppShell({
{session?.source === "server" ? "服务器会话" : "预览会话"}
@@ -456,7 +445,7 @@ function AppShell({ onSelectView("login"); }} > - + 个人中心 {showCommunityReview ? ( @@ -480,7 +469,7 @@ function AppShell({ onSelectView("communityReview"); }} > - + 社区审核 @@ -495,7 +484,7 @@ function AppShell({ onSelectView("communityCaseAdd"); }} > - + 添加案例 diff --git a/src/components/NotificationCenter.tsx b/src/components/NotificationCenter.tsx index 586b9f2..a0a3757 100644 --- a/src/components/NotificationCenter.tsx +++ b/src/components/NotificationCenter.tsx @@ -1,26 +1,17 @@ -import { - BellOutlined, - CheckCircleOutlined, - CloseCircleOutlined, - DeleteOutlined, - DislikeOutlined, - ExclamationCircleOutlined, - LikeOutlined, - LockOutlined, -} from "@ant-design/icons"; import { useEffect, useRef, useState } from "react"; import type { WebNotification, WebNotificationType, WebViewKey } from "../types"; import { AnimatedPanel } from "./AnimatedPanel"; +import { ShellIcon } from "./ShellIcon"; const NOTIFICATION_ICONS: Record = { - task_completed: , - task_failed: , - review_pending: , - review_passed: , - review_rejected: , - credits_low: , - session_expired: , - info: , + task_completed: , + task_failed: , + review_pending: , + review_passed: , + review_rejected: , + credits_low: , + session_expired: , + info: , }; function parseTimestamp(dateStr: string): number { @@ -111,7 +102,7 @@ function NotificationCenter({ items, onNavigate, onMarkRead, onMarkAllRead, onCl aria-label={`通知中心${unreadCount > 0 ? `,${unreadCount}条未读` : ""}`} onClick={() => { setOpen((v) => !v); setNow(Date.now()); }} > - + {unreadCount > 0 && ( {unreadCount > 99 ? "99+" : unreadCount} )} @@ -127,7 +118,7 @@ function NotificationCenter({ items, onNavigate, onMarkRead, onMarkAllRead, onCl )} {notifications.length > 0 && onClear && ( )}
@@ -135,7 +126,7 @@ function NotificationCenter({ items, onNavigate, onMarkRead, onMarkAllRead, onCl
{notifications.length === 0 ? (
- + 暂无通知
) : ( diff --git a/src/components/ShellIcon.tsx b/src/components/ShellIcon.tsx new file mode 100644 index 0000000..03ff357 --- /dev/null +++ b/src/components/ShellIcon.tsx @@ -0,0 +1,344 @@ +import type { CSSProperties } from "react"; + +export type ShellIconName = + | "arrow-down" + | "arrow-left" + | "arrow-up" + | "bar-chart" + | "bell" + | "branches" + | "check-circle" + | "chevron-left" + | "chevron-right" + | "close-circle" + | "copy" + | "customer-service" + | "delete" + | "dislike" + | "download" + | "exclamation-circle" + | "flag" + | "file-text" + | "folder" + | "global" + | "heart" + | "home" + | "info-circle" + | "like" + | "line-chart" + | "lock" + | "login" + | "logout" + | "loading" + | "plus-circle" + | "reload" + | "robot" + | "shopping" + | "swap" + | "team" + | "thunderbolt" + | "tool" + | "upload" + | "user" + | "wallet" + | "warning"; + +interface ShellIconProps { + name: ShellIconName; + className?: string; + style?: CSSProperties; +} + +function renderIcon(name: ShellIconName) { + switch (name) { + case "arrow-down": + return ; + case "arrow-left": + return ; + case "arrow-up": + return ; + case "bar-chart": + return ( + <> + + + + + + + ); + case "bell": + return ( + <> + + + + ); + case "branches": + return ( + <> + + + + + + + ); + case "check-circle": + return ( + <> + + + + ); + case "chevron-left": + return ; + case "chevron-right": + return ; + case "close-circle": + return ( + <> + + + + ); + case "copy": + return ( + <> + + + + ); + case "customer-service": + return ( + <> + + + + + + ); + case "delete": + return ( + <> + + + + + + + ); + case "download": + return ( + <> + + + + + ); + case "dislike": + return ( + <> + + + + + ); + case "exclamation-circle": + return ( + <> + + + + + ); + case "flag": + return ( + <> + + + + ); + case "file-text": + return ( + <> + + + + + + ); + case "folder": + return ; + case "global": + return ( + <> + + + + + + ); + case "heart": + return ; + case "home": + return ( + <> + + + + + ); + case "info-circle": + return ( + <> + + + + + ); + case "like": + return ( + <> + + + + + ); + case "line-chart": + return ( + <> + + + + + ); + case "lock": + return ( + <> + + + + ); + case "login": + return ( + <> + + + + + ); + case "logout": + return ( + <> + + + + + ); + case "loading": + return ( + <> + + + + ); + case "plus-circle": + return ( + <> + + + + + ); + case "reload": + return ( + <> + + + + ); + case "robot": + return ( + <> + + + + + + + ); + case "shopping": + return ( + <> + + + + + + ); + case "swap": + return ( + <> + + + + ); + case "team": + return ( + <> + + + + + + ); + case "thunderbolt": + return ; + case "tool": + return ; + case "upload": + return ( + <> + + + + + ); + case "user": + return ( + <> + + + + ); + case "wallet": + return ( + <> + + + + + ); + case "warning": + return ( + <> + + + + + ); + default: + return ; + } +} + +export function ShellIcon({ name, className, style }: ShellIconProps) { + return ( + + ); +} diff --git a/src/features/script-tokens/ScriptTokensPage.tsx b/src/features/script-tokens/ScriptTokensPage.tsx index 1f7060b..3cf256f 100644 --- a/src/features/script-tokens/ScriptTokensPage.tsx +++ b/src/features/script-tokens/ScriptTokensPage.tsx @@ -1,18 +1,9 @@ -import { - BarChartOutlined, - CheckCircleFilled, - CopyOutlined, - DownloadOutlined, - FileTextOutlined, - LoadingOutlined, - ThunderboltOutlined, - UploadOutlined, -} from "@ant-design/icons"; import { useEffect, useRef, useState, type ChangeEvent, type KeyboardEvent } from "react"; import "../../styles/pages/script-tokens-v5.css"; import "../../styles/pages/script-tokens.css"; import { evaluateScript } from "../../api/scriptEvalClient"; import { buildApiUrl, getStoredToken } from "../../api/serverConnection"; +import { ShellIcon } from "../../components/ShellIcon"; import { useSessionStore } from "../../stores"; interface ScoreDimension { @@ -494,7 +485,7 @@ function ScriptTokensPage() { > {uploadedFile ? (
- + {uploadedFile.name} {formatFileSize(uploadedFile.size)} @@ -505,10 +496,10 @@ function ScriptTokensPage() {
) : ( <> -
+
拖拽或点击上传
{TEXT_FILE_HINT}
@@ -581,11 +572,11 @@ function ScriptTokensPage() { disabled={loading || !hasContent} onClick={() => void handleEvaluate()} > - {loading ? : } + {loading ? : } {loading ? "评测中..." : "开始评测"}
@@ -603,10 +594,10 @@ function ScriptTokensPage() { {result && ( <> )} @@ -640,7 +631,7 @@ function ScriptTokensPage() { onKeyDown={uploadKeyDown} >
- +
{uploadedFile ? "剧本已导入" : "上传剧本文件"} @@ -744,7 +735,7 @@ function ScriptTokensPage() {
- + {activeDim === null ? "悬停维度可查看当前分项表现,优先从低分项制定改稿计划。" diff --git a/src/features/script-tokens/TokenUsagePage.tsx b/src/features/script-tokens/TokenUsagePage.tsx index 215aafb..33dec5d 100644 --- a/src/features/script-tokens/TokenUsagePage.tsx +++ b/src/features/script-tokens/TokenUsagePage.tsx @@ -1,16 +1,5 @@ -import { - ArrowLeftOutlined, - BarChartOutlined, - CheckCircleOutlined, - LeftOutlined, - LineChartOutlined, - ReloadOutlined, - RightOutlined, - TeamOutlined, - UserOutlined, - WarningOutlined, -} from "@ant-design/icons"; import { useCallback, useEffect, useMemo, useState } from "react"; +import { ShellIcon } from "../../components/ShellIcon"; import "../../styles/pages/more-tools.css"; import "../../styles/pages/script-tokens-v5.css"; import "../../styles/pages/script-tokens.css"; @@ -246,7 +235,7 @@ function TokenUsagePage({
管理中心 @@ -257,18 +246,18 @@ function TokenUsagePage({ {enterpriseUsageLoading ? "正在同步企业用量" : enterpriseUsageError || "服务器已连接"}
{isLowBalance ? (
- + 当前余额 {formatCredits(availableBalanceCents)},可能不足以完成下一次生成,请及时充值。
) : null} @@ -287,7 +276,7 @@ function TokenUsagePage({

- + 模型消耗分布

{enterpriseUsageLoading ? "SYNC" : modelBreakdown.length ? `${modelBreakdown.length} 个模型` : "LIVE"} @@ -309,7 +298,7 @@ function TokenUsagePage({
) : (
- + 暂无模型用量数据
)} @@ -318,7 +307,7 @@ function TokenUsagePage({

- + 系统状态

@@ -347,7 +336,7 @@ function TokenUsagePage({

- + 团队成员 ({members.length})

@@ -366,7 +355,7 @@ function TokenUsagePage({ {member.taskCount} 调用 {formatDateTime(member.lastUsedAt)} - +
))}
@@ -375,7 +364,7 @@ function TokenUsagePage({

- + 调用记录

{records.length} 条记录 @@ -411,11 +400,11 @@ function TokenUsagePage({ {records.length > pageSize && (
{recordPage + 1} / {totalPages}
)} diff --git a/src/styles/shell/app-shell.css b/src/styles/shell/app-shell.css index d8519d9..6c644da 100644 --- a/src/styles/shell/app-shell.css +++ b/src/styles/shell/app-shell.css @@ -189,6 +189,18 @@ gap: 8px; } +.shell-icon { + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 0; +} + +.shell-icon svg { + width: 1em; + height: 1em; +} + .creator-button, .member-button, .profile-button,