From a8a1a56f3d696fd8e53677ba9f0610b46b5205ac Mon Sep 17 00:00:00 2001
From: ibuler <ibuler@qq.com>
Date: Mon, 17 Mar 2025 17:57:20 +0800
Subject: [PATCH] =?UTF-8?q?perf:=20=E7=BB=9F=E4=B8=80=20automations=20?=
 =?UTF-8?q?=E5=8E=86=E5=8F=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Table/TableFormatters/DetailFormatter.vue |   2 +-
 src/components/const.js                       |   2 +
 src/guards.js                                 |   2 +-
 src/router/pam/automations.js                 |   6 +-
 .../Executions/AccountBackupExecutionList.vue | 138 ++-------------
 .../AccountChangeSecretExecutionList.vue      | 154 ++--------------
 .../AccountDiscoverExecutionList.vue          |  34 ++++
 ...ue => AccountDiscoverTaskCreateUpdate.vue} |   0
 .../AccountDiscoverTaskList.vue               |   2 +-
 .../AccountDiscover/TaskDetail/index.vue      |   2 +-
 src/views/accounts/AccountDiscover/index.vue  |   2 +-
 .../AccountPush/AccountPushExecutionList.vue  | 165 ++----------------
 .../BaseExecutionList.vue}                    |  52 +++---
 .../RiskDetect/AccountCheckExecutionList.vue  | 139 ++-------------
 src/views/assets/const.js                     |   3 +-
 15 files changed, 130 insertions(+), 573 deletions(-)
 create mode 100644 src/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue
 rename src/views/accounts/AccountDiscover/{TaskCreateUpdate.vue => AccountDiscoverTaskCreateUpdate.vue} (100%)
 rename src/views/accounts/{AccountDiscover/TaskExecutionList.vue => Automation/BaseExecutionList.vue} (78%)

diff --git a/src/components/Table/TableFormatters/DetailFormatter.vue b/src/components/Table/TableFormatters/DetailFormatter.vue
index 28428b122..4b4a730bd 100644
--- a/src/components/Table/TableFormatters/DetailFormatter.vue
+++ b/src/components/Table/TableFormatters/DetailFormatter.vue
@@ -85,7 +85,7 @@ export default {
     disabled() {
       let can = this.formatterArgs.can
       if (typeof can === 'function') {
-        can = can(this.col)
+        can = can({ col: this.col, row: this.row })
       }
       return !can
     },
diff --git a/src/components/const.js b/src/components/const.js
index a286f472d..438be6fdd 100644
--- a/src/components/const.js
+++ b/src/components/const.js
@@ -69,6 +69,8 @@ export const is_periodic = {
   }
 }
 
