Просмотр исходного кода

feat: Add Export in some menu
fix: Left menu height
fix: Export csv when double quotation marks in data

lejianwen месяцев назад: 7
Родитель
Сommit
fc7e0595a1

+ 4 - 1
src/layout/components/aside.vue

@@ -13,5 +13,8 @@
13
   })
13
   })
14
 </script>
14
 </script>
15
 
15
 
16
-<style scoped>
16
+<style scoped lang="scss">
17
+.scroll-sidebar {
18
+  background-color: #2d3a4b;
19
+}
17
 </style>
20
 </style>

+ 0 - 1
src/layout/index.vue

@@ -60,7 +60,6 @@
60
 }
60
 }
61
 
61
 
62
 .app-left {
62
 .app-left {
63
-  height: 100%;
64
   transition: width 0.5s;
63
   transition: width 0.5s;
65
 }
64
 }
66
 
65
 

+ 1 - 1
src/utils/file.js

@@ -38,7 +38,7 @@ export function jsonToCsv (data) {
38
   let keys = Object.keys(data[0])
38
   let keys = Object.keys(data[0])
39
   csv += keys.join(',') + '\n'
39
   csv += keys.join(',') + '\n'
40
   data.forEach(row => {
40
   data.forEach(row => {
41
-    csv += keys.map(key => `"${row[key]}"`).join(',') + '\n'
41
+    csv += keys.map(key => `"${row[key].toString().replaceAll('"', '""')}"`).join(',') + '\n'
42
   })
42
   })
43
   return new Blob([csv], { type: 'text/csv' })
43
   return new Blob([csv], { type: 'text/csv' })
44
 }
44
 }

+ 1 - 1
src/utils/i18n/zh_CN.json

@@ -447,7 +447,7 @@
447
     "One": "新密码"
447
     "One": "新密码"
448
   },
448
   },
449
   "NewPasswordEqualOldPassword": {
449
   "NewPasswordEqualOldPassword": {
450
-    "One": "New Password cannot be the same as Old Password"
450
+    "One": "新密码不能与旧密码相同"
451
   },
451
   },
452
   "ConfirmPassword": {
452
   "ConfirmPassword": {
453
     "One": "确认密码"
453
     "One": "确认密码"

Разница между файлами не показана из-за своего большого размера
+ 0 - 4272
src/utils/pca.json


+ 2 - 0
src/views/audit/connList.vue

@@ -11,6 +11,7 @@
11
         <el-form-item>
11
         <el-form-item>
12
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
12
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
13
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
13
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
14
+          <el-button type="success" @click="toExport">{{ T('Export') }}</el-button>
14
         </el-form-item>
15
         </el-form-item>
15
       </el-form>
16
       </el-form>
16
     </el-card>
17
     </el-card>
@@ -62,6 +63,7 @@
62
     handlerQuery,
63
     handlerQuery,
63
     del,
64
     del,
64
     batchdel,
65
     batchdel,
66
+    toExport,
65
   } = useRepositories()
67
   } = useRepositories()
66
 
68
 
67
   onMounted(getList)
69
   onMounted(getList)

+ 2 - 0
src/views/audit/fileList.vue

@@ -11,6 +11,7 @@
11
         <el-form-item>
11
         <el-form-item>
12
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
12
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
13
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
13
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
14
+          <el-button type="success" @click="toExport">{{ T('Export') }}</el-button>
14
         </el-form-item>
15
         </el-form-item>
15
       </el-form>
16
       </el-form>
16
     </el-card>
17
     </el-card>
@@ -109,6 +110,7 @@
109
     handlerQuery,
110
     handlerQuery,
110
     del,
111
     del,
111
     batchdel,
112
     batchdel,
113
+    toExport,
112
   } = useFileRepositories()
114
   } = useFileRepositories()
113
 
115
 
114
   onMounted(getList)
116
   onMounted(getList)

+ 26 - 1
src/views/audit/reponsitories.js

@@ -1,9 +1,9 @@
1
 import { reactive } from 'vue'
