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

kirs pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 767c035  [Feature][UI Next] Add alarm instance manage (#8208)
767c035 is described below

commit 767c03551b0130e9f2e14b1956f58f2c2537c602
Author: Amy0104 <[email protected]>
AuthorDate: Wed Jan 26 19:24:59 2022 +0800

    [Feature][UI Next] Add alarm instance manage (#8208)
---
 .../src/components/form/fields.ts                  |  54 ++++++
 .../src/components/form/get-elements-by-json.ts    |  60 +++++++
 .../src/components/form/index.tsx                  |  71 ++++++++
 .../alert-plugin => components/form}/types.ts      |  71 ++++----
 .../index.ts => components/form/use-form.ts}       |  37 ++--
 .../index.ts => components/form/utils.ts}          |  31 ++--
 .../src/locales/modules/en_US.ts                   |  55 ++++++
 .../src/locales/modules/zh_CN.ts                   |  55 ++++++
 .../src/router/modules/security.ts                 |   9 +
 .../src/service/modules/alert-plugin/index.ts      |   7 -
 .../src/service/modules/alert-plugin/types.ts      |   6 +-
 .../src/service/modules/ui-plugins/index.ts        |   4 +-
 .../src/service/modules/ui-plugins/types.ts        |   6 +-
 .../security/alarm-instance-manage/detail.tsx      | 196 +++++++++++++++++++++
 .../alarm-instance-manage/index.module.scss}       |  20 ++-
 .../views/security/alarm-instance-manage/index.tsx | 170 ++++++++++++++++++
 .../security/alarm-instance-manage}/types.ts       |  58 +++---
 .../security/alarm-instance-manage/use-columns.ts  | 100 +++++++++++
 .../security/alarm-instance-manage/use-detail.ts   |  78 ++++++++
 .../security/alarm-instance-manage/use-form.ts     | 131 ++++++++++++++
 .../security/alarm-instance-manage/use-table.ts    |  95 ++++++++++
 .../alarm-instance-manage/use-userinfo.ts}         |  16 +-
 22 files changed, 1206 insertions(+), 124 deletions(-)

diff --git a/dolphinscheduler-ui-next/src/components/form/fields.ts 
b/dolphinscheduler-ui-next/src/components/form/fields.ts
new file mode 100644
index 0000000..1fe4388
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/fields.ts
@@ -0,0 +1,54 @@
+/*
+ * 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 { h } from 'vue'
+import { NInput, NRadio, NRadioGroup, NSpace } from 'naive-ui'
+import type { IFieldParams } from './types'
+
+// TODO Support other widgets later
+// Input
+export function renderInput(params: IFieldParams) {
+  const { props, fields, field } = params
+  return h(NInput, {
+    ...props,
+    value: fields[field],
+    onUpdateValue: (value) => void (fields[field] = value)
+  })
+}
+
+// Radio && RadioGroup
+export function renderRadio(params: IFieldParams) {
+  const { props, fields, field, options } = params
+  if (!options || options.length === 0) {
+    return h(NRadio, {
+      ...props,
+      value: fields[field],
+      onUpdateChecked: (checked) => void (fields[field] = checked)
+    })
+  }
+  return h(
+    NRadioGroup,
+    {
+      value: fields[field],
+      onUpdateValue: (value) => void (fields[field] = value)
+    },
+    () =>
+      h(NSpace, null, () =>
+        options.map((option) => h(NRadio, option, () => option.label))
+      )
+  )
+}
diff --git 
a/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts 
b/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
new file mode 100644
index 0000000..e880370
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
@@ -0,0 +1,60 @@
+/*
+ * 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 * as Field from './fields'
+import { formatValidate } from './utils'
+import type { FormRules } from 'naive-ui'
+import type { IJsonItem } from './types'
+
+export default function getElementByJson(
+  json: IJsonItem[],
+  fields: { [field: string]: any },
+  t: Function,
+  prefix: string
+) {
+  const rules: FormRules = {}
+  const initialValues: { [field: string]: any } = {}
+  const elements = []
+
+  const getElement = (item: IJsonItem) => {
+    const { type, props = {}, field, options } = item
+    // TODO Support other widgets later
+    if (type === 'radio') {
+      return Field.renderRadio({
+        field,
+        fields,
+        props,
+        options
+      })
+    }
+
+    return Field.renderInput({ field, fields, props })
+  }
+
+  for (let item of json) {
+    fields[item.field] = item.value
+    initialValues[item.field] = item.value
+    if (item.validate) rules[item.field] = formatValidate(item.validate)
+    elements.push({
+      label: t(prefix + '.' + item.field),
+      path: item.field,
+      widget: () => getElement(item)
+    })
+  }
+
+  return { rules, elements, initialValues }
+}
diff --git a/dolphinscheduler-ui-next/src/components/form/index.tsx 
b/dolphinscheduler-ui-next/src/components/form/index.tsx
new file mode 100644
index 0000000..f315141
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/index.tsx
@@ -0,0 +1,71 @@
+/*
+ * 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 { defineComponent, PropType, toRefs, h } from 'vue'
+import { NSpin, NGrid, NForm, NFormItemGi } from 'naive-ui'
+import { useForm } from './use-form'
+import type { GridProps, IMeta } from './types'
+
+const props = {
+  meta: {
+    type: Object as PropType<IMeta>,
+    default: {},
+    required: true
+  },
+  layout: {
+    type: Object as PropType<GridProps>
+  },
+  loading: {
+    type: Boolean as PropType<boolean>,
+    default: false
+  }
+}
+
+const Form = defineComponent({
+  name: 'Form',
+  props,
+  setup(props, { expose }) {
+    const { state, ...rest } = useForm()
+    expose({
+      ...rest
+    })
+    return { ...toRefs(state) }
+  },
+  render(props: { meta: IMeta; layout?: GridProps; loading?: boolean }) {
+    const { loading, layout, meta } = props
+    const { elements, ...restFormProps } = meta
+    return (
+      <NSpin show={loading}>
+        <NForm {...restFormProps} ref='formRef'>
+          <NGrid {...layout}>
+            {elements &&
+              elements.map((element) => {
+                const { span = 24, path, widget, ...formItemProps } = element
+                return (
+                  <NFormItemGi {...formItemProps} span={span} path={path}>
+                    {h(widget)}
+                  </NFormItemGi>
+                )
+              })}
+          </NGrid>
+        </NForm>
+      </NSpin>
+    )
+  }
+})
+
+export default Form
diff --git a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts 
b/dolphinscheduler-ui-next/src/components/form/types.ts
similarity index 53%
copy from dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
copy to dolphinscheduler-ui-next/src/components/form/types.ts
index 74d8905..95babad 100644
--- a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
+++ b/dolphinscheduler-ui-next/src/components/form/types.ts
@@ -15,47 +15,54 @@
  * limitations under the License.
  */
 