+export const taskStatusFormatterMeta = {}
+
 export const periodicMeta = {
   is_periodic,
   interval,
diff --git a/src/guards.js b/src/guards.js
index 3a7dcbc2e..ff4eb7238 100644
--- a/src/guards.js
+++ b/src/guards.js
@@ -16,7 +16,7 @@ router.beforeEach(async(to, from, next) => {
   try {
     await store.dispatch('common/cleanDrawerActionMeta')
     await startup({ to, from, next })
-    if (to.name !== from.name) {
+    if (to.name && from.name && to.name !== from.name) {
       await beforeRouteChange(to, from, next)
     }
     next()
diff --git a/src/router/pam/automations.js b/src/router/pam/automations.js
index 4d0dd27ce..743278a8c 100644
--- a/src/router/pam/automations.js
+++ b/src/router/pam/automations.js
@@ -28,7 +28,7 @@ export default [
       },
       {
         path: 'create',
-        component: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate'),
+        component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
         name: 'AccountDiscoverTaskCreate',
         hidden: true,
         meta: {
@@ -50,7 +50,7 @@ export default [
       },
       {
         path: ':id/update',
-        component: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate'),
+        component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
         name: 'AccountDiscoverTaskUpdate',
         hidden: true,
         meta: {
@@ -62,7 +62,7 @@ export default [
       },
       {
         path: 'executions',
-        component: () => import('@/views/accounts/AccountDiscover/TaskExecutionList.vue'),
+        component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue'),
         name: 'AccountDiscoverTaskExecutionList',
         hidden: true,
         meta: {
diff --git a/src/views/accounts/AccountBackup/Executions/AccountBackupExecutionList.vue b/src/views/accounts/AccountBackup/Executions/AccountBackupExecutionList.vue
index a7ff60a0b..d2cc6bab9 100644
--- a/src/views/accounts/AccountBackup/Executions/AccountBackupExecutionList.vue
+++ b/src/views/accounts/AccountBackup/Executions/AccountBackupExecutionList.vue
@@ -1,140 +1,26 @@
 <template>
-  <div>
-    <GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
-    <ReportDialog :visible.sync="visible" :url="reportUrl" />
-  </div>
+  <BaseExecutionList
+    :automation-route="automationRoute"
+    :detail-route="detailRoute"
+    :resource="resource"
+    :url="url"
+  />
 </template>
 
 <script>
-import GenericListTable from '@/layout/components/GenericListTable/index.vue'
-import { openTaskPage } from '@/utils/jms'
-import { DetailFormatter } from '@/components/Table/TableFormatters'
-import ReportDialog from '@/components/Dialog/ReportDialog.vue'
+import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
 
 export default {
   name: 'AccountBackupExecutionList',
   components: {
-    GenericListTable,
-    ReportDialog
-  },
-  props: {
-    object: {
-      type: Object,
-      required: false,
-      default: () => ({})
-    }
+    BaseExecutionList
   },
   data() {
-    const vm = this
     return {
-      visible: false,
-      reportUrl: '',
-      tableConfig: {
-        url: '/api/v1/accounts/account-backup-plan-executions/',
-        columns: [
-          'automation', 'backup_name', 'trigger',
-          'date_start', 'date_finished', 'duration', 'actions'
-        ],
-        columnsShow: {
-          default: [
-            'automation', 'backup_name', 'trigger',
-            'date_start', 'date_finished', 'actions'
-          ]
-        },
-        columnsMeta: {
-          automation: {
-            label: this.$t('ID'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              route: 'AccountBackupExecutionDetail',
-              getRoute: ({ row }) => ({
-                name: 'AccountBackupExecutionDetail',
-                params: { id: row.id }
-              }),
-              getDrawerTitle: ({ row }) => row.id,
-              getTitle: ({ row }) => row.id.slice(0, 8),
-              drawer: true,
-              can: this.$hasPerm('accounts.view_backupaccountexecution')
-            }
-          },
-          backup_name: {
-            label: this.$t('DisplayName'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              drawer: true,
-              getTitle: ({ row }) => row.automation.name,
-              getDrawerTitle: ({ row }) => row.automation.name,
-              getRoute: ({ row }) => ({
-                name: 'AccountBackupDetail',
-                params: { id: row.automation.id }
-              })
-            },
-            id: ({ row }) => row.automation
-          },
-          duration: {
-            label: this.$t('TimeDelta'),
-            formatter: function(row) {
-              return row.duration + 's'
-            }
-          },
-          actions: {
-            formatterArgs: {
-              hasDelete: false,
-              hasUpdate: false,
-              hasClone: false,
-              extraActions: [
-                {
-                  name: 'log',
-                  type: 'primary',
-                  can: this.$hasPerm('accounts.view_backupaccountexecution'),
-                  title: this.$t('Log'),
-                  callback: function({ row }) {
-                    openTaskPage(row['id'])
-                  }
-                },
-                {
-                  name: 'report',
-                  title: this.$t('Report'),
-                  type: 'success',
-                  can: this.$hasPerm('accounts.view_backupaccountexecution'),
-                  callback: function({ row }) {
-                    vm.visible = true
-                    vm.reportUrl = `/api/v1/accounts/account-backup-plan-executions/${row.id}/report/`
-                  }
-                }
-              ]
-            }
-          }
-        }
-      },
-      headerActions: {
-        searchConfig: {
-          getUrlQuery: true,
-          options: [
-            {
-              label: this.$t('TaskID'),
-              value: 'automation_id'
-            },
-            {
-              label: this.$t('DisplayName'),
-              value: 'automation__name'
-            }
-          ]
-        },
-        hasRefresh: true,
-        hasRightActions: true,
-        hasLeftActions: false,
-        hasMoreActions: false,
-        hasExport: false,
-        hasImport: false,
-        hasCreate: false
-      }
-    }
-  },
-  mounted() {
-    const plan_id = this.$route.query.plan_id
-    if (plan_id !== undefined) {
-      this.tableConfig.url = `${this.tableConfig.url}?plan_id=${plan_id}`
+      url: '/api/v1/accounts/account-backup-plan-executions/',
+      detailRoute: 'AccountBackupExecutionDetail',
+      automationRoute: 'AccountBackupDetail',
+      resource: 'backupaccountexecution'
     }
   }
 }
diff --git a/src/views/accounts/AccountChangeSecret/Executions/AccountChangeSecretExecutionList.vue b/src/views/accounts/AccountChangeSecret/Executions/AccountChangeSecretExecutionList.vue
index 65383ec21..deb777321 100644
--- a/src/views/accounts/AccountChangeSecret/Executions/AccountChangeSecretExecutionList.vue
+++ b/src/views/accounts/AccountChangeSecret/Executions/AccountChangeSecretExecutionList.vue
@@ -1,156 +1,26 @@
 <template>
-  <div>
-    <GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
-    <ReportDialog :visible.sync="visible" :url="reportUrl" />
-  </div>
+  <BaseExecutionList
+    :automation-route="automationRoute"
+    :detail-route="detailRoute"
+    :resource="resource"
+    :url="url"
+  />
 </template>
 
 <script>
-import GenericListTable from '@/layout/components/GenericListTable/index.vue'
-import { openTaskPage } from '@/utils/jms'
-import { DetailFormatter } from '@/components/Table/TableFormatters'
-import ReportDialog from '@/components/Dialog/ReportDialog.vue'
+import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
 
 export default {
   name: 'AccountChangeSecretExecutionList',
   components: {
-    ReportDialog,
-    GenericListTable
+    BaseExecutionList
   },
   data() {
-    const vm = this
     return {
-      visible: false,
-      reportUrl: '',
-      tableConfig: {
-        url: '/api/v1/accounts/change-secret-executions/',
-        columns: [
-          'automation', 'change_secret_name', 'asset_amount', 'node_amount', 'status',
-          'trigger', 'date_start', 'date_finished', 'actions'
-        ],
-        columnsShow: {
-          default: [
-            'automation', 'change_secret_name', 'trigger', 'status',
-            'date_start', 'date_finished', 'actions'
-          ]
-        },
-        columnsMeta: {
-          automation: {
-            label: this.$t('ID'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              route: 'AccountChangeSecretExecutionDetail',
-              getRoute: ({ row }) => ({
-                name: 'AccountChangeSecretExecutionDetail',
-                params: { id: row.id }
-              }),
-              getDrawerTitle: ({ row }) => row.id,
-              getTitle: ({ row }) => row.id.slice(0, 8),
-              drawer: true,
-              can: this.$hasPerm('accounts.view_changesecretexecution')
-            }
-          },
-          change_secret_name: {
-            label: this.$t('DisplayName'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              drawer: true,
-              getDrawerTitle({ row }) {
-                return row.automation.name
-              },
-              getTitle: ({ row }) => row.automation.name,
-              getRoute: ({ row }) => ({
-                name: 'AccountChangeSecretDetail',
-                params: { id: row.automation.id }
-              })
-            },
-            id: ({ row }) => row.automation
-          },
-          asset_amount: {
-            label: this.$t('AssetsOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.asset_amount}</span>
-            }
-          },
-          node_amount: {
-            label: this.$t('NodeOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.node_amount}</span>
-            }
-          },
-          status: {
-            label: this.$t('Result')
-          },
-          actions: {
-            formatterArgs: {
-              hasDelete: false,
-              hasUpdate: false,
-              hasClone: false,
-              extraActions: [
-                {
-                  name: 'log',
-                  type: 'primary',
-                  can: this.$hasPerm('accounts.view_changesecretexecution'),
-                  title: this.$t('Log'),
-                  callback: function({ row }) {
-                    openTaskPage(row['id'])
-                  }
-                },
-                {
-                  name: 'report',
-                  title: this.$t('Report'),
-                  type: 'success',
-                  can: this.$hasPerm('accounts.view_changesecretexecution'),
-                  callback: function({ row }) {
-                    vm.visible = true
-                    vm.reportUrl = `/api/v1/accounts/change-secret-executions/${row.id}/report/`
-                  }
-                },
-                {
-                  name: 'record',
-                  title: this.$t('Record'),
-                  can: this.$hasPerm('accounts.view_changesecretrecord'),
-                  callback: function({ row }) {
-                    return this.$router.push({
-                      name: 'AccountChangeSecretList',
-                      query: {
-                        tab: 'ChangeSecretRecord',
-                        execution_id: row.id
-                      }
-                    })
-                  }
-                }
-              ]
-            }
-          }
-        }
-      },
-      headerActions: {
-        searchConfig: {
-          getUrlQuery: true,
-          options: [
-            {
-              label: this.$t('TaskID'),
-              value: 'automation_id'
-            },
-            {
-              label: this.$t('DisplayName'),
-              value: 'automation__name'
-            }
-          ]
-        },
-        hasLeftActions: false,
-        hasMoreActions: false,
-        hasExport: false,
-        hasImport: false,
-        hasCreate: false
-      }
-    }
-  },
-  mounted() {
-    const automation_id = this.$route.query.automation_id
-    if (automation_id !== undefined) {
-      this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
+      url: '/api/v1/accounts/change-secret-executions/',
+      detailRoute: 'AccountChangeSecretExecutionDetail',
+      automationRoute: 'AccountChangeSecretDetail',
+      resource: 'changesecretexecution'
     }
   }
 }
diff --git a/src/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue b/src/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue
new file mode 100644
index 000000000..6de01dbfd
--- /dev/null
+++ b/src/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue
@@ -0,0 +1,34 @@
+<template>
+  <BaseExecutionList
+    :automation-route="automationRoute"
+    :detail-route="detailRoute"
+    :resource="resource"
+    :url="url"
+  />
+</template>
+
+<script>
+import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
+
+export default {
+  name: 'AccountDiscoverTaskExecutionList',
+  components: {
+    BaseExecutionList
+  },
+  props: {
+    object: {
+      type: Object,
+      required: false,
+      default: () => ({})
+    }
+  },
+  data() {
+    return {
+      url: '/api/v1/accounts/gather-account-executions/',
+      detailRoute: 'AccountDiscoverExecutionDetail',
+      automationRoute: 'AccountDiscoverTaskDetail',
+      resource: 'gatheraccountsexecution'
+    }
+  }
+}
+</script>
diff --git a/src/views/accounts/AccountDiscover/TaskCreateUpdate.vue b/src/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue
similarity index 100%
rename from src/views/accounts/AccountDiscover/TaskCreateUpdate.vue
rename to src/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue
diff --git a/src/views/accounts/AccountDiscover/AccountDiscoverTaskList.vue b/src/views/accounts/AccountDiscover/AccountDiscoverTaskList.vue
index ab284f4e1..c2ee24227 100644
--- a/src/views/accounts/AccountDiscover/AccountDiscoverTaskList.vue
+++ b/src/views/accounts/AccountDiscover/AccountDiscoverTaskList.vue
@@ -21,7 +21,7 @@ export default {
   data() {
     const vm = this
     return {
-      createDrawer: () => import('@/views/accounts/AccountDiscover/TaskCreateUpdate.vue'),
+      createDrawer: () => import('@/views/accounts/AccountDiscover/AccountDiscoverTaskCreateUpdate.vue'),
       detailDrawer: () => import('@/views/accounts/AccountDiscover/TaskDetail/index.vue'),
       showViewSecretDialog: false,
       showTableUpdateDrawer: false,
diff --git a/src/views/accounts/AccountDiscover/TaskDetail/index.vue b/src/views/accounts/AccountDiscover/TaskDetail/index.vue
index 538acafe5..b6e4dcd68 100644
--- a/src/views/accounts/AccountDiscover/TaskDetail/index.vue
+++ b/src/views/accounts/AccountDiscover/TaskDetail/index.vue
@@ -9,7 +9,7 @@
 <script>
 import { GenericDetailPage, TabPage } from '@/layout/components'
 import Detail from './Detail.vue'
-import TaskExecutionList from '../TaskExecutionList.vue'
+import TaskExecutionList from '../AccountDiscoverExecutionList.vue'
 
 export default {
   name: 'AccountDiscoverTaskDetail',
diff --git a/src/views/accounts/AccountDiscover/index.vue b/src/views/accounts/AccountDiscover/index.vue
index 6a0e697b1..e4f120581 100644
--- a/src/views/accounts/AccountDiscover/index.vue
+++ b/src/views/accounts/AccountDiscover/index.vue
@@ -35,7 +35,7 @@ export default {
             title: this.$t('ExecutionHistory'),
             name: 'AccountDiscoverTaskExecutionList',
             hidden: !this.$hasPerm('accounts.view_gatheraccountsexecution'),
-            component: () => import('@/views/accounts/AccountDiscover/TaskExecutionList.vue')
+            component: () => import('@/views/accounts/AccountDiscover/AccountDiscoverExecutionList.vue')
           }
         ]
       }
diff --git a/src/views/accounts/AccountPush/AccountPushExecutionList.vue b/src/views/accounts/AccountPush/AccountPushExecutionList.vue
index 3f39920eb..a57e3850a 100644
--- a/src/views/accounts/AccountPush/AccountPushExecutionList.vue
+++ b/src/views/accounts/AccountPush/AccountPushExecutionList.vue
@@ -1,163 +1,30 @@
 <template>
-  <div>
-    <GenericListTable
-      ref="listTable"
-      :detail-drawer="detailDrawer"
-      :header-actions="headerActions"
-      :table-config="tableConfig"
-    />
-    <ReportDialog :url="reportUrl" :visible.sync="visible" />
-  </div>
+  <BaseExecutionList
+    :automation-route="automationRoute"
+    :detail-drawer="detailDrawer"
+    :detail-route="detailRoute"
+    :resource="resource"
+    :resource-label="resourceLabel"
+    :url="url"
+  />
 </template>
 
 <script>
-import GenericListTable from '@/layout/components/GenericListTable/index.vue'
-import { openTaskPage } from '@/utils/jms'
-import { DetailFormatter } from '@/components/Table/TableFormatters'
-import ReportDialog from '@/components/Dialog/ReportDialog'
+import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
 
 export default {
   name: 'AccountPushExecutionList',
   components: {
-    GenericListTable,
-    ReportDialog
+    BaseExecutionList
   },
   data() {
-    const vm = this
     return {
-      visible: false,
-      reportUrl: '',
-      detailDrawer: () => import('@/views/accounts/AccountPush/ExecutionDetail/index.vue'),
-      tableConfig: {
-        url: '/api/v1/accounts/push-account-executions/',
-        columns: [
-          'automation', 'push_user_name', 'asset_amount', 'node_amount', 'status',
-          'trigger', 'date_start', 'date_finished', 'actions'
-        ],
-        columnsShow: {
-          default: [
-            'automation', 'push_user_name', 'trigger', 'status',
-            'date_start', 'date_finished', 'actions'
-          ]
-        },
-        columnsMeta: {
-          automation: {
-            label: this.$t('ID'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              route: 'AccountPushExecutionDetail',
-              getRoute: ({ row }) => ({
-                name: 'AccountPushExecutionDetail',
-                params: { id: row.id }
-              }),
-              getDrawerTitle: ({ row }) => row.id,
-              getTitle: ({ row }) => row.id.slice(0, 8),
-              drawer: true,
-              can: this.$hasPerm('accounts.view_pushaccountexecution')
-            }
-          },
-          push_user_name: {
-            label: this.$t('DisplayName'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              drawer: true,
-              getTitle: ({ row }) => row.automation?.name,
-              getRoute: ({ row }) => ({
-                name: 'AccountPushDetail',
-                params: { id: row.automation.id }
-              }),
-              getDrawerTitle({ row }) {
-                return row.automation?.name
-              }
-            },
-            id: ({ row }) => row.automation
-          },
-          asset_amount: {
-            label: this.$t('AssetsOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.asset_amount}</span>
-            }
-          },
-          node_amount: {
-            label: this.$t('NodeOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.node_amount}</span>
-            }
-          },
-          status: {
-            label: this.$t('Result')
-          },
-          actions: {
-            formatterArgs: {
-              hasDelete: false,
-              hasUpdate: false,
-              hasClone: false,
-              extraActions: [
-                {
-                  name: 'log',
-                  type: 'primary',
-                  can: this.$hasPerm('accounts.view_pushaccountexecution'),
-                  title: this.$t('Log'),
-                  callback: function({ row }) {
-                    openTaskPage(row['id'])
-                  }
-                },
-                {
-                  name: 'report',
-                  title: this.$t('Report'),
-                  can: this.$hasPerm('accounts.view_pushaccountexecution'),
-                  callback: function({ row }) {
-                    vm.visible = true
-                    vm.reportUrl = `/api/v1/accounts/push-account-executions/${row.id}/report/`
-                  }
-                },
-                {
-                  name: 'record',
-                  title: this.$t('Record'),
-                  can: this.$hasPerm('accounts.view_pushsecretrecord'),
-                  callback: function({ row }) {
-                    return this.$router.push({
-                      name: 'AccountPushList',
-                      query: {
-                        tab: 'AccountPushRecord',
-                        execution_id: row.id
-                      }
-                    })
-                  }
-                }
-              ]
-            }
-          }
-        }
-      },
-      headerActions: {
-        searchConfig: {
-          getUrlQuery: true,
-          options: [
-            {
-              label: this.$t('TaskID'),
-              value: 'automation_id'
-            },
-            {
-              label: this.$t('DisplayName'),
-              value: 'automation__name'
-            }
-          ]
-        },
-        hasSearch: true,
-        hasRefresh: true,
-        hasRightActions: true,
-        hasLeftActions: false,
-        hasMoreActions: false,
-        hasExport: false,
-        hasImport: false
-      }
-    }
-  },
-  mounted() {
-    const automation_id = this.$route.query.automation_id
-    if (automation_id !== undefined) {
-      this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
+      url: '/api/v1/accounts/push-account-executions/',
+      automationRoute: 'AccountPushDetail',
+      detailRoute: 'AccountPushExecutionDetail',
+      resource: 'pushaccountexecution',
+      resourceLabel: this.$t('AccountPushExecution'),
+      detailDrawer: () => import('@/views/accounts/AccountPush/ExecutionDetail/index.vue')
     }
   }
 }
diff --git a/src/views/accounts/AccountDiscover/TaskExecutionList.vue b/src/views/accounts/Automation/BaseExecutionList.vue
similarity index 78%
rename from src/views/accounts/AccountDiscover/TaskExecutionList.vue
rename to src/views/accounts/Automation/BaseExecutionList.vue
index 8c301c8bb..188642b0f 100644
--- a/src/views/accounts/AccountDiscover/TaskExecutionList.vue
+++ b/src/views/accounts/Automation/BaseExecutionList.vue
@@ -1,7 +1,10 @@
 <template>
   <div>
-    <GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
-    <ReportDialog :visible.sync="visible" :url="reportUrl" />
+    <GenericListTable
+      :header-actions="headerActions"
+      :table-config="tableConfig"
+    />
+    <ReportDialog :url="reportUrl" :visible.sync="visible" />
   </div>
 </template>
 
@@ -21,10 +24,21 @@ export default {
     GenericListTable
   },
   props: {
-    object: {
-      type: Object,
-      required: false,
-      default: () => ({})
+    url: {
+      type: String,
+      required: true
+    },
+    detailRoute: {
+      type: String,
+      required: true
+    },
+    automationRoute: {
+      type: String,
+      required: true
+    },
+    resource: {
+      type: String,
+      required: true
     }
   },
   data() {
@@ -36,7 +50,7 @@ export default {
       currentTemplate: null,
       drawerTitle: '',
       tableConfig: {
-        url: '/api/v1/accounts/gather-account-executions/',
+        url: this.url,
         columns: [
           'id', 'automation', 'status', 'trigger',
           'date_start', 'date_finished', 'actions'
@@ -45,10 +59,11 @@ export default {
           id: {
             label: this.$t('ID'),
             formatter: DetailFormatter,
+            width: '100px',
             formatterArgs: {
-              route: 'AccountDiscoverExecutionDetail',
+              route: this.detailRoute,
               getRoute: ({ row }) => ({
-                name: 'AccountDiscoverExecutionDetail',
+                name: this.detailRoute,
                 params: { id: row.id }
               }),
               getTitle: ({ row }) => row.id.slice(0, 8),
@@ -64,19 +79,20 @@ export default {
             width: '135px'
           },
           automation: {
-            label: this.$t('Name'),
+            label: this.$t('Task'),
             formatter: DetailFormatter,
+            minWidth: '180px',
             formatterArgs: {
-              getTitle: ({ row }) => row.automation.name,
+              getTitle: ({ row }) => row.snapshot.name,
               getRoute: ({ row }) => ({
-                name: 'AccountDiscoverTaskDetail',
+                name: this.automationRoute,
                 params: { id: row.automation.id }
               }),
-              getDrawerTitle: ({ row }) => row.automation.name,
+              can: ({ row }) => row.automation?.id,
               drawer: true
             },
             id: ({ row }) => row.automation,
-            can: this.$hasPerm('accounts.view_gatheraccountsexecution')
+            can: this.$hasPerm('accounts.view_' + this.resource)
           },
           date_start: {
             width: null
@@ -99,10 +115,10 @@ export default {
                   name: 'report',
                   title: this.$t('Report'),
                   type: 'success',
-                  can: this.$hasPerm('accounts.view_gatheraccountsexecution'),
+                  can: this.$hasPerm('accounts.view_' + this.resource),
                   callback: function({ row }) {
                     vm.visible = true
-                    vm.reportUrl = `/api/v1/accounts/gather-account-executions/${row.id}/report/`
+                    vm.reportUrl = `${this.url}${row.id}/report/`
                   }
                 }
               ]
@@ -141,10 +157,6 @@ export default {
   methods: {
     handleDetailCallback(row) {
       this.$route.params.id = row.id
-
-      this.$route.query.type = 'pam'
-
-      this.currentTemplate = 'AccountDiscoverExecutionDetail'
       this.showTableUpdateDrawer = true
     }
   }
diff --git a/src/views/accounts/RiskDetect/AccountCheckExecutionList.vue b/src/views/accounts/RiskDetect/AccountCheckExecutionList.vue
index 235487eb2..3d8b1d2b9 100644
--- a/src/views/accounts/RiskDetect/AccountCheckExecutionList.vue
+++ b/src/views/accounts/RiskDetect/AccountCheckExecutionList.vue
@@ -1,21 +1,19 @@
 <template>
-  <div>
-    <GenericListTable ref="listTable" :header-actions="headerActions" :table-config="tableConfig" />
-    <ReportDialog :url="reportUrl" :visible.sync="visible" />
-  </div>
+  <BaseExecutionList
+    :automation-route="automationRoute"
+    :detail-route="detailRoute"
+    :resource="resource"
+    :url="url"
+  />
 </template>
 
 <script>
-import GenericListTable from '@/layout/components/GenericListTable/index.vue'
-import { openTaskPage } from '@/utils/jms'
-import { DetailFormatter } from '@/components/Table/TableFormatters'
-import ReportDialog from '@/components/Dialog/ReportDialog.vue'
+import BaseExecutionList from '@/views/accounts/Automation/BaseExecutionList.vue'
 
 export default {
   name: 'CheckAccountExecutionList',
   components: {
-    ReportDialog,
-    GenericListTable
+    BaseExecutionList
   },
   props: {
     object: {
@@ -25,124 +23,11 @@ export default {
     }
   },
   data() {
-    const vm = this
     return {
-      visible: false,
-      reportUrl: '',
-      tableConfig: {
-        url: '/api/v1/accounts/check-account-executions/',
-        columns: [
-          'automation', 'task_name', 'asset_amount',
-          'node_amount', 'status', 'trigger',
-          'date_start', 'date_finished', 'actions'
-        ],
-        columnsShow: {
-          default: [
-            'automation', 'task_name', 'status',
-            'date_start', 'date_finished', 'actions'
-          ]
-        },
-        columnsMeta: {
-          automation: {
-            label: this.$t('ID'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              getRoute: ({ row }) => ({
-                name: 'RiskHistoryExecutionDetail',
-                params: { id: row.id }
-              }),
-              getTitle: ({ row }) => row.id.slice(0, 8),
-              getDrawerTitle: ({ row }) => row.id,
-              drawer: true,
-              can: this.$hasPerm('accounts.view_checkaccountexecution')
-            }
-          },
-          task_name: {
-            label: this.$t('DisplayName'),
-            formatter: DetailFormatter,
-            formatterArgs: {
-              drawer: true,
-              getTitle: ({ row }) => row.automation.name,
-              getRoute: ({ row }) => ({
-                name: 'AccountCheckDetail',
-                params: { id: row.automation.id }
-              }),
-              getDrawerTitle: ({ row }) => row.automation.name
-            },
-            id: ({ row }) => row.automation
-          },
-          asset_amount: {
-            label: this.$t('AssetsOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.asset_amount}</span>
-            }
-          },
-          node_amount: {
-            label: this.$t('NodeOfNumber'),
-            formatter: function(row) {
-              return <span>{row.snapshot.node_amount}</span>
-            }
-          },
-          status: {
-            label: this.$t('Result')
-          },
-          actions: {
-            formatterArgs: {
-              hasDelete: false,
-              hasUpdate: false,
-              hasClone: false,
-              extraActions: [
-                {
-                  name: 'log',
-                  type: 'primary',
-                  can: this.$hasPerm('accounts.view_checkaccountexecution'),
-                  title: this.$t('Log'),
-                  callback: function({ row }) {
-                    openTaskPage(row['id'])
-                  }
-                },
-                {
-                  name: 'report',
-                  title: this.$t('Report'),
-                  type: 'success',
-                  can: this.$hasPerm('accounts.view_checkaccountexecution'),
-                  callback: function({ row }) {
-                    vm.visible = true
-                    vm.reportUrl = `/api/v1/accounts/check-account-executions/${row.id}/report/`
-                  }
-                }
-              ]
-            }
-          }
-        }
-      },
-      headerActions: {
-        searchConfig: {
-          options: [
-            {
-              label: this.$t('TaskID'),
-              value: 'automation_id'
-            },
-            {
-              label: this.$t('DisplayName'),
-              value: 'automation__name'
-            }
-          ]
-        },
-        hasSearch: true,
-        hasRefresh: true,
-        hasRightActions: true,
-        hasLeftActions: false,
-        hasMoreActions: false,
-        hasExport: false,
-        hasImport: false
-      }
-    }
-  },
-  mounted() {
-    const automation_id = this.$route.query.automation_id
-    if (automation_id !== undefined) {
-      this.tableConfig.url = `${this.tableConfig.url}?automation_id=${automation_id}`
+      url: '/api/v1/accounts/check-account-executions/',
+      automationRoute: 'AccountCheckDetail',
+      detailRoute: 'RiskHistoryExecutionDetail',
+      resource: 'checkaccountexecution'
     }
   }
 }
diff --git a/src/views/assets/const.js b/src/views/assets/const.js
index 1aa6437f2..a0eadd4f1 100644
--- a/src/views/assets/const.js
+++ b/src/views/assets/const.js
@@ -42,8 +42,9 @@ function updatePlatformProtocols(vm, platformType, updateForm, isPlatformChanged
         'username_selector': setting.username_selector
       })
     }
+    // 这里不能清空,比如 gateway 切换时,protocol 没有变化,就会出现 bug, tapd: 1053282
+    // updateForm({ protocols: [] })
     vm.iConfig.fieldsMeta.protocols.el.choices = platformProtocols
-    updateForm({ protocols: [] })
   }), 100)
 }