@4399ywkf/cli 2.0.11 → 2.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +187 -13
- package/dist/templates/app/ywkf.config.ts.tpl +9 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -492,6 +492,10 @@ async function injectMasterAppPages(pagesDir, appName) {
|
|
|
492
492
|
path.join(pagesDir, "micro/layout.tsx"),
|
|
493
493
|
MASTER_MICRO_LAYOUT
|
|
494
494
|
);
|
|
495
|
+
await writeFile(
|
|
496
|
+
path.join(pagesDir, "micro/$.tsx"),
|
|
497
|
+
MASTER_MICRO_CATCHALL
|
|
498
|
+
);
|
|
495
499
|
await writeFile(
|
|
496
500
|
path.join(pagesDir, "page.tsx"),
|
|
497
501
|
MASTER_HOME_PAGE
|
|
@@ -626,35 +630,172 @@ export default function MicroLayout() {
|
|
|
626
630
|
);
|
|
627
631
|
}
|
|
628
632
|
`;
|
|
629
|
-
const MASTER_MICRO_PAGE = `import {
|
|
633
|
+
const MASTER_MICRO_PAGE = `import { useMemo, useState, useEffect, useCallback } from "react";
|
|
634
|
+
import { useNavigate } from "react-router";
|
|
635
|
+
import {
|
|
636
|
+
Typography,
|
|
637
|
+
Card,
|
|
638
|
+
Space,
|
|
639
|
+
Tag,
|
|
640
|
+
Table,
|
|
641
|
+
Button,
|
|
642
|
+
Empty,
|
|
643
|
+
Tooltip,
|
|
644
|
+
Descriptions,
|
|
645
|
+
} from "antd";
|
|
646
|
+
import type { ColumnsType } from "antd/es/table";
|
|
647
|
+
import Garfish from "garfish";
|
|
648
|
+
|
|
649
|
+
const { Title, Text } = Typography;
|
|
650
|
+
|
|
651
|
+
interface SubAppInfo {
|
|
652
|
+
name: string;
|
|
653
|
+
entry: string;
|
|
654
|
+
activeWhen?: string | ((path: string) => boolean);
|
|
655
|
+
basename?: string;
|
|
656
|
+
}
|
|
630
657
|
|
|
631
|
-
|
|
658
|
+
type AppStatus = "online" | "offline" | "checking";
|
|
659
|
+
|
|
660
|
+
function useSubApps() {
|
|
661
|
+
return useMemo<SubAppInfo[]>(() => {
|
|
662
|
+
const infos = Garfish.appInfos ?? {};
|
|
663
|
+
return Object.values(infos).map((info) => ({
|
|
664
|
+
name: info.name,
|
|
665
|
+
entry: info.entry,
|
|
666
|
+
activeWhen: info.activeWhen,
|
|
667
|
+
basename: info.basename,
|
|
668
|
+
}));
|
|
669
|
+
}, []);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function useAppStatusMap(apps: SubAppInfo[]) {
|
|
673
|
+
const [statusMap, setStatusMap] = useState<Record<string, AppStatus>>(() =>
|
|
674
|
+
Object.fromEntries(apps.map((a) => [a.name, "checking" as const]))
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
const checkStatus = useCallback(async (app: SubAppInfo) => {
|
|
678
|
+
try {
|
|
679
|
+
const res = await fetch(app.entry, { mode: "no-cors", cache: "no-store" });
|
|
680
|
+
return (res.status === 0 || res.ok) ? "online" : "offline";
|
|
681
|
+
} catch {
|
|
682
|
+
return "offline";
|
|
683
|
+
}
|
|
684
|
+
}, []);
|
|
685
|
+
|
|
686
|
+
useEffect(() => {
|
|
687
|
+
if (apps.length === 0) return;
|
|
688
|
+
let cancelled = false;
|
|
689
|
+
|
|
690
|
+
async function checkAll() {
|
|
691
|
+
const results = await Promise.all(
|
|
692
|
+
apps.map(async (app) => [app.name, await checkStatus(app)] as const)
|
|
693
|
+
);
|
|
694
|
+
if (!cancelled) setStatusMap(Object.fromEntries(results));
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
checkAll();
|
|
698
|
+
const timer = setInterval(checkAll, 15_000);
|
|
699
|
+
return () => { cancelled = true; clearInterval(timer); };
|
|
700
|
+
}, [apps, checkStatus]);
|
|
701
|
+
|
|
702
|
+
return statusMap;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const STATUS_TAG: Record<AppStatus, { color: string; text: string }> = {
|
|
706
|
+
online: { color: "success", text: "\u5728\u7EBF" },
|
|
707
|
+
offline: { color: "error", text: "\u79BB\u7EBF" },
|
|
708
|
+
checking: { color: "processing", text: "\u68C0\u6D4B\u4E2D" },
|
|
709
|
+
};
|
|
632
710
|
|
|
633
711
|
export default function MicroPage() {
|
|
712
|
+
const navigate = useNavigate();
|
|
713
|
+
const apps = useSubApps();
|
|
714
|
+
const statusMap = useAppStatusMap(apps);
|
|
715
|
+
|
|
716
|
+
const columns: ColumnsType<SubAppInfo> = [
|
|
717
|
+
{
|
|
718
|
+
title: "\u5E94\u7528\u540D\u79F0",
|
|
719
|
+
dataIndex: "name",
|
|
720
|
+
render: (name: string) => <Text strong>{name}</Text>,
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
title: "\u5165\u53E3\u5730\u5740",
|
|
724
|
+
dataIndex: "entry",
|
|
725
|
+
render: (entry: string) => (
|
|
726
|
+
<Tooltip title="\u70B9\u51FB\u5728\u65B0\u7A97\u53E3\u6253\u5F00">
|
|
727
|
+
<a href={entry} target="_blank" rel="noopener noreferrer">{entry}</a>
|
|
728
|
+
</Tooltip>
|
|
729
|
+
),
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
title: "\u6FC0\u6D3B\u8DEF\u7531",
|
|
733
|
+
dataIndex: "activeWhen",
|
|
734
|
+
render: (val: SubAppInfo["activeWhen"]) =>
|
|
735
|
+
typeof val === "string" ? <code>{val}</code> : <Tag>\u81EA\u5B9A\u4E49\u51FD\u6570</Tag>,
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
title: "\u72B6\u6001",
|
|
739
|
+
key: "status",
|
|
740
|
+
width: 100,
|
|
741
|
+
render: (_, record) => {
|
|
742
|
+
const s = statusMap[record.name] ?? "checking";
|
|
743
|
+
const tag = STATUS_TAG[s];
|
|
744
|
+
return <Tag color={tag.color}>{tag.text}</Tag>;
|
|
745
|
+
},
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
title: "\u64CD\u4F5C",
|
|
749
|
+
key: "action",
|
|
750
|
+
width: 100,
|
|
751
|
+
render: (_, record) => {
|
|
752
|
+
const route = typeof record.activeWhen === "string" ? record.activeWhen : null;
|
|
753
|
+
if (!route) return null;
|
|
754
|
+
return (
|
|
755
|
+
<Button type="link" size="small" onClick={() => navigate(route)}>
|
|
756
|
+
\u8BBF\u95EE
|
|
757
|
+
</Button>
|
|
758
|
+
);
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
];
|
|
762
|
+
|
|
634
763
|
return (
|
|
635
|
-
<div style={{ maxWidth:
|
|
764
|
+
<div style={{ maxWidth: 960, margin: "0 auto" }}>
|
|
636
765
|
<Title level={2}>
|
|
637
766
|
\u5FAE\u524D\u7AEF\u7BA1\u7406 <Tag color="green">Garfish</Tag>
|
|
638
767
|
</Title>
|
|
639
768
|
|
|
640
769
|
<Space direction="vertical" size="middle" style={{ width: "100%" }}>
|
|
641
|
-
<Card title=
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
770
|
+
<Card title={\`\u5B50\u5E94\u7528\u5217\u8868\uFF08\${apps.length}\uFF09\`}>
|
|
771
|
+
{apps.length > 0 ? (
|
|
772
|
+
<Table<SubAppInfo>
|
|
773
|
+
rowKey="name"
|
|
774
|
+
columns={columns}
|
|
775
|
+
dataSource={apps}
|
|
776
|
+
pagination={false}
|
|
777
|
+
size="middle"
|
|
778
|
+
/>
|
|
779
|
+
) : (
|
|
780
|
+
<Empty
|
|
781
|
+
description={
|
|
782
|
+
<Text type="secondary">
|
|
783
|
+
\u6682\u672A\u6CE8\u518C\u5B50\u5E94\u7528\u3002\u8BF7\u5728 <code>ywkf.config.ts</code> \u4E2D\u914D\u7F6E{" "}
|
|
784
|
+
<code>garfishPlugin</code> \u7684 apps \u5217\u8868\u3002
|
|
785
|
+
</Text>
|
|
786
|
+
}
|
|
787
|
+
/>
|
|
788
|
+
)}
|
|
649
789
|
</Card>
|
|
650
790
|
|
|
651
791
|
<Card title="\u63A5\u5165\u8BF4\u660E">
|
|
652
792
|
<Descriptions bordered column={1} size="small">
|
|
653
793
|
<Descriptions.Item label="\u5B50\u5E94\u7528\u6CE8\u518C">
|
|
654
|
-
<code>garfishPlugin({
|
|
794
|
+
<code>garfishPlugin({"{"} master: true, apps: [...] {"}"})</code>
|
|
655
795
|
</Descriptions.Item>
|
|
656
796
|
<Descriptions.Item label="\u6302\u8F7D\u5BB9\u5668">
|
|
657
|
-
<code><div id
|
|
797
|
+
<code><div id="subapp-container" /></code>
|
|
798
|
+
\uFF08\u5DF2\u5185\u7F6E\u5728\u5F53\u524D\u5E03\u5C40\u4E2D\uFF09
|
|
658
799
|
</Descriptions.Item>
|
|
659
800
|
<Descriptions.Item label="\u8DEF\u7531\u524D\u7F00">
|
|
660
801
|
\u5B50\u5E94\u7528 <code>activeRule</code> \u5EFA\u8BAE\u4EE5 <code>/micro/xxx</code> \u5F00\u5934
|
|
@@ -669,6 +810,39 @@ export default function MicroPage() {
|
|
|
669
810
|
);
|
|
670
811
|
}
|
|
671
812
|
`;
|
|
813
|
+
const MASTER_MICRO_CATCHALL = `import { Typography, Spin, Alert } from "antd";
|
|
814
|
+
import { useLocation } from "react-router";
|
|
815
|
+
|
|
816
|
+
const { Paragraph } = Typography;
|
|
817
|
+
|
|
818
|
+
export default function MicroCatchAll() {
|
|
819
|
+
const { pathname } = useLocation();
|
|
820
|
+
|
|
821
|
+
return (
|
|
822
|
+
<div style={{ maxWidth: 720, margin: "0 auto", padding: "40px 0" }}>
|
|
823
|
+
<Alert
|
|
824
|
+
type="warning"
|
|
825
|
+
showIcon
|
|
826
|
+
message="\u5B50\u5E94\u7528\u8DEF\u7531\u533A\u57DF"
|
|
827
|
+
description={
|
|
828
|
+
<>
|
|
829
|
+
<Paragraph>
|
|
830
|
+
\u5F53\u524D\u8DEF\u5F84 <code>{pathname}</code> \u9884\u671F\u7531 Garfish \u5B50\u5E94\u7528\u63A5\u7BA1\u3002
|
|
831
|
+
</Paragraph>
|
|
832
|
+
<Paragraph type="secondary">
|
|
833
|
+
\u5982\u679C\u4F60\u770B\u5230\u6B64\u9875\u9762\uFF0C\u8BF4\u660E\u5BF9\u5E94\u7684\u5B50\u5E94\u7528\u5C1A\u672A\u6CE8\u518C\u6216\u672A\u542F\u52A8\u3002
|
|
834
|
+
\u8BF7\u68C0\u67E5 <code>ywkf.config.ts</code> \u4E2D <code>garfishPlugin</code> \u7684 apps \u914D\u7F6E\u3002
|
|
835
|
+
</Paragraph>
|
|
836
|
+
</>
|
|
837
|
+
}
|
|
838
|
+
/>
|
|
839
|
+
<div style={{ textAlign: "center", marginTop: 24 }}>
|
|
840
|
+
<Spin tip="\u7B49\u5F85\u5B50\u5E94\u7528\u52A0\u8F7D..." />
|
|
841
|
+
</div>
|
|
842
|
+
</div>
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
`;
|
|
672
846
|
const SUB_LAYOUT = `import { Outlet, Link, useLocation } from "react-router";
|
|
673
847
|
import { Layout, Menu, Tag } from "antd";
|
|
674
848
|
import { useEffect, useState } from "react";
|
|
@@ -48,7 +48,14 @@ export default defineConfig({
|
|
|
48
48
|
// },
|
|
49
49
|
|
|
50
50
|
plugins: [
|
|
51
|
-
reactQueryPlugin(
|
|
51
|
+
reactQueryPlugin({
|
|
52
|
+
// staleTime: 5 * 60 * 1000, // 缓存过期时间(默认 5 分钟)
|
|
53
|
+
// gcTime: 10 * 60 * 1000, // GC 回收周期(默认 10 分钟)
|
|
54
|
+
// retry: 1, // 失败重试次数(默认 1)
|
|
55
|
+
// devtools: true, // React Query DevTools(仅开发模式)
|
|
56
|
+
// baseURL: "/api", // axios 默认 baseURL
|
|
57
|
+
// timeout: 15000, // 请求超时(默认 15 秒)
|
|
58
|
+
}),
|
|
52
59
|
zustandPlugin(),
|
|
53
60
|
tailwindPlugin(),
|
|
54
61
|
{{#isSubApp}}
|
|
@@ -65,7 +72,7 @@ export default defineConfig({
|
|
|
65
72
|
master: true,
|
|
66
73
|
apps: [
|
|
67
74
|
// 在此注册子应用
|
|
68
|
-
// { name: "sub-app", entry: "http://localhost:3001", activeRule: "/sub" },
|
|
75
|
+
// { name: "sub-app", entry: "http://localhost:3001", activeRule: "/micro/sub-app" },
|
|
69
76
|
],
|
|
70
77
|
}),
|
|
71
78
|
{{/isMasterApp}}
|