Files
erp/apps/web/src/pages/PluginTabsPage.tsx
iven 92789e6713 feat(crm): 创建 CRM 插件 crate + 前端 tabs/tree 页面类型 + 动态菜单
- CRM WASM 插件:Cargo.toml + src/lib.rs + plugin.toml(5 实体 + 9 权限 + 6 页面)
- 注册 erp-plugin-crm 到 workspace members
- PluginTabsPage: 通用标签页容器,递归渲染子页面
- PluginTreePage: 通用树形页面,前端构建树结构
- App.tsx: 新增 /tabs/:pageLabel 和 /tree/:entityName 路由
- plugin store: 从 manifest pages 生成菜单(支持 tabs 聚合)
- MainLayout: 动态图标映射(team/user/message/tags/apartment)
2026-04-16 12:41:17 +08:00

62 lines
1.7 KiB
TypeScript

import { useState } from 'react';
import { Tabs } from 'antd';
import {
PluginPageSchema,
PluginEntitySchema,
PluginFieldSchema,
} from '../api/plugins';
interface PluginTabsPageProps {
pluginId: string;
label: string;
icon?: string;
tabs: PluginPageSchema[];
entities: PluginEntitySchema[];
}
export function PluginTabsPage({ pluginId, label, tabs, entities }: PluginTabsPageProps) {
const [activeKey, setActiveKey] = useState(tabs[0] && 'label' in tabs[0] ? tabs[0].label : '');
const renderTabContent = (tab: PluginPageSchema) => {
if (tab.type === 'crud') {
// 懒加载 PluginCRUDPage 避免循环依赖
const PluginCRUDPage = require('./PluginCRUDPage').default;
return (
<PluginCRUDPage
pluginIdOverride={pluginId}
entityOverride={tab.entity}
enableSearch={tab.enable_search}
enableViews={tab.enable_views}
/>
);
}
if (tab.type === 'tree') {
const PluginTreePage = require('./PluginTreePage').PluginTreePage;
const entity = entities.find((e) => e.name === tab.entity);
return (
<PluginTreePage
pluginId={pluginId}
entity={tab.entity}
idField={tab.id_field}
parentField={tab.parent_field}
labelField={tab.label_field}
fields={entity?.fields || []}
/>
);
}
return <div>: {tab.type}</div>;
};
const items = tabs.map((tab) => ({
key: 'label' in tab ? tab.label : '',
label: 'label' in tab ? tab.label : '',
children: renderTabContent(tab),
}));
return (
<div style={{ padding: 24 }}>
<Tabs activeKey={activeKey} onChange={setActiveKey} items={items} />
</div>
);
}