Skip to content

Commit 1bcfc25

Browse files
committed
服务列表增加状态显示
1 parent 74962be commit 1bcfc25

File tree

4 files changed

+337
-1
lines changed

4 files changed

+337
-1
lines changed

src/components/List/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { FC } from "react";
2+
import PublicList, { PublicListProps } from "./Public";
3+
import ServiceList from "./service";
4+
5+
const listMap: Record<string, FC<PublicListProps>> = {
6+
service: ServiceList,
7+
};
8+
export default function getList(module: string) {
9+
const List = listMap[module] || PublicList;
10+
return List;
11+
}

src/components/List/service.tsx

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
import React, {
2+
useContext,
3+
useEffect,
4+
useImperativeHandle,
5+
useMemo,
6+
useRef,
7+
} from "react";
8+
import { Button, Popconfirm, Space, Table, App, Tag } from "antd";
9+
import { red, green } from "@ant-design/colors";
10+
import { getRESTfulApi } from "../../api";
11+
import JsonForm from "../Forms/Json";
12+
import { jsonFormatValue, jsonParse } from "../../utils";
13+
import {
14+
CheckCircleOutlined,
15+
CopyOutlined,
16+
DeleteOutlined,
17+
EditOutlined,
18+
StopOutlined,
19+
} from "@ant-design/icons";
20+
import { GostCommit } from "../../api/local";
21+
import Ctx, { CardCtx } from "../../utils/ctx";
22+
import { useListData1, UseTemplates } from "../ListCard/hooks";
23+
import { configEvent } from "../../utils/events";
24+
import { useTranslation } from "react-i18next";
25+
import { PublicListProps } from "./Public";
26+
const showJsonForm = JsonForm.show;
27+
28+
const statusColors: Record<string, string> = {
29+
running: "gold",
30+
ready: "green",
31+
failed: "red",
32+
};
33+
34+
// export type PublicListProps = {
35+
// name: string;
36+
// title: string;
37+
// api: ReturnType<typeof getRESTfulApi>;
38+
// localApi?: GostCommit;
39+
// keyName: string;
40+
// rowKey?: string;
41+
// keyword?: string;
42+
// renderConfig?: (v: any, r: any, i: number) => React.ReactNode;
43+
// filter?: (item: any, keyord: string) => boolean;
44+
// };
45+
46+
export const UpdateCtx = React.createContext<{ update?: (v?: any) => any }>({});
47+
48+
const defaultRenderConfig = (value: any, record: any, index: number) => {
49+
return JSON.stringify(record);
50+
};
51+
52+
const defFilter = (item: any, keyord: string) => {
53+
return item?.name?.toLowerCase()?.indexOf(keyord) !== -1;
54+
};
55+
56+
const ServiceList: React.FC<PublicListProps> = (props) => {
57+
const {
58+
name,
59+
title,
60+
api,
61+
localApi,
62+
keyName,
63+
rowKey = "name",
64+
keyword,
65+
renderConfig = defaultRenderConfig,
66+
filter = defFilter,
67+
} = props;
68+
const { t } = useTranslation();
69+
const { localList, comm } = useContext(CardCtx);
70+
const { gostConfig, localConfig } = useContext(Ctx);
71+
const { dataList, dataSource } = useListData1({
72+
localApi,
73+
name: keyName,
74+
gostConfig,
75+
localConfig,
76+
});
77+
const templates = UseTemplates({ name: keyName });
78+
const { modal, message, notification } = App.useApp();
79+
const {
80+
deleteValue,
81+
updateValue,
82+
disable,
83+
enable,
84+
updateLocal,
85+
deleteLocal,
86+
addValue,
87+
// } = comm.current;
88+
} = comm!;
89+
const ref = useRef<any>({ dataList, dataSource });
90+
useImperativeHandle(
91+
ref,
92+
() => {
93+
return {
94+
dataList,
95+
dataSource,
96+
};
97+
},
98+
[dataList, dataSource]
99+
);
100+
101+
const showList = useMemo(() => {
102+
if (keyword) {
103+
return dataSource.filter((item) => {
104+
return filter(item, keyword);
105+
});
106+
}
107+
return dataSource;
108+
}, [dataSource, filter, keyword]);
109+
useEffect(() => {
110+
function onEdit({ path, record }: { path: string; record: any }) {
111+
const { dataList, dataSource } = ref.current;
112+
const isEnable = dataList.includes(record);
113+
const key = record.name;
114+
const attrs = path.split(",");
115+
const v = attrs.reduce((a, b) => {
116+
return a?.[b];
117+
}, record);
118+
const onup = (value: any) => {
119+
let _record = record;
120+
attrs.forEach((attr, i) => {
121+
if (i === attrs.length - 1) {
122+
_record[attr] = value;
123+
} else {
124+
_record = _record[attr];
125+
}
126+
});
127+
};
128+
showJsonForm({
129+
title: t("base.cmd.edit"),
130+
initialValues: { value: jsonFormatValue(v) },
131+
onFinish: async (values: any) => {
132+
onup(jsonParse(values.value));
133+
if (isEnable) {
134+
await updateValue(key, record);
135+
} else {
136+
await updateLocal(key, record);
137+
}
138+
return true;
139+
},
140+
});
141+
}
142+
configEvent.on(`edit:${name}`, onEdit);
143+
return () => {
144+
configEvent.off(`edit:${name}`, onEdit);
145+
};
146+
}, [name, t, updateLocal, updateValue]);
147+
148+
return (
149+
<div style={{ height: 348, overflow: "auto" }}>
150+
<Table
151+
rowKey={(obj) => obj._id_ || obj.name}
152+
scroll={{ y: 290 }}
153+
size="small"
154+
dataSource={showList}
155+
columns={[
156+
{
157+
title: t("base.form.name"),
158+
dataIndex: rowKey,
159+
ellipsis: true,
160+
width: 150,
161+
},
162+
{
163+
title: t("base.form.details"),
164+
ellipsis: true,
165+
render: (value, record, index) => {
166+
const isEnable = dataList.includes(record);
167+
const update = isEnable
168+
? (value?: any) => updateValue(record.name, value || record)
169+
: (value?: any) => updateLocal(record.name, value || record);
170+
let render: React.ReactNode;
171+
try {
172+
render = renderConfig(value, record, index);
173+
} catch (e) {
174+
render = defaultRenderConfig(value, record, index);
175+
}
176+
return (
177+
<UpdateCtx.Provider value={{ update }}>
178+
{render}
179+
</UpdateCtx.Provider>
180+
);
181+
},
182+
},
183+
{
184+
title: t("base.form.status"),
185+
width: 80,
186+
// ellipsis: true,
187+
render: (value, record, index) => {
188+
const isEnable = dataList.includes(record);
189+
const status = isEnable ? record?.status?.state : 'disable';
190+
if (status) {
191+
// const color = status.state === "running" ? "green" : "red";
192+
return (
193+
<Tag color={statusColors[status as string]}>
194+
{status}
195+
</Tag>
196+
);
197+
}
198+
return "-";
199+
},
200+
},
201+
{
202+
title: t("base.cmd.controls"),
203+
width: localApi ? 120 : 90,
204+
align: "right",
205+
dataIndex: rowKey,
206+
render: (value, record, index) => {
207+
// console.log("render", record);
208+
const isEnable = dataList.includes(record);
209+
const content = { ...record };
210+
delete content.status;
211+
return (
212+
<Space size={2}>
213+
{localApi ? (
214+
isEnable ? (
215+
<Button
216+
title={t("base.cmd.disable")}
217+
icon={
218+
<CheckCircleOutlined
219+
style={{ color: green.primary }}
220+
/>
221+
}
222+
type="link"
223+
size={"small"}
224+
onClick={async () => {
225+
await disable(record);
226+
}}
227+
>
228+
{/* 禁用 */}
229+
</Button>
230+
) : (
231+
<Button
232+
title={t("base.cmd.enabled")}
233+
type="link"
234+
icon={<StopOutlined style={{ color: red.primary }} />}
235+
size={"small"}
236+
onClick={async () => {
237+
await enable(record);
238+
}}
239+
>
240+
{/* 启用 */}
241+
</Button>
242+
)
243+
) : null}
244+
<Button
245+
title={t("base.cmd.edit")}
246+
icon={<EditOutlined />}
247+
type="link"
248+
size={"small"}
249+
onClick={() => {
250+
showJsonForm({
251+
title: t("title.edit", { name: value || "" }),
252+
templates: templates,
253+
initialValues: { value: jsonFormatValue(content) },
254+
onFinish: async (values: any) => {
255+
const { value } = values;
256+
const json = jsonParse(value);
257+
if (isEnable) {
258+
await updateValue(record.name, json);
259+
} else {
260+
await updateLocal(record.name, {
261+
...content,
262+
...json,
263+
});
264+
}
265+
return true;
266+
},
267+
});
268+
}}
269+
/>
270+
<Button
271+
title={t("base.cmd.copy")}
272+
icon={<CopyOutlined />}
273+
type="link"
274+
size={"small"}
275+
onClick={() => {
276+
showJsonForm({
277+
title: t("title.copied", { name: value || "" }),
278+
templates: templates,
279+
initialValues: { value: jsonFormatValue(content) },
280+
onFinish: async (values: any) => {
281+
const { value } = values;
282+
const json = jsonParse(value);
283+
await comm!.addValue(json);
284+
return true;
285+
},
286+
});
287+
}}
288+
/>
289+
<Popconfirm
290+
title={t("text.warn")}
291+
description={t("text.deleteing")}
292+
onConfirm={() => {
293+
if (isEnable) {
294+
deleteValue(record);
295+
} else {
296+
deleteLocal(record);
297+
}
298+
}}
299+
>
300+
<Button
301+
title={t("base.cmd.del")}
302+
icon={<DeleteOutlined />}
303+
type="link"
304+
size={"small"}
305+
/>
306+
</Popconfirm>
307+
</Space>
308+
);
309+
},
310+
},
311+
]}
312+
pagination={false}
313+
></Table>
314+
</div>
315+
);
316+
};
317+
export default ServiceList;