1
 import { reactive } from 'vue'
2
 import { list, remove, fileList, fileRemove, batchDelete, fileBatchDelete } from '@/api/audit'
2
 import { list, remove, fileList, fileRemove, batchDelete, fileBatchDelete } from '@/api/audit'
3
 import { ElMessage, ElMessageBox } from 'element-plus'
3
 import { ElMessage, ElMessageBox } from 'element-plus'
4
-import { useRoute } from 'vue-router'
5
 import { formatTime } from '@/utils/time'
4
 import { formatTime } from '@/utils/time'
6
 import { T } from '@/utils/i18n'
5
 import { T } from '@/utils/i18n'
6
+import { downBlob, jsonToCsv } from '@/utils/file'
7
 
7
 
8
 export function useRepositories () {
8
 export function useRepositories () {
9
   const listRes = reactive({
9
   const listRes = reactive({
@@ -73,6 +73,17 @@ export function useRepositories () {
73
       getList()
73
       getList()
74
     }
74
     }
75
   }
75
   }
76
+
77
+  const toExport = async () => {
78
+    const q = { ...listQuery }
79
+    q.page_size = 1000000
80
+    q.page = 1
81
+    const res = await list(q).catch(_ => false)
82
+    if (res) {
83
+      const csv = jsonToCsv(res.data.list)
84
+      downBlob(csv, 'connectLog.csv')
85
+    }
86
+  }
76
   return {
87
   return {
77
     listRes,
88
     listRes,
78
     listQuery,
89
     listQuery,
@@ -80,6 +91,7 @@ export function useRepositories () {
80
     handlerQuery,
91
     handlerQuery,
81
     del,
92
     del,
82
     batchdel,
93
     batchdel,
94
+    toExport,
83
   }
95
   }
84
 }
96
 }
85
 
97
 
@@ -151,6 +163,18 @@ export function useFileRepositories () {
151
       getList()
163
       getList()
152
     }
164
     }
153
   }
165
   }
166
+
167
+  const toExport = async () => {
168
+    const q = { ...listQuery }
169
+    q.page_size = 1000000
170
+    q.page = 1
171
+    const res = await fileList(q).catch(_ => false)
172
+    if (res) {
173
+      const csv = jsonToCsv(res.data.list)
174
+      downBlob(csv, 'fileTransformLog.csv')
175
+    }
176
+  }
177
+
154
   return {
178
   return {
155
     listRes,
179
     listRes,
156
     listQuery,
180
     listQuery,
@@ -158,5 +182,6 @@ export function useFileRepositories () {
158
     handlerQuery,
182
     handlerQuery,
159
     del,
183
     del,
160
     batchdel,
184
     batchdel,
185
+    toExport,
161
   }
186
   }
162
 }
187
 }

+ 19 - 3
src/views/login/log.js

@@ -2,10 +2,10 @@ import { reactive, ref } from 'vue'
2
 import { list as admin_fetchPeers } from '@/api/peer'
2
 import { list as admin_fetchPeers } from '@/api/peer'
3
 import { list as my_fetchPeers } from '@/api/my/peer'
3
 import { list as my_fetchPeers } from '@/api/my/peer'
4
 import { ElMessage, ElMessageBox } from 'element-plus'
4
 import { ElMessage, ElMessageBox } from 'element-plus'
5
-import { useRoute } from 'vue-router'
6
 import { T } from '@/utils/i18n'
5
 import { T } from '@/utils/i18n'
7
 import { batchDelete as admin_batchDelete, list as admin_list, remove as admin_remove } from '@/api/login_log'
6
 import { batchDelete as admin_batchDelete, list as admin_list, remove as admin_remove } from '@/api/login_log'
8
 import { batchDelete as my_batchDelete, list as my_list, remove as my_remove } from '@/api/my/login_log'
7
 import { batchDelete as my_batchDelete, list as my_list, remove as my_remove } from '@/api/my/login_log'
8
+import { downBlob, jsonToCsv } from '@/utils/file'
9
 
9
 