-interface ListReq {
-  pageNo: number
-  pageSize: number
-  searchVal?: string
-}
+import type {
+  GridProps,
+  FormProps,
+  FormItemGiProps,
+  FormItemRule,
+  FormRules,
+  SelectOption
+} from 'naive-ui'
 
-interface PluginInstanceReq {
-  instanceName: string
-  pluginDefineId: number
-  pluginInstanceParams: string
-}
+type IType = 'input' | 'radio'
+
+type IOption = SelectOption
 
-interface InstanceNameReq {
-  alertInstanceName: string
+interface IFormItem extends FormItemGiProps {
+  widget: any
 }
 
-interface IdReq {
-  id: number
+interface IMeta extends Omit<FormProps, 'model'> {
+  elements?: IFormItem[]
+  model: object
 }
 
-interface UpdatePluginInstanceReq {
-  alertPluginInstanceId: number
-  instanceName: string
-  pluginInstanceParams: string
+interface IFieldParams {
+  field: string
+  props: object
+  fields: { [field: string]: any }
+  options?: IOption[]
 }
 
-interface AlertPluginItem {
-  id: number
-  pluginDefineId: number
-  instanceName: string
-  pluginInstanceParams: string
-  createTime: string
-  updateTime: string
-  alertPluginName: string
+interface IJsonItem {
+  field: string
+  name?: string
+  props?: object
+  title?: string
+  type?: IType
+  validate?: FormItemRule
+  value?: any
+  options?: IOption[]
 }
 
 export {
-  ListReq,
-  PluginInstanceReq,
-  InstanceNameReq,
-  IdReq,
-  UpdatePluginInstanceReq,
-  AlertPluginItem
+  IMeta,
+  IType,
+  IJsonItem,
+  IOption,
+  FormItemRule,
+  FormRules,
+  IFormItem,
+  GridProps,
+  IFieldParams
 }
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts 
b/dolphinscheduler-ui-next/src/components/form/use-form.ts
similarity index 61%
copy from dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
copy to dolphinscheduler-ui-next/src/components/form/use-form.ts
index 553cc48..a5e5e8c 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
+++ b/dolphinscheduler-ui-next/src/components/form/use-form.ts
@@ -15,20 +15,31 @@
  * limitations under the License.
  */
 
-import { axios } from '@/service/service'
-import { PluginTypeReq, IdReq } from './types'
+import { reactive, ref } from 'vue'
 
-export function queryUiPluginsByType(params: PluginTypeReq): any {
-  return axios({
-    url: '/ui-plugins/query-by-type',
-    method: 'get',
-    params
+export function useForm() {
+  const state = reactive({
+    formRef: ref()
   })
-}
 
-export function queryUiPluginDetailById(id: IdReq): any {
-  return axios({
-    url: `/ui-plugins/${id}`,
-    method: 'get'
-  })
+  const validate = () => {
+    state.formRef.validate()
+  }
+
+  const setValues = (initialValues: { [field: string]: any }) => {
+    for (let [key, value] of Object.entries(initialValues)) {
+      state.formRef.model[key] = value
+    }
+  }
+
+  const restoreValidation = () => {
+    state.formRef.restoreValidation()
+  }
+
+  return {
+    state,
+    validate,
+    setValues,
+    restoreValidation
+  }
 }
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts 
b/dolphinscheduler-ui-next/src/components/form/utils.ts
similarity index 59%
copy from dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
copy to dolphinscheduler-ui-next/src/components/form/utils.ts
index 553cc48..20c5df1 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
+++ b/dolphinscheduler-ui-next/src/components/form/utils.ts
@@ -14,21 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import type { FormRules, FormItemRule } from './types'
 
-import { axios } from '@/service/service'
-import { PluginTypeReq, IdReq } from './types'
-
-export function queryUiPluginsByType(params: PluginTypeReq): any {
-  return axios({
-    url: '/ui-plugins/query-by-type',
-    method: 'get',
-    params
-  })
+export function formatLabel(label?: string): string {
+  if (!label) return ''
+  const match = label.match(/^\$t\('(\S*)'\)/)
+  return match ? match[1] : label
 }
 
-export function queryUiPluginDetailById(id: IdReq): any {
-  return axios({
-    url: `/ui-plugins/${id}`,
-    method: 'get'
-  })
+export function formatValidate(
+  validate?: FormItemRule | FormRules
+): FormItemRule {
+  if (!validate) return {}
+  if (Array.isArray(validate)) {
+    validate.map((item: FormItemRule) => {
+      if (!item?.message) delete item.message
+      return item
+    })
+  }
+  if (!validate.message) delete validate.message
+  return validate
 }
diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts 
b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index 709966e..0ed8489 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -482,6 +482,61 @@ const security = {
     delete: 'Delete',
     save_error_msg: 'Failed to save, please retry',
     delete_error_msg: 'Failed to delete, please retry'
+  },
+  alarm_instance: {
+    search_input_tips: 'Please input the keywords',
+    alarm_instance_manage: 'Alarm instance manage',
+    alarm_instance: 'Alarm Instance',
+    serial_number: '#',
+    alarm_instance_name: 'Alarm instance name',
+    alarm_instance_name_tips: 'Please enter alarm plugin instance name',
+    alarm_plugin_name: 'Alarm plugin name',
+    create_time: 'Create Time',
+    update_time: 'Update Time',
+    operation: 'Operation',
+    edit: 'Edit',
+    delete: 'Delete',
+    confirm: 'Confirm',
+    cancel: 'Cancel',
+    submit: 'Submit',
+    create: 'Create',
+    select_plugin: 'Select plugin',
+    select_plugin_tips: 'Select Alarm plugin',
+    instance_parameter_exception: 'Instance parameter exception',
+    WebHook: 'WebHook',
+    webHook: 'WebHook',
+    IsEnableProxy: 'Enable Proxy',
+    Proxy: 'Proxy',
+    Port: 'Port',
+    User: 'User',
+    corpId: 'CorpId',
+    secret: 'Secret',
+    Secret: 'Secret',
+    users: 'Users',
+    userSendMsg: 'UserSendMsg',
+    agentId: 'AgentId',
+    showType: 'Show Type',
+    receivers: 'Receivers',
+    receiverCcs: 'ReceiverCcs',
+    serverHost: 'SMTP Host',
+    serverPort: 'SMTP Port',
+    sender: 'Sender',
+    enableSmtpAuth: 'SMTP Auth',
+    Password: 'Password',
+    starttlsEnable: 'SMTP STARTTLS Enable',
+    sslEnable: 'SMTP SSL Enable',
+    smtpSslTrust: 'SMTP SSL Trust',
+    url: 'URL',
+    requestType: 'Request Type',
+    headerParams: 'Headers',
+    bodyParams: 'Body',
+    contentField: 'Content Field',
+    Keyword: 'Keyword',
+    userParams: 'User Params',
+    path: 'Script Path',
+    type: 'Type',
+    sendType: 'Send Type',
+    username: 'Username'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts 
b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index fab3be9..273c60f 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -479,6 +479,61 @@ const security = {
     delete: '删除',
     save_error_msg: '保存失败,请重试',
     delete_error_msg: '删除失败,请重试'
+  },
+  alarm_instance: {
+    search_input_tips: '请输入关键字',
+    alarm_instance_manage: '告警实例管理',
+    alarm_instance: '告警实例',
+    serial_number: '编号',
+    alarm_instance_name: '告警实例名称',
+    alarm_instance_name_tips: '请输入告警实例名称',
+    alarm_plugin_name: '告警插件名称',
+    create_time: '创建时间',
+    update_time: '更新时间',
+    operation: '操作',
+    edit: '编辑',
+    delete: '删除',
+    confirm: '确定',
+    cancel: '取消',
+    submit: '提交',
+    create: '创建',
+    select_plugin: '选择插件',
+    select_plugin_tips: '请选择告警插件',
+    instance_parameter_exception: '实例参数异常',
+    WebHook: 'Web钩子',
+    webHook: 'Web钩子',
+    IsEnableProxy: '启用代理',
+    Proxy: '代理',
+    Port: '端口',
+    User: '用户',
+    corpId: '企业ID',
+    secret: '密钥',
+    Secret: '密钥',
+    users: '群员',
+    userSendMsg: '群员信息',
+    agentId: '应用ID',
+    showType: '内容展示类型',
+    receivers: '收件人',
+    receiverCcs: '抄送人',
+    serverHost: 'SMTP服务器',
+    serverPort: 'SMTP端口',
+    sender: '发件人',
+    enableSmtpAuth: '请求认证',
+    Password: '密码',
+    starttlsEnable: 'STARTTLS连接',
+    sslEnable: 'SSL连接',
+    smtpSslTrust: 'SSL证书信任',
+    url: 'URL',
+    requestType: '请求方式',
+    headerParams: '请求头',
+    bodyParams: '请求体',
+    contentField: '内容字段',
+    Keyword: '关键词',
+    userParams: '自定义参数',
+    path: '脚本路径',
+    type: '类型',
+    sendType: '发送类型',
+    username: '用户名'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/router/modules/security.ts 
b/dolphinscheduler-ui-next/src/router/modules/security.ts
index ab6d069..6750b81 100644
--- a/dolphinscheduler-ui-next/src/router/modules/security.ts
+++ b/dolphinscheduler-ui-next/src/router/modules/security.ts
@@ -91,6 +91,15 @@ export default {
         title: '令牌管理管理',
         showSide: true
       }
+    },
+    {
+      path: '/security/alarm-instance-manage',
+      name: 'alarm-instance-manage',
+      component: components['security-alarm-instance-manage'],
+      meta: {
+        title: '告警实例管理',
+        showSide: true
+      }
     }
   ]
 }
diff --git a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/index.ts 
b/dolphinscheduler-ui-next/src/service/modules/alert-plugin/index.ts
index 68c03f3..c6f5f30 100644
--- a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/index.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/alert-plugin/index.ts
@@ -40,13 +40,6 @@ export function createAlertPluginInstance(data: 
PluginInstanceReq): any {
   })
 }
 
-export function queryAlertPluginInstanceList(): any {
-  return axios({
-    url: '/alert-plugin-instances/list',
-    method: 'get'
-  })
-}
-
 export function verifyAlertInstanceName(params: InstanceNameReq): any {
   return axios({
     url: '/alert-plugin-instances/verify-name',
diff --git a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts 
b/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
index 74d8905..dca86a4 100644
--- a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
@@ -31,10 +31,6 @@ interface InstanceNameReq {
   alertInstanceName: string
 }
 
-interface IdReq {
-  id: number
-}
-
 interface UpdatePluginInstanceReq {
   alertPluginInstanceId: number
   instanceName: string
@@ -51,6 +47,8 @@ interface AlertPluginItem {
   alertPluginName: string
 }
 
+type IdReq = number
+
 export {
   ListReq,
   PluginInstanceReq,
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts 
b/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
index 553cc48..1a9e99a 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/ui-plugins/index.ts
@@ -16,7 +16,7 @@
  */
 
 import { axios } from '@/service/service'
-import { PluginTypeReq, IdReq } from './types'
+import { PluginTypeReq, IPluginId } from './types'
 
 export function queryUiPluginsByType(params: PluginTypeReq): any {
   return axios({
@@ -26,7 +26,7 @@ export function queryUiPluginsByType(params: PluginTypeReq): 
any {
   })
 }
 
-export function queryUiPluginDetailById(id: IdReq): any {
+export function queryUiPluginDetailById(id: IPluginId): any {
   return axios({
     url: `/ui-plugins/${id}`,
     method: 'get'
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts 
b/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
index 82bec60..785abcb 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
@@ -19,8 +19,6 @@ interface PluginTypeReq {
   pluginType: 'ALERT' | 'REGISTER' | 'TASK'
 }
 
-interface IdReq {
-  id: number
-}
+type IPluginId = number
 
-export { PluginTypeReq, IdReq }
+export { PluginTypeReq, IPluginId }
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/detail.tsx 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/detail.tsx
new file mode 100644
index 0000000..a426484
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/detail.tsx
@@ -0,0 +1,196 @@
+/*
+ * 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 { defineComponent, PropType, toRefs, watch, onMounted, ref } from 'vue'
+import { NSelect, NInput } from 'naive-ui'
+import Modal from '@/components/modal'
+import Form from '@/components/form'
+import { useI18n } from 'vue-i18n'
+import { useForm } from './use-form'
+import { useDetail } from './use-detail'
+import getElementByJson from '@/components/form/get-elements-by-json'
+import type { IRecord, FormRules, IFormItem } from './types'
+
+const props = {
+  show: {
+    type: Boolean as PropType<boolean>,
+    default: false
+  },
+  currentRecord: {
+    type: Object as PropType<IRecord>,
+    default: {}
+  }
+}
+
+const DetailModal = defineComponent({
+  name: 'DetailModal',
+  props,
+  emits: ['cancel', 'update'],
+  setup(props, ctx) {
+    const { t } = useI18n()
+
+    const rules = ref<FormRules>({})
+    const elements = ref<IFormItem[]>([])
+
+    const {
+      meta,
+      state,
+      setDetail,
+      initForm,
+      resetForm,
+      getFormValues,
+      changePlugin
+    } = useForm()
+
+    const { status, createOrUpdate } = useDetail(getFormValues)
+
+    const onCancel = () => {
+      resetForm()
+      ctx.emit('cancel')
+    }
+
+    const onSubmit = async () => {
+      await state.detailFormRef.validate()
+      const res = await createOrUpdate(props.currentRecord, state.json)
+      if (res) {
+        onCancel()
+        ctx.emit('update')
+      }
+    }
+
+    const onChangePlugin = changePlugin
+
+    watch(
+      () => props.show,
+      async () => {
+        props.show && props.currentRecord && setDetail(props.currentRecord)
+      }
+    )
+    watch(
+      () => state.json,
+      () => {
+        const { rules: fieldsRules, elements: fieldsElements } =
+          getElementByJson(
+            state.json,
+            state.detailForm,
+            t,
+            'security.alarm_instance'
+          )
+        rules.value = fieldsRules
+        elements.value = fieldsElements
+      }
+    )
+
+    onMounted(() => {
+      initForm()
+    })
+
+    return {
+      t,
+      ...toRefs(state),
+      ...toRefs(status),
+      meta,
+      rules,
+      elements,
+      onChangePlugin,
+      onSubmit,
+      onCancel
+    }
+  },
+  render(props: { currentRecord: IRecord }) {
+    const {
+      show,
+      t,
+      meta,
+      rules,
+      elements,
+      detailForm,
+      uiPlugins,
+      pluginsLoading,
+      loading,
+      saving,
+      onChangePlugin,
+      onCancel,
+      onSubmit
+    } = this
+    const { currentRecord } = props
+    return (
+      <Modal
+        show={show}
+        title={`${t(
+          currentRecord?.id
+            ? 'security.alarm_instance.edit'
+            : 'security.alarm_instance.create'
+        )} ${t('security.alarm_instance.alarm_instance')}`}
+        onConfirm={onSubmit}
+        confirmLoading={saving || loading}
+        onCancel={() => void onCancel()}
+      >
+        {{
+          default: () => (
+            <Form
+              ref='detailFormRef'
+              loading={loading || pluginsLoading}
+              meta={{
+                ...meta,
+                rules: {
+                  ...meta.rules,
+                  ...rules
+                },
+                elements: [
+                  {
+                    path: 'instanceName',
+                    label: t('security.alarm_instance.alarm_instance_name'),
+                    widget: (
+                      <NInput
+                        v-model={[detailForm.instanceName, 'value']}
+                        placeholder={t(
+                          'security.alarm_instance.alarm_instance_name_tips'
+                        )}
+                      />
+                    )
+                  },
+                  {
+                    path: 'pluginDefineId',
+                    label: t('security.alarm_instance.select_plugin'),
+                    widget: (
+                      <NSelect
+                        v-model={[detailForm.pluginDefineId, 'value']}
+                        options={uiPlugins}
+                        disabled={!!currentRecord?.id}
+                        placeholder={t(
+                          'security.alarm_instance.select_plugin_tips'
+                        )}
+                        on-update:value={onChangePlugin}
+                      />
+                    )
+                  },
+                  ...elements
+                ]
+              }}
+              layout={{
+                cols: 24
+              }}
+            />
+          )
+        }}
+      </Modal>
+    )
+  }
+})
+
+export default DetailModal
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.module.scss
similarity index 78%
copy from dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
copy to 
dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.module.scss
index 82bec60..fc5f4cc 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.module.scss
@@ -15,12 +15,18 @@
  * limitations under the License.
  */
 
-interface PluginTypeReq {
-  pluginType: 'ALERT' | 'REGISTER' | 'TASK'
+.conditions {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
 }
-
-interface IdReq {
-  id: number
+.conditions-search-input {
+  width: 250px;
+}
+.pagination {
+  margin-top: 20px;
+  justify-content: center;
+}
+.mt-8 {
+  margin-top: 8px;
 }
-
-export { PluginTypeReq, IdReq }
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.tsx 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.tsx
new file mode 100644
index 0000000..0c3b086
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/index.tsx
@@ -0,0 +1,170 @@
+/*
+ * 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 { defineComponent, onMounted, ref, toRefs } from 'vue'
+import {
+  NButton,
+  NInput,
+  NIcon,
+  NDataTable,
+  NPagination,
+  NSpace
+} from 'naive-ui'
+import Card from '@/components/card'
+import DetailModal from './detail'
+import { SearchOutlined } from '@vicons/antd'
+import { useI18n } from 'vue-i18n'
+import { useUserInfo } from './use-userinfo'
+import { useColumns } from './use-columns'
+import { useTable } from './use-table'
+import styles from './index.module.scss'
+import type { IRecord } from './types'
+
+const AlarmInstanceManage = defineComponent({
+  name: 'alarm-instance-manage',
+  setup() {
+    const { t } = useI18n()
+    const showDetailModal = ref(false)
+    const currentRecord = ref()
+
+    const { IS_ADMIN } = useUserInfo()
+
+    const { columnsRef } = useColumns(
+      (record: IRecord, type: 'edit' | 'delete') => {
+        if (type === 'edit') {
+          showDetailModal.value = true
+          currentRecord.value = record
+        } else {
+          deleteRecord(record.id)
+        }
+      }
+    )
+
+    const { data, changePage, changePageSize, deleteRecord, updateList } =
+      useTable()
+
+    const onCreate = () => {
+      currentRecord.value = null
+      showDetailModal.value = true
+    }
+
+    const onCloseModal = () => {
+      showDetailModal.value = false
+      currentRecord.value = {}
+    }
+
+    onMounted(() => {
+      changePage(1)
+    })
+
+    return {
+      t,
+      IS_ADMIN,
+      showDetailModal,
+      currentRecord: currentRecord,
+      columnsRef,
+      ...toRefs(data),
+      changePage,
+      changePageSize,
+      onCreate,
+      onCloseModal,
+      onUpdatedList: updateList
+    }
+  },
+  render() {
+    const {
+      t,
+      IS_ADMIN,
+      currentRecord,
+      showDetailModal,
+      columnsRef,
+      list,
+      page,
+      pageSize,
+      itemCount,
+      loading,
+      changePage,
+      changePageSize,
+      onCreate,
+      onUpdatedList,
+      onCloseModal
+    } = this
+
+    return (
+      <>
+        <Card title=''>
+          {{
+            default: () => (
+              <div class={styles['conditions']}>
+                {IS_ADMIN && (
+                  <NButton onClick={onCreate} type='primary'>{`${t(
+                    'security.alarm_instance.create'
+                  )} ${t('security.alarm_instance.alarm_instance')}`}</NButton>
+                )}
+                <NSpace
+                  class={styles['conditions-search']}
+                  justify='end'
+                  wrap={false}
+                >
+                  <div class={styles['conditions-search-input']}>
+                    <NInput
+                      v-model={[this.searchVal, 'value']}
+                      placeholder={`${t(
+                        'security.alarm_instance.search_input_tips'
+                      )}`}
+                    />
+                  </div>
+                  <NButton type='primary' onClick={onUpdatedList}>
+                    <NIcon>
+                      <SearchOutlined />
+                    </NIcon>
+                  </NButton>
+                </NSpace>
+              </div>
+            )
+          }}
+        </Card>
+        <Card title='' class={styles['mt-8']}>
+          <NDataTable
+            columns={columnsRef}
+            data={list}
+            loading={loading}
+            striped
+          />
+          <NPagination
+            page={page}
+            page-size={pageSize}
+            item-count={itemCount}
+            show-quick-jumper
+            class={styles['pagination']}
+            on-update:page={changePage}
+            on-update:page-size={changePageSize}
+          />
+        </Card>
+        {IS_ADMIN && (
+          <DetailModal
+            show={showDetailModal}
+            currentRecord={currentRecord}
+            onCancel={onCloseModal}
+            onUpdate={onUpdatedList}
+          />
+        )}
+      </>
+    )
+  }
+})
+export default AlarmInstanceManage
diff --git a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/types.ts
similarity index 58%
copy from dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
copy to 
dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/types.ts
index 74d8905..12188f3 100644
--- a/dolphinscheduler-ui-next/src/service/modules/alert-plugin/types.ts
+++ b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/types.ts
@@ -15,47 +15,37 @@
  * limitations under the License.
  */
 
-interface ListReq {
-  pageNo: number
-  pageSize: number
-  searchVal?: string
-}
-
-interface PluginInstanceReq {
-  instanceName: string
-  pluginDefineId: number
-  pluginInstanceParams: string
-}
-
-interface InstanceNameReq {
-  alertInstanceName: string
-}
+import type { IPluginId } from '@/service/modules/ui-plugins/types'
+import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
+import type { IMeta, IJsonItem, IFormItem } from '@/components/form/types'
+import type { FormRules } from 'naive-ui'
 
-interface IdReq {
+interface IRecord {
+  alertPluginName?: string
+  createTime?: string
   id: number
-}
-
-interface UpdatePluginInstanceReq {
-  alertPluginInstanceId: number
   instanceName: string
-  pluginInstanceParams: string
+  pluginDefineId: number
+  pluginInstanceParams?: string
+  updateTime?: string
 }
 
-interface AlertPluginItem {
+interface IPlugin {
   id: number
-  pluginDefineId: number
-  instanceName: string
-  pluginInstanceParams: string
-  createTime: string
-  updateTime: string
-  alertPluginName: string
+  pluginName: string
+  pluginParams?: string
+  pluginType?: string
+  createTime?: string
+  updateTime?: string
 }
 
 export {
-  ListReq,
-  PluginInstanceReq,
-  InstanceNameReq,
-  IdReq,
-  UpdatePluginInstanceReq,
-  AlertPluginItem
+  IPluginId,
+  IRecord,
+  IPlugin,
+  IJsonItem,
+  IMeta,
+  IFormItem,
+  TableColumns,
+  FormRules
 }
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-columns.ts
 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-columns.ts
new file mode 100644
index 0000000..f87574b
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-columns.ts
@@ -0,0 +1,100 @@
+/*
+ * 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 { h } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { NButton, NIcon, NPopconfirm, NSpace } from 'naive-ui'
+import { EditOutlined, DeleteOutlined } from '@vicons/antd'
+import { TableColumns } from './types'
+
+export function useColumns(onCallback: Function) {
+  const { t } = useI18n()
+
+  const columnsRef: TableColumns = [
+    {
+      title: t('security.alarm_instance.serial_number'),
+      key: 'index',
+      render: (rowData, rowIndex) => rowIndex + 1
+    },
+    {
+      title: t('security.alarm_instance.alarm_instance_name'),
+      key: 'instanceName'
+    },
+    {
+      title: t('security.alarm_instance.alarm_plugin_name'),
+      key: 'alertPluginName'
+    },
+    {
+      title: t('security.alarm_instance.create_time'),
+      key: 'createTime'
+    },
+    {
+      title: t('security.alarm_instance.update_time'),
+      key: 'updateTime'
+    },
+    {
+      title: t('security.alarm_instance.operation'),
+      key: 'operation',
+      width: 150,
+      render: (rowData, rowIndex) => {
+        return h(NSpace, null, {
+          default: () => [
+            h(
+              NButton,
+              {
+                circle: true,
+                type: 'info',
+                onClick: () => void onCallback(rowData, 'edit')
+              },
+              {
+                default: () =>
+                  h(NIcon, null, { default: () => h(EditOutlined) })
+              }
+            ),
+            h(
+              NPopconfirm,
+              {
+                onPositiveClick: () => void onCallback(rowData, 'delete'),
+                negativeText: t('security.alarm_instance.cancel'),
+                positiveText: t('security.alarm_instance.confirm')
+              },
+              {
+                trigger: () =>
+                  h(
+                    NButton,
+                    {
+                      circle: true,
+                      type: 'error'
+                    },
+                    {
+                      default: () =>
+                        h(NIcon, null, { default: () => h(DeleteOutlined) })
+                    }
+                  ),
+                default: () => t('security.alarm_instance.delete')
+              }
+            )
+          ]
+        })
+      }
+    }
+  ]
+
+  return {
+    columnsRef
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-detail.ts
 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-detail.ts
new file mode 100644
index 0000000..05efe48
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-detail.ts
@@ -0,0 +1,78 @@
+/*
+ * 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 { reactive } from 'vue'
+import {
+  createAlertPluginInstance,
+  updateAlertPluginInstance,
+  verifyAlertInstanceName
+} from '@/service/modules/alert-plugin'
+import type { IJsonItem, IRecord } from './types'
+
+export function useDetail(getFormValues: Function) {
+  const status = reactive({
+    saving: false,
+    loading: false
+  })
+
+  const formatParams = (
+    json?: IJsonItem[],
+    values: { [field: string]: any } = {}
+  ): string => {
+    json?.forEach((item) => {
+      item.value = values[item.field]
+    })
+    return JSON.stringify(json)
+  }
+
+  const createOrUpdate = async (currentRecord: IRecord, json?: IJsonItem[]) => 
{
+    const values = getFormValues()
+    if (status.saving) return false
+    status.saving = true
+    try {
+      if (currentRecord?.instanceName !== values.instanceName) {
+        await verifyAlertInstanceName({
+          alertInstanceName: values.instanceName
+        })
+      }
+
+      currentRecord?.id
+        ? await updateAlertPluginInstance(
+            {
+              alertPluginInstanceId: values.pluginDefineId,
+              instanceName: values.instanceName,
+              pluginInstanceParams: formatParams(json, values)
+            },
+            currentRecord.id
+          )
+        : await createAlertPluginInstance({
+            instanceName: values.instanceName,
+            pluginDefineId: values.pluginDefineId,
+            pluginInstanceParams: formatParams(json, values)
+          })
+
+      status.saving = false
+      return true
+    } catch (e) {
+      window.$message.error((e as Error).message)
+      status.saving = false
+      return false
+    }
+  }
+
+  return { status, createOrUpdate }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-form.ts 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-form.ts
new file mode 100644
index 0000000..956f302
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-form.ts
@@ -0,0 +1,131 @@
+/*
+ * 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 { reactive, ref, Ref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import {
+  queryUiPluginsByType,
+  queryUiPluginDetailById
+} from '@/service/modules/ui-plugins'
+import type {
+  IPluginId,
+  IPlugin,
+  FormRules,
+  IMeta,
+  IJsonItem,
+  IRecord
+} from './types'
+
+export function useForm() {
+  const { t } = useI18n()
+
+  const initialValues = {
+    instanceName: '',
+    pluginDefineId: null
+  }
+
+  const state = reactive({
+    detailFormRef: ref(),
+    detailForm: { ...initialValues },
+    uiPlugins: [],
+    pluginsLoading: false,
+    json: []
+  } as { detailFormRef: Ref; json: IJsonItem[]; detailForm: { instanceName: 
string; pluginDefineId: number | null }; pluginsLoading: boolean; uiPlugins: [] 
})
+
+  const meta = {
+    model: state.detailForm,
+    requireMarkPlacement: 'left',
+    labelPlacement: 'left',
+    labelWidth: 180,
+    rules: {
+      instanceName: {
+        trigger: 'input',
+        required: true,
+        message: t('security.alarm_instance.alarm_instance_name_tips')
+      },
+      pluginDefineId: {
+        trigger: ['blur', 'change'],
+        required: true,
+        validator(validte, value) {
+          if (!value && value !== 0) {
+            return new Error(t('security.alarm_instance.select_plugin_tips'))
+          }
+        }
+      }
+    } as FormRules
+  } as IMeta
+
+  const getUiPluginsByType = async () => {
+    if (state.pluginsLoading) return
+    state.pluginsLoading = true
+    try {
+      const plugins = await queryUiPluginsByType({ pluginType: 'ALERT' })
+      state.uiPlugins = plugins.map((plugin: IPlugin) => ({
+        label: plugin.pluginName,
+        value: plugin.id
+      }))
+      state.pluginsLoading = false
+    } catch (err) {
+      state.uiPlugins = []
+      state.pluginsLoading = false
+    }
+  }
+
+  const changePlugin = async (pluginId: IPluginId) => {
+    if (state.pluginsLoading) return
+    state.pluginsLoading = true
+    state.detailForm.pluginDefineId = pluginId
+    try {
+      const { pluginParams } = await queryUiPluginDetailById(pluginId)
+      if (pluginParams) {
+        state.json = JSON.parse(pluginParams)
+      }
+      state.pluginsLoading = false
+    } catch (e) {
+      window.$message.error((e as Error).message)
+      state.pluginsLoading = false
+    }
+  }
+
+  const initForm = () => {
+    getUiPluginsByType()
+  }
+
+  const resetForm = () => {
+    state.detailFormRef.setValues({ ...initialValues })
+    state.json = []
+  }
+
+  const getFormValues = () => state.detailForm
+
+  const setDetail = (record: IRecord) => {
+    state.detailForm.instanceName = record.instanceName
+    state.detailForm.pluginDefineId = record.pluginDefineId
+    if (record.pluginInstanceParams)
+      state.json = JSON.parse(record.pluginInstanceParams)
+  }
+
+  return {
+    meta,
+    state,
+    setDetail,
+    initForm,
+    resetForm,
+    getFormValues,
+    changePlugin
+  }
+}
diff --git 
a/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-table.ts
 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-table.ts
new file mode 100644
index 0000000..fcfe7b2
--- /dev/null
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-table.ts
@@ -0,0 +1,95 @@
+/*
+ * 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 { reactive } from 'vue'
+import {
+  queryAlertPluginInstanceListPaging,
+  deleteAlertPluginInstance
+} from '@/service/modules/alert-plugin'
+import { format } from 'date-fns'
+import type { IRecord } from './types'
+
+export function useTable() {
+  const data = reactive({
+    page: 1,
+    pageSize: 10,
+    itemCount: 0,
+    searchVal: '',
+    list: [],
+    loading: false
+  })
+
+  const getList = async () => {
+    if (data.loading) return
+    data.loading = true
+
+    try {
+      const { totalList, total } = await queryAlertPluginInstanceListPaging({
+        pageNo: data.page,
+        pageSize: data.pageSize,
+        searchVal: data.searchVal
+      })
+      data.loading = false
+      if (!totalList) throw Error()
+      data.list = totalList.map((record: IRecord) => {
+        record.createTime = record.createTime
+          ? format(new Date(record.createTime), 'yyyy-MM-dd HH:mm:ss')
+          : ''
+        record.updateTime = record.updateTime
+          ? format(new Date(record.updateTime), 'yyyy-MM-dd HH:mm:ss')
+          : ''
+        return record
+      })
+
+      data.itemCount = total
+    } catch (e) {
+      if ((e as Error).message) window.$message.error((e as Error).message)
+      data.loading = false
+      data.list = []
+      data.itemCount = 0
+    }
+  }
+
+  const updateList = () => {
+    if (data.list.length === 1 && data.page > 1) {
+      --data.page
+    }
+    getList()
+  }
+
+  const deleteRecord = async (id: number) => {
+    try {
+      const res = await deleteAlertPluginInstance(id)
+      updateList()
+    } catch (e) {
+      window.$message.error((e as Error).message)
+    }
+  }
+
+  const changePage = (page: number) => {
+    data.page = page
+    getList()
+  }
+
+  const changePageSize = (pageSize: number) => {
+    data.page = 1
+    data.pageSize = pageSize
+    getList()
+  }
+
+  return { data, changePage, changePageSize, deleteRecord, updateList }
+}
diff --git a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-userinfo.ts
similarity index 71%
copy from dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
copy to 
dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-userinfo.ts
index 82bec60..968d830 100644
--- a/dolphinscheduler-ui-next/src/service/modules/ui-plugins/types.ts
+++ 
b/dolphinscheduler-ui-next/src/views/security/alarm-instance-manage/use-userinfo.ts
@@ -15,12 +15,14 @@
  * limitations under the License.
  */
 
-interface PluginTypeReq {
-  pluginType: 'ALERT' | 'REGISTER' | 'TASK'
-}
+import { useUserStore } from '@/store/user/user'
+import type { UserInfoRes } from '@/service/modules/users/types'
 
-interface IdReq {
-  id: number
-}
+export function useUserInfo() {
+  const userStore = useUserStore()
+  const userInfo = userStore.getUserInfo as UserInfoRes
 
-export { PluginTypeReq, IdReq }
+  const IS_ADMIN = userInfo.userType === 'ADMIN_USER'
+
+  return { IS_ADMIN }
+}

Reply via email to