src/components/ListCard/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { configEvent } from "../../utils/events";
1212
import { CloseOutlined } from "@ant-design/icons";
1313
import classnames from "classnames";
1414
import { useTranslation } from "react-i18next";
15+
import getList from "../List";
1516

1617
export type ListCardProps = {
1718
module?: string;
@@ -159,6 +160,12 @@ const ListCard: React.FC<ListCardProps> = (props) => {
159160
useEffect(() => {
160161
return commBindEvent(name, comm);
161162
}, [comm, name]);
163+
164+
const List = useMemo(() => {
165+
debugger;
166+
return getList(props.module!);
167+
}, [props.module]);
168+
162169
return (
163170
<CardCtx.Provider value={{ name, comm }}>
164171
<ProCard
@@ -180,7 +187,7 @@ const ListCard: React.FC<ListCardProps> = (props) => {
180187
</Space>
181188
}
182189
>
183-
<PublicList {..._prop}></PublicList>
190+
<List {..._prop}></List>
184191
</ProCard>
185192
</CardCtx.Provider>
186193
);

src/i18n/languages.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ base.form.password,密码,Password
77
base.form.local,保存到本地,Save to local
88
base.form.name,名称,Name
99
base.form.details,详情,Details
10+
base.form.status,状态,Status
1011
base.cmd.connect,连接,Connect
1112
base.cmd.controls,操作,Operation
1213
base.cmd.enabled,启用,Enabled

0 commit comments

Comments
 (0)