This is an automated email from the ASF dual-hosted git repository.

liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new ece3c41f feat: Registry config. (#541)
ece3c41f is described below

commit ece3c41fb19b828d92d598930d3ee87f33181421
Author: Wweiei <45253632+wwe...@users.noreply.github.com>
AuthorDate: Tue Sep 2 10:56:16 2025 +0800

    feat: Registry config. (#541)
---
 src/common/menu.js                     |   5 +
 src/common/router.js                   |   7 +
 src/locales/en-US.json                 |   9 +
 src/locales/zh-CN.json                 |   9 +
 src/models/registry.js                 | 138 +++++++++++
 src/routes/System/Registry/AddModal.js | 220 +++++++++++++++++
 src/routes/System/Registry/index.js    | 424 +++++++++++++++++++++++++++++++++
 src/services/api.js                    |  41 ++++
 8 files changed, 853 insertions(+)

diff --git a/src/common/menu.js b/src/common/menu.js
index 0f1ce8bd..32da50f8 100644
--- a/src/common/menu.js
+++ b/src/common/menu.js
@@ -105,6 +105,11 @@ export const menuData = [
         path: "instance",
         locale: "SHENYU.MENU.SYSTEM.MANAGMENT.INSTANCE",
       },
+      {
+        name: getIntlContent("SHENYU.MENU.SYSTEM.MANAGMENT.REGISTRY"),
+        path: "registry",
+        locale: "SHENYU.MENU.SYSTEM.MANAGMENT.REGISTRY",
+      },
     ],
   },
   {
diff --git a/src/common/router.js b/src/common/router.js
index b56037c2..66b454e7 100644
--- a/src/common/router.js
+++ b/src/common/router.js
@@ -182,6 +182,13 @@ export const getRouterData = (app) => {
         () => import("../routes/System/Instance"),
       ),
     },
