diff --git a/.dockerignore b/.dockerignore
index 7c3b4c0b7..ec513dc87 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,3 +1,4 @@
 lina
 dist
 node_modules
+.git
diff --git a/src/components/AccountListTable/const.js b/src/components/AccountListTable/const.js
index 3bb920009..07f7f1d04 100644
--- a/src/components/AccountListTable/const.js
+++ b/src/components/AccountListTable/const.js
@@ -1,5 +1,5 @@
-import { ChoicesFormatter } from '@/components/TableFormatters'
 import { toSafeLocalDateStr } from '@/utils/common'
+import ChoicesFormatter from '@/components/TableFormatters/ChoicesFormatter'
 import i18n from '@/i18n/i18n'
 
 export const connectivityMeta = {
@@ -7,9 +7,14 @@ export const connectivityMeta = {
   formatter: ChoicesFormatter,
   formatterArgs: {
     iconChoices: {
-      ok: 'fa-check text-primary',
-      failed: 'fa-times text-danger',
-      unknown: 'fa-circle text-warning'
+      ok: 'fa-check',
+      failed: 'fa-times',
+      unknown: 'fa-circle-o'
+    },
+    classChoices: {
+      ok: 'text-primary',
+      failed: 'text-danger',
+      unknown: 'text-warning'
     },
     hasTips: true,
     getTips: ({ row, cellValue }) => {
diff --git a/src/components/AutoDataTable/index.vue b/src/components/AutoDataTable/index.vue
index bd814f022..88b4eb475 100644
--- a/src/components/AutoDataTable/index.vue
+++ b/src/components/AutoDataTable/index.vue
@@ -1,6 +1,14 @@
 <template>
   <div>
-    <DataTable v-if="!loading" ref="dataTable" v-loading="loading" :config="iConfig" v-bind="$attrs" v-on="$listeners" @filter-change="filterChange" />
+    <DataTable
+      v-if="!loading"
+      ref="dataTable"
+      v-loading="loading"
+      :config="iConfig"
+      v-bind="$attrs"
+      v-on="$listeners"
+      @filter-change="filterChange"
+    />
     <ColumnSettingPopover
       :current-columns="popoverColumns.currentCols"
       :total-columns-list="popoverColumns.totalColumnsList"
@@ -13,7 +21,13 @@
 
 <script type="text/jsx">
 import DataTable from '../DataTable'
-import { DateFormatter, DetailFormatter, DisplayFormatter, BooleanFormatter, ActionsFormatter } from '@/components/TableFormatters'
+import {
+  DateFormatter,
+  DetailFormatter,
+  DisplayFormatter,
+  ActionsFormatter,
+  ChoicesFormatter
+} from '@/components/TableFormatters'
 import i18n from '@/i18n/i18n'
 import ColumnSettingPopover from './components/ColumnSettingPopover'
 import { newURL } from '@/utils/common'
@@ -103,7 +117,7 @@ export default {
           break
         case 'is_valid':
           col.label = i18n.t('common.Validity')
-          col.formatter = BooleanFormatter
+          col.formatter = ChoicesFormatter
           col.align = 'center'
           col.width = '80px'
           break
@@ -123,7 +137,7 @@ export default {
           col.formatter = DisplayFormatter
           break
         case 'boolean':
-          col.formatter = BooleanFormatter
+          col.formatter = ChoicesFormatter
           col.align = 'center'
           col.width = '80px'
           break
diff --git a/src/components/TableFormatters/BooleanFormatter.vue b/src/components/TableFormatters/BooleanFormatter.vue
index c2261ff46..983cdd0f1 100644
--- a/src/components/TableFormatters/BooleanFormatter.vue
+++ b/src/components/TableFormatters/BooleanFormatter.vue
@@ -5,7 +5,7 @@
 <script>
 import BaseFormatter from './base'
 export default {
-  name: 'ChoicesFormatter',
+  name: 'BooleanFormatter',
   extends: BaseFormatter,
   props: {
     formatterArgsDefault: {
@@ -16,6 +16,7 @@ export default {
             true: 'fa-check text-primary',
             false: 'fa-times text-danger'
           },
+          showFalse: true,
           typeChange(val) {
             return !!val
           }
@@ -31,6 +32,9 @@ export default {
   computed: {
     iconClass() {
       const key = this.formatterArgs.typeChange(this.cellValue)
+      if (!key && !this.formatterArgs.showFalse) {
+        return ''
+      }
       return this.formatterArgs.iconChoices[key]
     }
   }
diff --git a/src/components/TableFormatters/ChoicesFormatter.vue b/src/components/TableFormatters/ChoicesFormatter.vue
index 634274010..92a9463f4 100644
--- a/src/components/TableFormatters/ChoicesFormatter.vue
+++ b/src/components/TableFormatters/ChoicesFormatter.vue
@@ -1,11 +1,11 @@
 <template>
-  <div>
-    <el-tooltip v-if="formatterArgs.hasTips" placement="bottom" effect="dark">
-      <div slot="content" v-html="tips" />
-      <i :class="'fa ' + iconClass" />
-    </el-tooltip>
-    <i v-else :class="'fa ' + iconClass" />
-  </div>
+  <el-tooltip v-if="shown" :disabled="!formatterArgs.hasTips" placement="bottom" effect="dark">
+    <div slot="content" v-html="tips" />
+    <span :class="classes">
+      <i v-if="formatterArgs.useIcon" :class="'fa ' + icon" />
+      <span v-if="formatterArgs.useText">{{ text }}</span>
+    </span>
+  </el-tooltip>
 </template>
 
 <script>
@@ -19,13 +19,24 @@ export default {
       default() {
         return {
           iconChoices: {
-            true: 'fa-check text-primary',
-            false: 'fa-times text-danger'
+            true: 'fa-check',
+            false: 'fa-times'
           },
-          getIconKey({ row, cellValue }) {
+          classChoices: {
+            true: 'text-primary',
+            false: 'text-danger'
+          },
+          textChoices: {
+            true: this.$t('common.Yes'),
+            false: this.$t('common.No')
+          },
+          getKey({ row, cellValue }) {
             return cellValue
           },
           hasTips: false,
+          useIcon: true,
+          useText: false,
+          showFalse: true,
           getTips: ({ row, cellValue }) => {
             return cellValue
           }
@@ -39,12 +50,28 @@ export default {
     }
   },
   computed: {
-    iconClass() {
-      const key = this.formatterArgs.getIconKey({ row: this.row, cellValue: this.cellValue })
-      return this.formatterArgs.iconChoices[key]
+    key() {
+      return this.formatterArgs.getKey(
+        { row: this.row, cellValue: this.cellValue }
+      )
+    },
+    icon() {
+      return this.formatterArgs.iconChoices[this.key]
+    },
+    classes() {
+      return this.formatterArgs.classChoices[this.key]
+    },
+    text() {
+      return this.formatterArgs.textChoices[this.key]
     },
     tips() {
       return this.formatterArgs.getTips({ cellValue: this.cellValue, row: this.row })
+    },
+    shown() {
+      if (!this.formatterArgs.showFalse && !this.key) {
+        return false
+      }
+      return true
     }
   }
 }
diff --git a/src/components/TableFormatters/DisplayFormatter.vue b/src/components/TableFormatters/DisplayFormatter.vue
index 4c0485c48..612144a5c 100644
--- a/src/components/TableFormatters/DisplayFormatter.vue
+++ b/src/components/TableFormatters/DisplayFormatter.vue
@@ -1,5 +1,5 @@
 <template>
-  <span>{{ display }}</span>
+  <span :class="cls"> {{ value }}</span>
 </template>
 
 <script>
@@ -19,19 +19,27 @@ export default {
   },
   data() {
     return {
-      display: this.getValue()
+      formatterArgs: Object.assign(this.formatterArgsDefault, this.col.formatterArgs)
     }
   },
-  methods: {
-    getValue() {
-      const formatterArgs = Object.assign(this.formatterArgsDefault, this.col.formatterArgs)
-      const displayKey = formatterArgs.displayKey
+  computed: {
+    value() {
+      const displayKey = this.formatterArgs.displayKey
       let value = this.row[displayKey]
       if (value === undefined) {
         value = this.row[this.col.prop]
       }
       return value
+    },
+    cls() {
+      const classChoices = this.formatterArgs?.classChoices
+      if (!classChoices) {
+        return ''
+      }
+      return classChoices[this.cellValue]
     }
+  },
+  methods: {
   }
 }
 </script>
diff --git a/src/components/TableFormatters/index.js b/src/components/TableFormatters/index.js
index 67de651a5..178ff07a3 100644
--- a/src/components/TableFormatters/index.js
+++ b/src/components/TableFormatters/index.js
@@ -1,7 +1,6 @@
 import DetailFormatter from './DetailFormatter'
 import ArrayFormatter from './ArrayFormatter'
 import DisplayFormatter from './DisplayFormatter'
-import BooleanFormatter from './BooleanFormatter'
 import ChoicesFormatter from './ChoicesFormatter'
 import ActionsFormatter from './ActionsFormatter'
 import DeleteActionFormatter from './DeleteActionFormatter'
@@ -15,7 +14,6 @@ import StatusFormatter from './StatusFormatter'
 export default {
   DetailFormatter,
   DisplayFormatter,
-  BooleanFormatter,
   ChoicesFormatter,
   ActionsFormatter,
   DeleteActionFormatter,
@@ -31,7 +29,6 @@ export default {
 export {
   DetailFormatter,
   DisplayFormatter,
-  BooleanFormatter,
   ChoicesFormatter,
   ActionsFormatter,
   DeleteActionFormatter,
diff --git a/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue b/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue
index 0c97fa8b6..368da7053 100644
--- a/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue
+++ b/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue
@@ -4,7 +4,6 @@
 
 <script>
 import GenericListTable from '@/layout/components/GenericListTable/index'
-import { BooleanFormatter, DateFormatter } from '@/components/TableFormatters'
 
 export default {
   name: 'TaskExecutionList',
@@ -26,33 +25,24 @@ export default {
       },
       tableConfig: {
         url: `/api/v1/xpack/gathered-user/task-executions/?task=${this.object.id}`,
-        columns: [
-          {
-            prop: 'timedelta',
+        columns: ['timedelta', 'date_start', 'success'],
+        columnsMeta: {
+          timedelta: {
             label: this.$t('ops.timeDelta'),
             formatter: function(row) {
               return row.timedelta.toFixed(2) + 's'
-            }
+            },
+            width: null
           },
-          {
-            prop: 'date_start',
-            label: this.$t('common.DateStart'),
-            formatter: DateFormatter
+          date_start: {
+            width: null
           },
-          {
-            prop: 'success',
-            label: this.$t('common.Success'),
-            width: '90px',
-            align: 'center',
-            formatter: BooleanFormatter,
-            formatterArgs: {
-              iconChoices: {
-                false: 'fa-times text-danger',
-                true: 'fa-check text-primary'
-              }
-            }
+          success: {
+            width: null,
+            label: this.$t('common.Success')
           }
-        ]
+        }
+
       }
     }
   }
diff --git a/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue b/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue
index ec643115f..4c61c3adb 100644
--- a/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue
+++ b/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue
@@ -36,7 +36,10 @@ export default {
             width: '100px'
           },
           username_same_with_user: {
-            width: '150px'
+            width: '150px',
+            formatterArgs: {
+              showFalse: false
+            }
           },
           login_mode: {
             width: '120px'
diff --git a/src/views/audits/LoginLogList.vue b/src/views/audits/LoginLogList.vue
index e3e19514b..55164615d 100644
--- a/src/views/audits/LoginLogList.vue
+++ b/src/views/audits/LoginLogList.vue
@@ -17,7 +17,10 @@ export default {
     return {
       tableConfig: {
         url: '/api/v1/audits/login-logs/',
-        columns: ['username', 'type', 'backend', 'ip', 'city', 'user_agent', 'mfa', 'reason', 'status', 'datetime'],
+        columns: [
+          'username', 'type', 'backend', 'ip', 'city',
+          'user_agent', 'mfa', 'reason', 'status', 'datetime'
+        ],
         columnsMeta: {
           username: {
             showOverflowTooltip: true
@@ -33,7 +36,13 @@ export default {
             width: '90px'
           },
           status: {
-            width: '85px'
+            width: '85px',
+            formatterArgs: {
+              classChoices: {
+                true: 'text-primary',
+                false: 'text-danger'
+              }
+            }
           },
           mfa: {
             label: 'MFA',
diff --git a/src/views/sessions/Storage/CommandStorage.vue b/src/views/sessions/Storage/CommandStorage.vue
index 6440f2d7e..e9e37f674 100644
--- a/src/views/sessions/Storage/CommandStorage.vue
+++ b/src/views/sessions/Storage/CommandStorage.vue
@@ -5,7 +5,6 @@
 <script>
 import ListTable from '@/components/ListTable'
 import { SetToDefaultCommandStorage, TestCommandStorage } from '@/api/sessions'
-import { BooleanFormatter } from '@/components/TableFormatters'
 export default {
   name: 'CommandStorage',
   components: {
@@ -56,12 +55,8 @@ export default {
             }
           },
           is_default: {
-            formatter: BooleanFormatter,
             formatterArgs: {
-              iconChoices: {
-                true: 'fa-check text-primary',
-                false: ''
-              }
+              showFalse: false
             },
             align: 'center',
             width: '100px'
diff --git a/src/views/sessions/Storage/ReplayStorage.vue b/src/views/sessions/Storage/ReplayStorage.vue
index bb3467b88..c80f66623 100644
--- a/src/views/sessions/Storage/ReplayStorage.vue
+++ b/src/views/sessions/Storage/ReplayStorage.vue
@@ -4,7 +4,6 @@
 <script>
 import ListTable from '@/components/ListTable'
 import { TestReplayStorage, SetToDefaultReplayStorage } from '@/api/sessions'
-import { BooleanFormatter } from '@/components/TableFormatters'
 export default {
   name: 'ReplayStorage',
   components: {
@@ -61,12 +60,8 @@ export default {
             }
           },
           is_default: {
-            formatter: BooleanFormatter,
             formatterArgs: {
-              iconChoices: {
-                true: 'fa-check text-primary',
-                false: ''
-              }
+              showFalse: false
             },
             align: 'center',
             width: '100px'
diff --git a/src/views/sessions/TerminalList.vue b/src/views/sessions/TerminalList.vue
index a6a79a88b..0db3ec3c5 100644
--- a/src/views/sessions/TerminalList.vue
+++ b/src/views/sessions/TerminalList.vue
@@ -17,7 +17,6 @@
 import { GenericListPage, GenericCreateUpdateForm } from '@/layout/components'
 import Dialog from '@/components/Dialog'
 import Select2 from '@/components/FormFields/Select2'
-import { BooleanFormatter } from '@/components/TableFormatters'
 export default {
   components: {
     GenericListPage,
@@ -94,7 +93,7 @@ export default {
           'name', 'remote_addr', 'session_online',
           'stat.cpu_load',
           'stat.disk_used', 'stat.memory_used',
-          'status_display',
+          'status',
           'is_active', 'is_alive', 'actions'
         ],
         columnsMeta: {
@@ -113,16 +112,25 @@ export default {
             label: this.$t('sessions.systemMemoryUsedPercent'),
             width: '120px'
           },
-          'status_display': {
+          status: {
             label: this.$t('xpack.LoadStatus'),
-            width: '120px'
+            width: '120px',
+            // formatter: DisplayFormatter,
+            filterable: 'custom',
+            formatterArgs: {
+              classChoices: {
+                offline: 'fa fa-chain-broken text-danger',
+                critical: 'fa fa-bolt text-warning',
+                high: 'fa fa-exclamation-triangle text-info',
+                normal: 'fa fa-check text-primary'
+              }
+            }
           },
           remote_addr: {
             sortable: 'custom'
           },
           is_active: {
             label: this.$t('sessions.active'),
-            formatter: BooleanFormatter,
             width: '80px',
             align: 'center'
           },
diff --git a/src/views/users/User/UserList.vue b/src/views/users/User/UserList.vue
index 3d145426d..f7eb8a96a 100644
--- a/src/views/users/User/UserList.vue
+++ b/src/views/users/User/UserList.vue
@@ -46,8 +46,8 @@ export default {
         columns: [
           'name', 'username', 'email', 'phone', 'wechat',
           'groups_display', 'total_role_display', 'source',
-          'is_valid', 'login_blocked', 'mfa_enabled', 'is_expired',
-          'mfa_force_enabled',
+          'is_valid', 'login_blocked', 'mfa_enabled',
+          'mfa_force_enabled', 'is_expired',
           'last_login', 'date_joined', 'date_password_last_updated',
           'comment', 'created_by', 'actions'
         ],
@@ -72,6 +72,22 @@ export default {
             label: this.$t('users.Role'),
             showOverflowTooltip: true
           },
+          mfa_enabled: {
+            label: 'MFA',
+            formatterArgs: {
+              showFalse: false
+            }
+          },
+          mfa_force_enabled: {
+            formatterArgs: {
+              showFalse: false
+            }
+          },
+          is_expired: {
+            formatterArgs: {
+              showFalse: false
+            }
+          },
           groups_display: {
             width: '200px',
             showOverflowTooltip: true
@@ -81,10 +97,10 @@ export default {
               canClone: true,
               hasDelete: hasDelete,
               canUpdate: function({ row }) {
-                return row.can_update
+                return row['can_update']
               },
               canDelete: function({ row }) {
-                return row.can_delete
+                return row['can_delete']
               },
               extraActions: [
                 {
diff --git a/src/views/xpack/Cloud/Account/AccountList.vue b/src/views/xpack/Cloud/Account/AccountList.vue
index 5755f0773..192f0f765 100644
--- a/src/views/xpack/Cloud/Account/AccountList.vue
+++ b/src/views/xpack/Cloud/Account/AccountList.vue
@@ -5,7 +5,6 @@
 <script type="text/jsx">
 import GenericListTable from '@/layout/components/GenericListTable'
 import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun, aws_china, aws_international, huaweicloud, qcloud, azure, azure_international, vmware, nutanix, qingcloud_private, huaweicloud_private, gcp } from '../const'
-import { BooleanFormatter, DetailFormatter } from '@/components/TableFormatters'
 
 export default {
   components: {
@@ -21,10 +20,8 @@ export default {
         ],
         columnsMeta: {
           name: {
-            prop: 'name',
             sortable: true,
             showOverflowTooltip: true,
-            formatter: DetailFormatter,
             formatterArgs: {
               route: 'AccountDetail'
             }
@@ -51,17 +48,6 @@ export default {
                 }
               ]
             }
-          },
-          validity: {
-            width: '90px',
-            align: 'center',
-            formatter: BooleanFormatter,
-            formatterArgs: {
-              iconChoices: {
-                false: 'fa-times text-danger',
-                true: 'fa-check text-primary'
-              }
-            }
           }
         }
       },