10
 const apis = {
10
 const apis = {
11
   admin: { batchDelete: admin_batchDelete, list: admin_list, remove: admin_remove, fetchPeers: admin_fetchPeers },
11
   admin: { batchDelete: admin_batchDelete, list: admin_list, remove: admin_remove, fetchPeers: admin_fetchPeers },
@@ -30,8 +30,8 @@ export function useRepositories (api_type = 'my') {
30
     listRes.loading = false
30
     listRes.loading = false
31
     if (res) {
31
     if (res) {
32
       //通过uuid补全peer信息
32
       //通过uuid补全peer信息
33
-      const uuids = res.data.list.filter(item => item.uuid&&item.client==='client'&&!item.device_id).map(item => item.uuid)
34
-      if(uuids.length > 0){
33
+      const uuids = res.data.list.filter(item => item.uuid && item.client === 'client' && !item.device_id).map(item => item.uuid)
34
+      if (uuids.length > 0) {
35
         //uuids去重
35
         //uuids去重
36
         const uniqueUuids = [...new Set(uuids)]
36
         const uniqueUuids = [...new Set(uuids)]
37
         const peers = await apis[api_type].fetchPeers({ uuids: uniqueUuids }).catch(_ => false)
37
         const peers = await apis[api_type].fetchPeers({ uuids: uniqueUuids }).catch(_ => false)
@@ -95,6 +95,21 @@ export function useRepositories (api_type = 'my') {
95
     }
95
     }
96
   }
96
   }
97
 
97
 
98
+  // only Admin
99
+  const toExport = async () => {
100
+    if (api_type !== 'admin') {
101
+      return false
102
+    }
103
+    const q = { ...listQuery }
104
+    q.page_size = 1000000
105
+    q.page = 1
106
+    const res = await admin_list(q).catch(_ => false)
107
+    if (res) {
108
+      const csv = jsonToCsv(res.data.list)
109
+      downBlob(csv, 'loginLog.csv')
110
+    }
111
+  }
112
+
98
   return {
113
   return {
99
     listRes,
114
     listRes,
100
     listQuery,
115
     listQuery,
@@ -102,5 +117,6 @@ export function useRepositories (api_type = 'my') {
102
     handlerQuery,
117
     handlerQuery,
103
     del,
118
     del,
104
     batchdel,
119
     batchdel,
120
+    toExport,
105
   }
121
   }
106
 }
122
 }

+ 5 - 0
src/views/login/log.vue

@@ -15,6 +15,7 @@
15
         <el-form-item>
15
         <el-form-item>
16
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
16
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
17
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
17
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
18
+          <el-button type="success" @click="toExport">{{ T('Export') }}</el-button>
18
         </el-form-item>
19
         </el-form-item>
19
       </el-form>
20
       </el-form>
20
     </el-card>
21
     </el-card>
@@ -62,6 +63,8 @@
62
   import { loadAllUsers } from '@/global'
63
   import { loadAllUsers } from '@/global'
63
   import { useRepositories } from '@/views/login/log.js'
64
   import { useRepositories } from '@/views/login/log.js'
64
   import { T } from '@/utils/i18n'
65
   import { T } from '@/utils/i18n'
66
+  import { list } from '@/api/peer'
67
+  import { downBlob, jsonToCsv } from '@/utils/file'
65
 
68
 
66
   const { allUsers, getAllUsers } = loadAllUsers()
69
   const { allUsers, getAllUsers } = loadAllUsers()
67
   getAllUsers()
70
   getAllUsers()
@@ -73,6 +76,7 @@
73
     handlerQuery,
76
     handlerQuery,
74
     del,
77
     del,
75
     batchdel,
78
     batchdel,
79
+    toExport,
76
   } = useRepositories('admin')
80
   } = useRepositories('admin')
77
 
81
 
78
   onMounted(getList)
82
   onMounted(getList)
@@ -91,6 +95,7 @@
91
     }
95
     }
92
     batchdel(multipleSelection.value)
96
     batchdel(multipleSelection.value)
93
   }
97
   }