+    "/config/registry": {
+      component: dynamicWrapper(
+        app,
+        ["registry"],
+        () => import("../routes/System/Registry"),
+      ),
+    },
     "/config/namespacePlugin": {
       component: dynamicWrapper(
         app,
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 77895823..72a29f35 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -94,6 +94,7 @@
   "SHENYU.MENU.SYSTEM.MANAGMENT.METADATA": "Metadata",
   "SHENYU.MENU.SYSTEM.MANAGMENT.DICTIONARY": "Dictionary",
   "SHENYU.MENU.SYSTEM.MANAGMENT.INSTANCE": "Instance",
+  "SHENYU.MENU.SYSTEM.MANAGMENT.REGISTRY": "RegistryConfig",
   "SHENYU.MENU.SYSTEM.MANAGMENT.NAMESPACE": "Namespace",
   "SHENYU.MENU.CONFIG.MANAGMENT": "BasicConfig",
   "SHENYU.PLUGIN.SELECTOR.LIST.TITLE": "SelectorList",
@@ -368,6 +369,14 @@
   "SHENYU.INSTANCE.SELECT.TYPE": "Instance Type",
   "SHENYU.INSTANCE.SELECT.TYPE.BOOTSTRAP": "Bootstrap",
   "SHENYU.INSTANCE.SELECT.TYPE.CLIENT": "Client",
+  "SHENYU.REGISTRY.NAMESPACE": "Namespace",
+  "SHENYU.REGISTRY.REGISTRY_ID": "RegistryId",
+  "SHENYU.REGISTRY.ADDRESS": "Address",
+  "SHENYU.REGISTRY.PROTOCOL": "Protocol",
+  "SHENYU.REGISTRY.USERNAME": "UserName",
+  "SHENYU.REGISTRY.GROUP": "Group",
+  "SHENYU.REGISTRY.MODAL.TITLE": "Add Registry Data",
+  "SHENYU.REGISTRY.PASSPORT": "Passport",
   "SHENYU.PLUGIN.SELECT.STATUS": "Select Status",
   "SHENYU.PLUGIN.REQUEST.HEADER.KEY": "Header Key",
   "SHENYU.PLUGIN.REQUEST.HEADER.VALUE": "Header Value",
diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json
index fcf4e881..7b7abfac 100644
--- a/src/locales/zh-CN.json
+++ b/src/locales/zh-CN.json
@@ -95,6 +95,7 @@
   "SHENYU.MENU.SYSTEM.MANAGMENT.METADATA": "元数据管理",
   "SHENYU.MENU.SYSTEM.MANAGMENT.DICTIONARY": "字典管理",
   "SHENYU.MENU.SYSTEM.MANAGMENT.INSTANCE": "实例管理",
+  "SHENYU.MENU.SYSTEM.MANAGMENT.REGISTRY":"注册中心管理",
   "SHENYU.MENU.CONFIG.MANAGMENT": "基础配置",
   "SHENYU.MENU.SYSTEM.MANAGMENT.NAMESPACE": "命名空间管理",
   "SHENYU.PLUGIN.SELECTOR.LIST.TITLE": "选择器列表",
@@ -372,6 +373,14 @@
   "SHENYU.INSTANCE.SELECT.TYPE": "实例类型",
   "SHENYU.INSTANCE.SELECT.TYPE.BOOTSTRAP": "网关实例",
   "SHENYU.INSTANCE.SELECT.TYPE.CLIENT": "客户端实例",
+  "SHENYU.REGISTRY.MODAL.TITLE": "注册中心",
+  "SHENYU.REGISTRY.REGISTRY_ID": "注册ID",
+  "SHENYU.REGISTRY.ADDRESS": "注册地址",
+  "SHENYU.REGISTRY.PROTOCOL": "协议类型",
+  "SHENYU.REGISTRY.USERNAME": "用户名",
+  "SHENYU.REGISTRY.NAMESPACE": "命名空间",
+  "SHENYU.REGISTRY.GROUP": "分组",
+  "SHENYU.REGISTRY.PASSPORT": "密码",
   "SHENYU.PLUGIN.SELECT.STATUS": "选择状态",
   "SHENYU.PLUGIN.REQUEST.HEADER.KEY": "Header Key",
   "SHENYU.PLUGIN.REQUEST.HEADER.VALUE": "Header Value",
diff --git a/src/models/registry.js b/src/models/registry.js
new file mode 100755
index 00000000..180966a1
--- /dev/null
+++ b/src/models/registry.js
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { message } from "antd";
+import {
+  getRegistryList,
+  insertOrUpdateRegistry,
+  getRegistryDetail,
+  batchDeleteRegistry,
+} from "../services/api";
+import { getIntlContent } from "../utils/IntlUtils";
+
+export default {
+  namespace: "registry",
+
+  state: {
+    registryList: [],
+    total: 0,
+  },
+
+  effects: {
+    *fetch(params, { call, put }) {
+      const { payload } = params;
+      const json = yield call(getRegistryList, payload);
+      if (json.code === 200) {
+        let { dataList, page } = json.data;
+        dataList = dataList.map((item) => {
+          item.key = item.id;
+          return item;
+        });
+        yield put({
+          type: "saveRegistryList",
+          payload: {
+            total: page.totalCount,
+            dataList,
+          },
+        });
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+
+    *add(params, { call, put }) {
+      const { payload, callback, fetchValue } = params;
+      const json = yield call(insertOrUpdateRegistry, payload);
+      if (json.code === 200) {
+        message.destroy();
+        message.success(getIntlContent("SHENYU.COMMON.RESPONSE.ADD.SUCCESS"));
+        callback();
+        yield put({ type: "fetch", payload: fetchValue });
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+
+    *update(params, { call, put }) {
+      const { payload, callback, fetchValue } = params;
+      const json = yield call(insertOrUpdateRegistry, payload);
+      if (json.code === 200) {
+        message.destroy();
+        message.success(
+          getIntlContent("SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS"),
+        );
+        callback();
+        yield put({ type: "fetch", payload: fetchValue });
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+
+    *delete(params, { call, put }) {
+      const { payload, fetchValue, callback } = params;
+      const { list } = payload;
+      const json = yield call(batchDeleteRegistry, { list });
+      if (json.code === 200) {
+        message.destroy();
+        message.success(
+          getIntlContent("SHENYU.COMMON.RESPONSE.DELETE.SUCCESS"),
+        );
+        callback();
+        yield put({ type: "fetch", payload: fetchValue });
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+
+    *fetchItem(params, { call }) {
+      const { payload, callback } = params;
+      const json = yield call(getRegistryList, { id: payload.id });
+      if (json.code === 200) {
+        const registry = json.data.dataList[0];
+        callback(registry);
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+    *getDetail(params, { call }) {
+      const { payload, callback } = params;
+      const json = yield call(getRegistryDetail, payload);
+      if (json.code === 200) {
+        const registry = json.data;
+        callback(registry);
+      } else {
+        message.destroy();
+        message.error(json.message);
+      }
+    },
+  },
+
+  reducers: {
+    saveRegistryList(state, { payload }) {
+      return {
+        ...state,
+        registryList: payload.dataList,
+        total: payload.total,
+      };
+    },
+  },
+};
diff --git a/src/routes/System/Registry/AddModal.js 
b/src/routes/System/Registry/AddModal.js
new file mode 100755
index 00000000..769c910e
--- /dev/null
+++ b/src/routes/System/Registry/AddModal.js
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { Component } from "react";
+import { Modal, Form, Input } from "antd";
+import { getIntlContent } from "../../../utils/IntlUtils";
+
+const FormItem = Form.Item;
+
+class AddModal extends Component {
+  handleSubmit = (e) => {
+    const { form, handleOk } = this.props;
+    const { id } = this.props?.detail || {};
+    e.preventDefault();
+    form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        let {
+          registryId,
+          protocol,
+          address,
+          username,
+          password,
+          namespace,
+          group,
+        } = values;
+        handleOk({
+          registryId,
+          protocol,
+          address,
+          username,
+          password,
+          namespace,
+          group,
+          id,
+        });
+      }
+    });
+  };
+
+  render() {
+    let { handleCancel, form } = this.props;
+
+    const {
+      registryId = "",
+      protocol = "",
+      address = "",
+      username = "",
+      password = "",
+      namespace = "",
+      group = "",
+      id = "",
+    } = this.props?.detail || {};
+
+    const { getFieldDecorator } = form;
+    const formItemLayout = {
+      labelCol: {
+        sm: { span: 6 },
+      },
+      wrapperCol: {
+        sm: { span: 18 },
+      },
+    };
+
+    return (
+      <Modal
+        width={550}
+        centered
+        title={getIntlContent("SHENYU.REGISTRY.MODAL.TITLE")}
+        visible
+        okText={getIntlContent("SHENYU.COMMON.SURE")}
+        cancelText={getIntlContent("SHENYU.COMMON.CALCEL")}
+        onOk={this.handleSubmit}
+        onCancel={handleCancel}
+      >
+        <Form onSubmit={this.handleSubmit} className="login-form">
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.REGISTRY_ID")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("registryId", {
+              rules: [
+                {
+                  required: true,
+                  message: getIntlContent("SHENYU.REGISTRY.REGISTRY_ID.INPUT"),
+                },
+                {
+                  max: 20,
+                  message: 
getIntlContent("SHENYU.REGISTRY.REGISTRY_ID.LENGTH"),
+                },
+              ],
+              initialValue: registryId,
+            })(
+              <Input
+                placeholder={getIntlContent(
+                  "SHENYU.REGISTRY.REGISTRY_ID.INPUT",
+                )}
+                disabled={id}
+              />,
+            )}
+          </FormItem>
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.PROTOCOL")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("protocol", {
+              rules: [
+                {
+                  required: true,
+                  message: getIntlContent("SHENYU.REGISTRY.PROTOCOL.INPUT"),
+                },
+              ],
+              initialValue: protocol,
+            })(
+              <Input
+                placeholder={getIntlContent("SHENYU.REGISTRY.PROTOCOL.INPUT")}
+              />,
+            )}
+          </FormItem>
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.ADDRESS")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("address", {
+              rules: [
+                {
+                  required: true,
+                  message: getIntlContent("SHENYU.REGISTRY.ADDRESS.INPUT"),
+                },
+                {
+                  max: 256,
+                  message: 
getIntlContent("SHENYU.REGISTRY.REGISTRY_ID.LENGTH"),
+                },
+              ],
+              initialValue: address,
+            })(
+              <Input
+                placeholder={getIntlContent("SHENYU.REGISTRY.ADDRESS.INPUT")}
+              />,
+            )}
+          </FormItem>
+
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.USERNAME")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("username", {
+              initialValue: username,
+            })(
+              <Input
+                placeholder={getIntlContent("SHENYU.REGISTRY.USERNAME.INPUT")}
+              />,
+            )}
+          </FormItem>
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.PASSPORT")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("password", {
+              initialValue: password,
+            })(
+              <Input
+                placeholder={getIntlContent("SHENYU.REGISTRY.PASSPORT.INPUT")}
+              />,
+            )}
+          </FormItem>
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.NAMESPACE")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("namespace", {
+              rules: [
+                {
+                  max: 128,
+                  message: 
getIntlContent("SHENYU.REGISTRY.DESCRIPTION.LENGTH"),
+                },
+              ],
+              initialValue: namespace,
+            })(
+              <Input
+                placeholder={getIntlContent(
+                  "SHENYU.REGISTRY.DESCRIPTION.INPUT",
+                )}
+              />,
+            )}
+          </FormItem>
+          <FormItem
+            label={getIntlContent("SHENYU.REGISTRY.GROUP")}
+            {...formItemLayout}
+          >
+            {getFieldDecorator("group", {
+              initialValue: group,
+            })(
+              <Input
+                placeholder={getIntlContent(
+                  "SHENYU.REGISTRY.DESCRIPTION.INPUT",
+                )}
+              />,
+            )}
+          </FormItem>
+        </Form>
+      </Modal>
+    );
+  }
+}
+
+export default Form.create()(AddModal);
diff --git a/src/routes/System/Registry/index.js 
b/src/routes/System/Registry/index.js
new file mode 100755
index 00000000..b89d057e
--- /dev/null
+++ b/src/routes/System/Registry/index.js
@@ -0,0 +1,424 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { Component } from "react";
+import { Table, Button, Popconfirm, message, Input, Tag, Popover } from "antd";
+import { connect } from "dva";
+import { resizableComponents } from "../../../utils/resizable";
+import AddModal from "./AddModal";
+import { getCurrentLocale, getIntlContent } from "../../../utils/IntlUtils";
+import AuthButton from "../../../utils/AuthButton";
+
+@connect(({ registry, loading, global }) => ({
+  registry,
+  language: global.language,
+  loading: loading.effects["registry/fetch"],
+}))
+export default class Registry extends Component {
+  components = resizableComponents;
+
+  constructor(props) {
+    super(props);
+    this.state = {
+      currentPage: 1,
+      pageSize: 12,
+      selectedRowKeys: [],
+      registryId: "",
+      address: "",
+      popup: "",
+      localeName: window.sessionStorage.getItem("locale")
+        ? window.sessionStorage.getItem("locale")
+        : "en-US",
+      columns: [],
+    };
+  }
+
+  componentDidMount() {
+    this.initColumns();
+    this.query();
+  }
+
+  componentDidUpdate() {
+    const { language } = this.props;
+    const { localeName } = this.state;
+    if (language !== localeName) {
+      this.initColumns();
+      this.changeLocale(language);
+    }
+  }
+
+  /**
+   * condition query page list
+   */
+  query = () => {
+    const { dispatch } = this.props;
+    const { registryId, address, currentPage, pageSize } = this.state;
+    dispatch({
+      type: "registry/fetch",
+      payload: {
+        registryId,
+        address,
+        currentPage,
+        pageSize,
+      },
+    });
+  };
+
+  pageOnchange = (page) => {
+    this.setState({ currentPage: page }, this.query);
+  };
+
+  onShowSizeChange = (currentPage, pageSize) => {
+    this.setState({ currentPage: 1, pageSize }, this.query);
+  };
+
+  /**
+   * close model
+   * @param reset after is reset search condition
+   */
+  closeModal = (reset = false) => {
+    this.setState(
+      reset
+        ? { popup: "", currentPage: 1, registryId: "", address: "" }
+        : { popup: "" },
+      this.query,
+    );
+  };
+
+  registryIdOnchange = (e) => {
+    this.setState({ registryId: e.target.value, currentPage: 1 });
+  };
+
+  addressOnchange = (e) => {
+    this.setState({ address: e.target.value, currentPage: 1 });
+  };
+
+  searchClick = () => {
+    this.setState({ currentPage: 1 }, this.query);
+  };
+
+  editClick = (record) => {
+    const { dispatch } = this.props;
+    const { currentPage, pageSize } = this.state;
+    dispatch({
+      type: "registry/getDetail",
+      payload: {
+        id: record.id,
+      },
+      callback: (registry) => {
+        this.setState({
+          popup: (
+            <AddModal
+              detail={registry}
+              handleOk={(values) => {
+                dispatch({
+                  type: "registry/update",
+                  payload: values,
+                  fetchValue: {
+                    currentPage,
+                    pageSize,
+                  },
+                  callback: () => {
+                    this.closeModal(true);
+                  },
+                });
+              }}
+              handleCancel={() => {
+                this.closeModal();
+              }}
+            />
+          ),
+        });
+      },
+    });
+  };
+
+  addClick = () => {
+    const { currentPage, pageSize } = this.state;
+    this.setState({
+      popup: (
+        <AddModal
+          handleOk={(values) => {
+            const { dispatch } = this.props;
+            dispatch({
+              type: "registry/add",
+              payload: values,
+              fetchValue: {
+                currentPage,
+                pageSize,
+              },
+              callback: () => {
+                this.closeModal(true);
+              },
+            });
+          }}
+          handleCancel={() => {
+            this.closeModal();
+          }}
+        />
+      ),
+    });
+  };
+
+  onSelectChange = (selectedRowKeys) => {
+    this.setState({ selectedRowKeys });
+  };
+
+  deleteClick = () => {
+    const { dispatch } = this.props;
+    const { currentPage, pageSize, selectedRowKeys } = this.state;
+    if (selectedRowKeys && selectedRowKeys.length > 0) {
+      dispatch({
+        type: "registry/delete",
+        payload: {
+          list: selectedRowKeys,
+        },
+        fetchValue: {
+          currentPage,
+          pageSize,
+        },
+        callback: () => {
+          this.setState({ selectedRowKeys: [], currentPage: 1 }, this.query);
+        },
+      });
+    } else {
+      message.destroy();
+      message.warn("Please select data");
+    }
+  };
+
+  handleResize =
+    (index) =>
+    (e, { size }) => {
+      this.setState(({ columns }) => {
+        const nextColumns = [...columns];
+        nextColumns[index] = {
+          ...nextColumns[index],
+          width: size.width,
+        };
+        return { columns: nextColumns };
+      });
+    };
+
+  changeLocale(locale) {
+    this.setState({
+      localeName: locale,
+    });
+    getCurrentLocale(this.state.localeName);
+  }
+
+  initColumns() {
+    this.setState({
+      columns: [
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.REGISTRY_ID"),
+          dataIndex: "registryId",
+          key: "registryId",
+          ellipsis: true,
+          width: 150,
+          sorter: (a, b) =>
+            (a.registryId || "").localeCompare(b.registryId || ""),
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.PROTOCOL"),
+          dataIndex: "protocol",
+          key: "protocol",
+          ellipsis: true,
+          width: 120,
+          render: (text) => {
+            return <Tag color="red">{text ? text.toUpperCase() : ""}</Tag>;
+          },
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.ADDRESS"),
+          dataIndex: "address",
+          key: "address",
+          ellipsis: true,
+          width: 120,
+          render: (text) => (
+            <Popover
+              content={<div style={{ wordBreak: "break-all" }}>{text}</div>}
+            >
+              <div>{text || "--"}</div>
+            </Popover>
+          ),
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.USERNAME"),
+          dataIndex: "username",
+          key: "username",
+          ellipsis: true,
+          width: 100,
+          render: (username) => <span>{username || "--"}</span>,
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.NAMESPACE"),
+          dataIndex: "namespace",
+          key: "namespace",
+          ellipsis: true,
+          width: 100,
+          render: (namespace) => <span>{namespace || "--"}</span>,
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.REGISTRY.GROUP"),
+          dataIndex: "group",
+          key: "group",
+          ellipsis: true,
+          width: 100,
+          render: (group) => <span>{group || "--"}</span>,
+        },
+        {
+          align: "center",
+          title: getIntlContent("SHENYU.COMMON.OPERAT"),
+          dataIndex: "operate",
+          key: "operate",
+          ellipsis: true,
+          width: 80,
+          render: (text, record) => {
+            return (
+              <div className="optionParts">
+                <AuthButton perms="system:registry:edit">
+                  <div
+                    className="edit"
+                    onClick={() => {
+                      this.editClick(record);
+                    }}
+                  >
+                    {getIntlContent("SHENYU.SYSTEM.EDITOR")}
+                  </div>
+                </AuthButton>
+              </div>
+            );
+          },
+        },
+      ],
+    });
+  }
+
+  render() {
+    const { registry, loading } = this.props;
+    const { registryList, total } = registry;
+    const {
+      currentPage,
+      pageSize,
+      selectedRowKeys,
+      registryId,
+      address,
+      popup,
+      columns = [],
+    } = this.state;
+
+    const tableColumns = columns.map((col, index) => ({
+      ...col,
+      onHeaderCell: (column) => ({
+        width: column.width,
+        onResize: this.handleResize(index),
+      }),
+    }));
+
+    const rowSelection = {
+      selectedRowKeys,
+      onChange: this.onSelectChange,
+    };
+
+    return (
+      <div className="plug-content-wrap">
+        <div style={{ display: "flex" }}>
+          <Input
+            allowClear
+            value={registryId}
+            onChange={this.registryIdOnchange}
+            placeholder={getIntlContent("SHENYU.REGISTRY.REGISTRY_ID")}
+            style={{ width: 240 }}
+          />
+          <Input
+            allowClear
+            value={address}
+            onChange={this.addressOnchange}
+            placeholder={getIntlContent("SHENYU.REGISTRY.ADDRESS")}
+            style={{ width: 240, marginLeft: 20 }}
+
+            // onSearch={this.searchClick}
+          />
+          <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
+            <AuthButton perms="system:registry:list">
+              <Button
+                type="primary"
+                onClick={this.searchClick}
+                style={{ marginLeft: 20 }}
+              >
+                {getIntlContent("SHENYU.SYSTEM.SEARCH")}
+              </Button>
+            </AuthButton>
+            <AuthButton perms="system:registry:delete">
+              <Popconfirm
+                title={getIntlContent("SHENYU.COMMON.DELETE")}
+                placement="bottom"
+                onConfirm={() => {
+                  this.deleteClick();
+                }}
+                okText={getIntlContent("SHENYU.COMMON.SURE")}
+                cancelText={getIntlContent("SHENYU.COMMON.CALCEL")}
+              >
+                <Button type="danger" style={{ marginLeft: 20 }}>
+                  {getIntlContent("SHENYU.COMMON.DELETE.NAME")}
+                </Button>
+              </Popconfirm>
+            </AuthButton>
+            <AuthButton perms="system:registry:add">
+              <Button
+                type="primary"
+                onClick={this.addClick}
+                style={{ marginLeft: 20 }}
+              >
+                {getIntlContent("SHENYU.SYSTEM.ADDDATA")}
+              </Button>
+            </AuthButton>
+          </div>
+        </div>
+
+        <Table
+          size="small"
+          components={this.components}
+          style={{ marginTop: 30 }}
+          bordered
+          loading={loading}
+          columns={tableColumns}
+          dataSource={registryList}
+          rowSelection={rowSelection}
+          pagination={{
+            total,
+            showTotal: (showTotal) => `${showTotal}`,
+            showSizeChanger: true,
+            pageSizeOptions: ["12", "20", "50", "100"],
+            current: currentPage,
+            pageSize,
+            onShowSizeChange: this.onShowSizeChange,
+            onChange: this.pageOnchange,
+          }}
+        />
+        {popup}
+      </div>
+    );
+  }
+}
diff --git a/src/services/api.js b/src/services/api.js
index 8dcd2f03..3e5791a0 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -1437,3 +1437,44 @@ export async function importSwagger(params) {
     },
   });
 }
+
+/* Registry Center Management APIs */
+
+/* get registry list */
+export async function getRegistryList(params) {
+  return request(`${baseUrl}/registry/findPageByQuery?${stringify(params)}`, {
+    method: `GET`,
+  });
+}
+
+/* get registry detail */
+export async function getRegistryDetail(params) {
+  return request(`${baseUrl}/registry/${params.id}`, {
+    method: `GET`,
+  });
+}
+
+/* add or update registry */
+export async function insertOrUpdateRegistry(params) {
+  return request(`${baseUrl}/registry/insertOrUpdate`, {
+    method: `POST`,
+    body: {
+      ...params,
+    },
+  });
+}
+
+/* delete registry */
+export async function deleteRegistry(id) {
+  return request(`${baseUrl}/registry/${id}`, {
+    method: `DELETE`,
+  });
+}
+
+/* batch delete registry */
+export async function batchDeleteRegistry(params) {
+  return request(`${baseUrl}/registry/batch`, {
+    method: `DELETE`,
+    body: [...params.list],
+  });
+}

Reply via email to