Browse Source

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

lejianwen 7 months ago
parent
commit
fc7e0595a1

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

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

+ 0 - 1
src/layout/index.vue

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

+ 1 - 1
src/utils/file.js

@@ -38,7 +38,7 @@ export function jsonToCsv (data) {
38 38
   let keys = Object.keys(data[0])
39 39
   csv += keys.join(',') + '\n'
40 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 43
   return new Blob([csv], { type: 'text/csv' })
44 44
 }

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

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

File diff suppressed because it is too large
+ 0 - 4272
src/utils/pca.json


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

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

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

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

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

@@ -1,9 +1,9 @@
1 1
 import { reactive } from 'vue'
2 2
 import { list, remove, fileList, fileRemove, batchDelete, fileBatchDelete } from '@/api/audit'
3 3
 import { ElMessage, ElMessageBox } from 'element-plus'
4
-import { useRoute } from 'vue-router'
5 4
 import { formatTime } from '@/utils/time'
6 5
 import { T } from '@/utils/i18n'
6
+import { downBlob, jsonToCsv } from '@/utils/file'
7 7
 
8 8
 export function useRepositories () {
9 9
   const listRes = reactive({
@@ -73,6 +73,17 @@ export function useRepositories () {
73 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 87
   return {
77 88
     listRes,
78 89
     listQuery,
@@ -80,6 +91,7 @@ export function useRepositories () {
80 91
     handlerQuery,
81 92
     del,
82 93
     batchdel,
94
+    toExport,
83 95
   }
84 96
 }
85 97
 
@@ -151,6 +163,18 @@ export function useFileRepositories () {
151 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 178
   return {
155 179
     listRes,
156 180
     listQuery,
@@ -158,5 +182,6 @@ export function useFileRepositories () {
158 182
     handlerQuery,
159 183
     del,
160 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 2
 import { list as admin_fetchPeers } from '@/api/peer'
3 3
 import { list as my_fetchPeers } from '@/api/my/peer'
4 4
 import { ElMessage, ElMessageBox } from 'element-plus'
5
-import { useRoute } from 'vue-router'
6 5
 import { T } from '@/utils/i18n'
7 6
 import { batchDelete as admin_batchDelete, list as admin_list, remove as admin_remove } from '@/api/login_log'
8 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 10
 const apis = {
11 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 30
     listRes.loading = false
31 31
     if (res) {
32 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 35
         //uuids去重
36 36
         const uniqueUuids = [...new Set(uuids)]
37 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 113
   return {
99 114
     listRes,
100 115
     listQuery,
@@ -102,5 +117,6 @@ export function useRepositories (api_type = 'my') {
102 117
     handlerQuery,
103 118
     del,
104 119
     batchdel,
120
+    toExport,
105 121
   }
106 122
 }

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

@@ -15,6 +15,7 @@
15 15
         <el-form-item>
16 16
           <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
17 17
           <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
18
+          <el-button type="success" @click="toExport">{{ T('Export') }}</el-button>
18 19
         </el-form-item>
19 20
       </el-form>
20 21
     </el-card>
@@ -62,6 +63,8 @@
62 63
   import { loadAllUsers } from '@/global'
63 64
   import { useRepositories } from '@/views/login/log.js'
64 65
   import { T } from '@/utils/i18n'
66
+  import { list } from '@/api/peer'
67
+  import { downBlob, jsonToCsv } from '@/utils/file'
65 68
 
66 69
   const { allUsers, getAllUsers } = loadAllUsers()
67 70
   getAllUsers()
@@ -73,6 +76,7 @@
73 76
     handlerQuery,
74 77
     del,
75 78
     batchdel,
79
+    toExport,
76 80
   } = useRepositories('admin')
77 81
 
78 82
   onMounted(getList)
@@ -91,6 +95,7 @@
91 95
     }
92 96
     batchdel(multipleSelection.value)
93 97
   }
98
+
94 99
 </script>
95 100
 
96 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 2
 import { list, remove, changePwd } from '@/api/user'
3 3
 import { list as groups } from '@/api/group'
4 4
 import { useRouter } from 'vue-router'
5 5
 import { ElMessageBox, ElMessage } from 'element-plus'
6 6
 import { T } from '@/utils/i18n'
7
+import { downBlob, jsonToCsv } from '@/utils/file'
7 8
 
8 9
 export function useRepositories () {
9 10
 
@@ -42,18 +43,24 @@ export function useRepositories () {
42 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 57
   return {
52 58
     listRes,
53 59
     listQuery,
54 60
     handlerQuery,
55 61
     getList,
56 62
     getGroups,
63
+    toExport,
57 64
   }
58 65
 }
59 66
 

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

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