98
+
94
 </script>
99
 </script>
95
 
100
 
96
 <style scoped lang="scss">
101
 <style scoped lang="scss">

+ 13 - 6
src/views/user/composables/index.js

@@ -1,9 +1,10 @@
1
-import { onMounted, reactive, watch } from 'vue'
1
+import { reactive } from 'vue'
2
 import { list, remove, changePwd } from '@/api/user'
2
 import { list, remove, changePwd } from '@/api/user'
3
 import { list as groups } from '@/api/group'
3
 import { list as groups } from '@/api/group'
4
 import { useRouter } from 'vue-router'
4
 import { useRouter } from 'vue-router'
5
 import { ElMessageBox, ElMessage } from 'element-plus'
5
 import { ElMessageBox, ElMessage } from 'element-plus'
6
 import { T } from '@/utils/i18n'
6
 import { T } from '@/utils/i18n'
7
+import { downBlob, jsonToCsv } from '@/utils/file'
7
 
8
 
8
 export function useRepositories () {
9
 export function useRepositories () {
9
 
10
 
@@ -42,18 +43,24 @@ export function useRepositories () {
42
       listRes.groups = res.data.list
43
       listRes.groups = res.data.list
43
     }
44
     }
44
   }
45
   }
45
-  onMounted(getGroups)
46
 
46
 
47
-  onMounted(getList)
48
-
49
-  watch(() => listQuery.page, getList)
50
-  watch(() => listQuery.page_size, handlerQuery)
47
+  const toExport = async () => {
48
+    const q = { ...listQuery }
49
+    q.page_size = 1000000
50
+    q.page = 1
51
+    const res = await list(q).catch(_ => false)
52
+    if (res) {
53
+      const csv = jsonToCsv(res.data.list)
54
+      downBlob(csv, 'users.csv')
55
+    }
56
+  }
51
   return {
57
   return {
52
     listRes,
58
     listRes,
53
     listQuery,
59
     listQuery,
54
     handlerQuery,
60
     handlerQuery,
55
     getList,
61
     getList,
56
     getGroups,
62
     getGroups,
63
+    toExport,
57
   }
64
   }
58
 }
65
 }
59
 
66
 

+ 11 - 0
src/views/user/index.vue

@@ -8,6 +8,7 @@
8
         <el-form-item>
8
         <el-form-item>
9
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
9
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
10
           <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
10
           <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
11
+          <el-button type="success" @click="toExport">{{ T('Export') }}</el-button>
11
         </el-form-item>
12
         </el-form-item>
12
       </el-form>
13
       </el-form>
13
     </el-card>
14
     </el-card>
@@ -63,14 +64,24 @@
63
   import { DISABLE_STATUS, ENABLE_STATUS } from '@/utils/common_options'
64
   import { DISABLE_STATUS, ENABLE_STATUS } from '@/utils/common_options'
64
   import { update } from '@/api/user'
65
   import { update } from '@/api/user'
65
   import { ElMessageBox, ElMessage } from 'element-plus'
66
   import { ElMessageBox, ElMessage } from 'element-plus'
67
+  import { onMounted, watch } from 'vue'
66
   //列表
68
   //列表
67
   const {
69
   const {
68
     listRes,
70
     listRes,
69
     listQuery,
71
     listQuery,
70
     handlerQuery,
72
     handlerQuery,
71
     getList,
73
     getList,
74
+    getGroups,
75
+    toExport,
72
   } = useRepositories()
76
   } = useRepositories()
73
 
77
 
78
+  onMounted(getGroups)
79
+
80
+  onMounted(getList)
81
+
82
+  watch(() => listQuery.page, getList)
83
+  watch(() => listQuery.page_size, handlerQuery)
84
+
74
   const { toEdit, toAdd, toAddressBook, toTag } = useToEditOrAdd()
85
   const { toEdit, toAdd, toAddressBook, toTag } = useToEditOrAdd()
75
 
86
 
76
   const { changePass } = useChangePwd()
87
   const { changePass } = useChangePwd()