diff --git a/frontend-web/src/pages/LightAppManagementPage.tsx b/frontend-web/src/pages/LightAppManagementPage.tsx index 21a805b7..1db97376 100644 --- a/frontend-web/src/pages/LightAppManagementPage.tsx +++ b/frontend-web/src/pages/LightAppManagementPage.tsx @@ -1,12 +1,23 @@ import { useMemo, useState } from "react"; import { + AlertCircle, + AlignLeft, + ChevronDown, + ChevronUp, + Copy, ExternalLink, + FolderTree, + Globe, HelpCircle, Info, Layers, + Link2, + Monitor, Pencil, Plus, Search, + Sliders, + Tag, Trash2, X, } from "lucide-react"; @@ -98,6 +109,7 @@ export default function LightAppManagementPage() { const [editing, setEditing] = useState(null); const [form, setForm] = useState(emptyForm); const [activeParamPopover, setActiveParamPopover] = useState(null); + const [viewMode, setViewMode] = useState<"table" | "cards">("table"); const saving = actions.create.isPending || actions.update.isPending; @@ -180,109 +192,164 @@ export default function LightAppManagementPage() { } }; + const handleCopyUrl = (url: string) => { + navigator.clipboard?.writeText(url); + toast.success("已复制地址"); + }; + const tableApps = useMemo(() => apps, [apps]); return ( -
-
-
-
-

应用管理

-

- 注册轻应用。window.open 类型在「应用列表」以卡片展示;iframe 类型挂载到所选菜单下并注入侧栏。 +

+
+
+
+

+ 应用管理 +

+

+ 注册轻应用。 + + window.open + + 类型在「应用列表」以卡片展示; + + iframe + + 类型挂载到所选菜单下并注入侧栏。

-
- - setSearch(e.target.value)} - placeholder="搜索应用名称 / 描述" - className="h-9 w-full rounded-[2px] border border-[#E8E8E8] bg-white pl-10 pr-4 text-[14px] text-[#222222] placeholder-[#C1C1C1] shadow-sm transition-all focus:border-[#F5222D] focus:outline-none focus:ring-1 focus:ring-[#F5222D]" - /> - {search && ( +
+
+ + setSearch(e.target.value)} + placeholder="搜索应用名称 / 描述..." + className="w-full rounded-lg border border-neutral-100 bg-neutral-50/60 py-2 pl-10 pr-10 text-xs text-neutral-800 placeholder-neutral-400 transition-all hover:bg-white focus:border-[#F5222D]/40 focus:outline-none focus:ring-4 focus:ring-[#F5222D]/10" + /> + {search && ( + + )} +
+ +
- )} + +
-
- - - - - - - - - - - - +
+
+ 搜寻到 {tableApps.length}{" "} + 个注册完成的子模块轻应用 +
+ + {viewMode === "table" ? ( +
+
名称类型地址 / 挂载参数启用操作
+ + + + + + + + + + + + {tableApps.map((app) => ( - + + + - @@ -375,17 +451,17 @@ export default function LightAppManagementPage() { {tableApps.length === 0 && ( -
名称类型地址挂载参数启用操作
-
- - {app.name} - - {app.description ? ( - {app.description} - ) : ( - 无描述说明 - )} -
+ + {app.name} +
{app.appType === "window_open" ? ( - - + + 新页跳转 ) : ( - - + + iframe 嵌套 )} -
+
- {app.url} + {app.url} - {app.appType === "iframe" && app.mountLocation && ( -
- - 挂载: {mountLabel(app.mountLocation)} -
- )} +
+ {app.appType === "iframe" && app.mountLocation ? ( + + + {mountLabel(app.mountLocation)} + + ) : ( + — + )} + -
+
{app.routeParams.length > 0 ? ( ) : ( - 0个 + 0个 )} {activeParamPopover === app.appId && app.routeParams.length > 0 && ( @@ -307,23 +376,30 @@ export default function LightAppManagementPage() { className="fixed inset-0 z-40" onClick={() => setActiveParamPopover(null)} /> -
-
- 路由参数明细 - - URL 拼接 +
+
+ + 注入的路由参数 +
-
+
{app.routeParams.map((p, idx) => (
- {p.key} - - ({getParamSourceLabel(p)}) - +
+ {p.key} + + {getParamSourceLabel(p)} + +
))}
@@ -337,36 +413,36 @@ export default function LightAppManagementPage() {
{app.enabled ? ( <> - - - + + + - 已启用 + 已启用 ) : ( <> - - 已禁用 + + 已停用 )}
-
+
+
+
-
+
-

+

{isLoading ? "加载中..." : "暂无匹配的组件应用"}

{!isLoading && ( -

+

{search ? "请确认搜索关键词输入是否正确" : "点击右上角“注册应用”添加第一款轻应用"}

)} @@ -396,25 +472,152 @@ export default function LightAppManagementPage() { )}
+
+ ) : tableApps.length === 0 ? ( +
+
+ +
+

+ {isLoading ? "加载中..." : "暂无匹配的组件应用"} +

+ {!isLoading && ( +

+ {search ? "请确认搜索关键词输入是否正确" : "点击右上角“注册应用”添加第一款轻应用"} +

+ )} +
+ ) : ( +
+ {tableApps.map((app) => ( +
+
+
+
+
+ {app.appType === "window_open" ? ( + + + 新页跳转 + + ) : ( + + + iframe 嵌套 + + )} +

+ {app.name} +

+
+ {app.enabled ? ( + + + 已启用 + + ) : ( + + + 已停用 + + )} +
+ +

+ {app.description || "暂无应用详细描述说明。"} +

+ +
+ + + {app.url} + + +
+ + {app.routeParams.length > 0 && ( +
+ {app.routeParams.map((p, idx) => ( + + {p.key} + + ))} +
+ )} + + {app.appType === "iframe" && app.mountLocation && ( +
+ 挂载分类: + {mountLabel(app.mountLocation)} +
+ )} +
+ +
+ + +
+
+ ))} +
+ )}
-
- -
-

📌 智能多维挂载规则:

-
    -
  • - 当您注册 iframe 嵌套{" "} - 应用时,您需要在菜单一栏指定分类(如“资源管理”),组件将直接作为新导航菜单项加入该分类。 + {viewMode === "table" && ( +
    +
    + +

    智能多维挂载规则:

    +
    +
      +
    • + • + + 当您注册 iframe 嵌套{" "} + 应用时,您需要在菜单一栏指定分类(如“资源管理”),组件将直接作为新导航菜单项加入该分类。 +
    • -
    • - 当路由挂载成功,点击左侧注入的子栏名称可在主区域调起{" "} - 真实 Iframe 预览器 - ,并自动将参数以加密/标准的QueryString传递过去。 +
    • + • + + 当路由挂载成功,点击左侧注入的子栏名称可在主区域调起{" "} + 真实 Iframe 预览器 + ,并自动将参数以加密/标准的QueryString传递过去。 +
    -
+ )}
{dialogOpen && ( @@ -426,9 +629,14 @@ export default function LightAppManagementPage() {
-

- {editing ? "修改轻应用" : "注册应用"} -

+
+ + + +

+ {editing ? "修改轻应用" : "注册应用"} +

+