lejianwen 1 год назад
Родитель
Сommit
502bea8dc3

+ 24 - 0
src/api/my.js

@@ -0,0 +1,24 @@
1
+import request from '@/utils/request'
2
+
3
+export function share_record_list (params) {
4
+  return request({
5
+    url: '/my/share_record/list',
6
+    params,
7
+  })
8
+}
9
+
10
+export function share_record_remove (data) {
11
+  return request({
12
+    url: '/my/share_record/delete',
13
+    method: 'post',
14
+    data,
15
+  })
16
+}
17
+
18
+export function share_record_batchDelete (data) {
19
+  return request({
20
+    url: '/my/share_record/batchDelete',
21
+    method: 'post',
22
+    data,
23
+  })
24
+}

+ 24 - 0
src/api/share_record.js

@@ -0,0 +1,24 @@
1
+import request from '@/utils/request'
2
+
3
+export function list (params) {
4
+  return request({
5
+    url: '/share_record/list',
6
+    params,
7
+  })
8
+}
9
+
10
+export function remove (data) {
11
+  return request({
12
+    url: '/share_record/delete',
13
+    method: 'post',
14
+    data,
15
+  })
16
+}
17
+
18
+export function batchDelete (data) {
19
+  return request({
20
+    url: '/share_record/batchDelete',
21
+    method: 'post',
22
+    data,
23
+  })
24
+}

+ 12 - 0
src/router/index.js

@@ -85,6 +85,12 @@ export const asyncRoutes = [
85 85
         meta: { title: 'Tags', icon: 'CollectionTag' /*keepAlive: true*/ },
86 86
         component: () => import('@/views/my/tag/index.vue'),
87 87
       },
88
+      {
89
+        path: 'shareRecord',
90
+        name: 'MyShareRecordList',
91
+        meta: { title: 'ShareRecord', icon: 'Share' /*keepAlive: true*/ },
92
+        component: () => import('@/views/my/share_record/index.vue'),
93
+      },
88 94
     ],
89 95
   },
90 96
   {
@@ -172,6 +178,12 @@ export const asyncRoutes = [
172 178
         meta: { title: 'AuditFileLog', icon: 'Files' /*keepAlive: true*/ },
173 179
         component: () => import('@/views/audit/fileList.vue'),
174 180
       },
181
+      {
182
+        path: '/shareRecord',
183
+        name: 'ShareRecord',
184
+        meta: { title: 'ShareRecord', icon: 'Share' /*keepAlive: true*/ },
185
+        component: () => import('@/views/share_record/index.vue'),
186
+      },
175 187
     ],
176 188
   },
177 189
 ]

+ 9 - 0
src/utils/i18n/en.json

@@ -456,5 +456,14 @@
456 456
   },
457 457
   "BatchEditTags": {
458 458
     "One": "Batch Edit Tags"
459
+  },
460
+  "User": {
461
+    "One": "User"
462
+  },
463
+  "ShareRecord": {
464
+    "One": "Share Record"
465
+  },
466
+  "Second": {
467
+    "One": "Second"
459 468
   }
460 469
 }

+ 9 - 0
src/utils/i18n/es.json

@@ -459,5 +459,14 @@
459 459
   },
460 460
   "BatchEditTags": {
461 461
     "One": "Editar etiquetas en bloque"
462
+  },
463
+  "User": {
464
+    "One": "Usuario"
465
+  },
466
+  "ShareRecord": {
467
+    "One": "Registro de compartición"
468
+  },
469
+  "Second": {
470
+    "One": "Segundo"
462 471
   }
463 472
 }

+ 9 - 0
src/utils/i18n/ko.json

@@ -445,5 +445,14 @@
445 445
   },
446 446
   "BatchEditTags": {
447 447
     "One": "태그 일괄 편집"
448
+  },
449
+  "User": {
450
+    "One": "사용자"
451
+  },
452
+  "ShareRecord": {
453
+    "One": "공유 기록"
454
+  },
455
+  "Second": {
456
+    "One": "초"
448 457
   }
449 458
 }

+ 9 - 0
src/utils/i18n/ru.json

@@ -459,6 +459,15 @@
459 459
   },
460 460
   "BatchEditTags": {
461 461
     "One": "Пакетное редактирование тегов"
462
+  },
463
+  "User": {
464
+    "One": "Пользователь"
465
+  },
466
+  "ShareRecord": {
467
+    "One": "Запись обмена"
468
+  },
469
+  "Second": {
470
+    "One": "Секунда"
462 471
   }
463 472
 }
464 473
 

+ 9 - 0
src/utils/i18n/zh_CN.json

@@ -475,5 +475,14 @@
475 475
   },
476 476
   "BatchEditTags": {
477 477
     "One": "批量编辑标签"
478
+  },
479
+  "User": {
480
+    "One": "用户"
481
+  },
482
+  "ShareRecord": {
483
+    "One": "分享记录"
484
+  },
485
+  "Second": {
486
+    "One": "秒"
478 487
   }
479 488
 }

+ 131 - 0
src/views/my/share_record/index.vue

@@ -0,0 +1,131 @@
1
+<template>
2
+  <div>
3
+    <el-card class="list-query" shadow="hover">
4
+      <el-form inline label-width="80px">
5
+        <el-form-item>
6
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
7
+          <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
8
+        </el-form-item>
9
+      </el-form>
10
+    </el-card>
11
+    <el-card class="list-body" shadow="hover">
12
+      <el-table :data="listRes.list" v-loading="listRes.loading" border @selection-change="handleSelectionChange">
13
+        <el-table-column type="selection" align="center" width="50"/>
14
+        <el-table-column prop="id" label="ID" align="center" width="100"/>
15
+        <el-table-column prop="peer_id" :label="T('Peer')" align="center"/>
16
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
17
+        <el-table-column :label="`${T('ExpireTime')}(${T('Second')})`" prop="expire" align="center">
18
+        </el-table-column>
19
+        <el-table-column :label="T('Actions')" align="center" width="400">
20
+          <template #default="{row}">
21
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
22
+          </template>
23
+        </el-table-column>
24
+      </el-table>
25
+    </el-card>
26
+    <el-card class="list-page" shadow="hover">
27
+      <el-pagination background
28
+                     layout="prev, pager, next, sizes, jumper"
29
+                     :page-sizes="[10,20,50,100]"
30
+                     v-model:page-size="listQuery.page_size"
31
+                     v-model:current-page="listQuery.page"
32
+                     :total="listRes.total">
33
+      </el-pagination>
34
+    </el-card>
35
+  </div>
36
+</template>
37
+
38
+<script setup>
39
+  import { onActivated, onMounted, ref, watch, reactive } from 'vue'
40
+  import { T } from '@/utils/i18n'
41
+  import { share_record_remove as remove, share_record_list as list, share_record_batchDelete as batchDelete } from '@/api/my'
42
+  import { ElMessage, ElMessageBox } from 'element-plus'
43
+
44
+  const listRes = reactive({
45
+    list: [], total: 0, loading: false,
46
+  })
47
+  const listQuery = reactive({
48
+    page: 1,
49
+    page_size: 10,
50
+  })
51
+
52
+  const getList = async () => {
53
+    listRes.loading = true
54
+    const res = await list(listQuery).catch(_ => false)
55
+    listRes.loading = false
56
+    if (res) {
57
+      listRes.list = res.data.list
58
+      listRes.total = res.data.total
59
+    }
60
+  }
61
+  const handlerQuery = () => {
62
+    if (listQuery.page === 1) {
63
+      getList()
64
+    } else {
65
+      listQuery.page = 1
66
+    }
67
+  }
68
+
69
+  const del = async (row) => {
70
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
71
+      confirmButtonText: T('Confirm'),
72
+      cancelButtonText: T('Cancel'),
73
+      type: 'warning',
74
+    }).catch(_ => false)
75
+    if (!cf) {
76
+      return false
77
+    }
78
+    const res = await remove({ id: row.id }).catch(_ => false)
79
+    if (res) {
80
+      ElMessage.success(T('OperationSuccess'))
81
+      getList()
82
+    }
83
+  }
84
+  onMounted(getList)
85
+  onActivated(getList)
86
+
87
+  watch(() => listQuery.page, getList)
88
+
89
+  watch(() => listQuery.page_size, handlerQuery)
90
+  const multipleSelection = ref([])
91
+  const handleSelectionChange = (val) => {
92
+    multipleSelection.value = val
93
+  }
94
+  const toBatchDelete = () => {
95
+    if (multipleSelection.value.length === 0) {
96
+      return
97
+    }
98
+    batchdel(multipleSelection.value)
99
+  }
100
+
101
+  const batchdel = async (rows) => {
102
+    const ids = rows.map(r => r.id)
103
+    if (!ids.length) {
104
+      ElMessage.warning(T('PleaseSelectData'))
105
+      return false
106
+    }
107
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('BatchDelete') }), {
108
+      confirmButtonText: T('Confirm'),
109
+      cancelButtonText: T('Cancel'),
110
+      type: 'warning',
111
+    }).catch(_ => false)
112
+    if (!cf) {
113
+      return false
114
+    }
115
+
116
+    const res = await batchDelete({ ids }).catch(_ => false)
117
+    if (res) {
118
+      ElMessage.success(T('OperationSuccess'))
119
+      getList()
120
+    }
121
+  }
122
+
123
+</script>
124
+
125
+<style scoped lang="scss">
126
+.list-query .el-select {
127
+  --el-select-width: 160px;
128
+}
129
+
130
+
131
+</style>

+ 156 - 0
src/views/share_record/index.vue

@@ -0,0 +1,156 @@
1
+<template>
2
+  <div>
3
+    <el-card class="list-query" shadow="hover">
4
+      <el-form inline label-width="80px">
5
+        <el-form-item :label="T('User')">
6
+          <el-select v-model="listQuery.user_id" clearable>
7
+            <el-option
8
+                v-for="item in allUsers"
9
+                :key="item.id"
10
+                :label="item.username"
11
+                :value="item.id"
12
+            ></el-option>
13
+          </el-select>
14
+        </el-form-item>
15
+        <el-form-item>
16
+          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
17
+          <el-button type="danger" @click="toBatchDelete">{{ T('BatchDelete') }}</el-button>
18
+        </el-form-item>
19
+      </el-form>
20
+    </el-card>
21
+    <el-card class="list-body" shadow="hover">
22
+      <el-table :data="listRes.list" v-loading="listRes.loading" border @selection-change="handleSelectionChange">
23
+        <el-table-column type="selection" align="center" width="50"/>
24
+        <el-table-column prop="id" label="ID" align="center" width="100"/>
25
+        <el-table-column :label="T('User')" align="center" width="120">
26
+          <template #default="{row}">
27
+            <span v-if="row.user_id"> <el-tag>{{ allUsers?.find(u => u.id === row.user_id)?.username }}</el-tag> </span>
28
+          </template>
29
+        </el-table-column>
30
+        <el-table-column prop="peer_id" :label="T('Peer')" align="center"/>
31
+        <el-table-column prop="created_at" :label="T('CreatedAt')" align="center"/>
32
+        <el-table-column :label="`${T('ExpireTime')}(${T('Second')})`" prop="expire" align="center">
33
+        </el-table-column>
34
+        <el-table-column :label="T('Actions')" align="center" width="400">
35
+          <template #default="{row}">
36
+            <el-button type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
37
+          </template>
38
+        </el-table-column>
39
+      </el-table>
40
+    </el-card>
41
+    <el-card class="list-page" shadow="hover">
42
+      <el-pagination background
43
+                     layout="prev, pager, next, sizes, jumper"
44
+                     :page-sizes="[10,20,50,100]"
45
+                     v-model:page-size="listQuery.page_size"
46
+                     v-model:current-page="listQuery.page"
47
+                     :total="listRes.total">
48
+      </el-pagination>
49
+    </el-card>
50
+  </div>
51
+</template>
52
+
53
+<script setup>
54
+  import { onActivated, onMounted, ref, watch, reactive } from 'vue'
55
+  import { loadAllUsers } from '@/global'
56
+  import { T } from '@/utils/i18n'
57
+  import { remove, list, batchDelete } from '@/api/share_record'
58
+  import { ElMessage, ElMessageBox } from 'element-plus'
59
+
60
+  const { allUsers, getAllUsers } = loadAllUsers()
61
+  getAllUsers()
62
+
63
+  const listRes = reactive({
64
+    list: [], total: 0, loading: false,
65
+  })
66
+  const listQuery = reactive({
67
+    page: 1,
68
+    page_size: 10,
69
+    is_my: 0,
70
+    user_id: null,
71
+  })
72
+
73
+  const getList = async () => {
74
+    listRes.loading = true
75
+    const res = await list(listQuery).catch(_ => false)
76
+    listRes.loading = false
77
+    if (res) {
78
+      listRes.list = res.data.list
79
+      listRes.total = res.data.total
80
+    }
81
+  }
82
+  const handlerQuery = () => {
83
+    if (listQuery.page === 1) {
84
+      getList()
85
+    } else {
86
+      listQuery.page = 1
87
+    }
88
+  }
89
+  const expired = (row) => {
90
+    const now = new Date().getTime()
91
+    return row.expire * 1000 < now
92
+  }
93
+
94
+  const del = async (row) => {
95
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('Delete') }), {
96
+      confirmButtonText: T('Confirm'),
97
+      cancelButtonText: T('Cancel'),
98
+      type: 'warning',
99
+    }).catch(_ => false)
100
+    if (!cf) {
101
+      return false
102
+    }
103
+    const res = await remove({ id: row.id }).catch(_ => false)
104
+    if (res) {
105
+      ElMessage.success(T('OperationSuccess'))
106
+      getList()
107
+    }
108
+  }
109
+  onMounted(getList)
110
+  onActivated(getList)
111
+
112
+  watch(() => listQuery.page, getList)
113
+
114
+  watch(() => listQuery.page_size, handlerQuery)
115
+  const multipleSelection = ref([])
116
+  const handleSelectionChange = (val) => {
117
+    multipleSelection.value = val
118
+  }
119
+  const toBatchDelete = () => {
120
+    if (multipleSelection.value.length === 0) {
121
+      return
122
+    }
123
+    batchdel(multipleSelection.value)
124
+  }
125
+
126
+  const batchdel = async (rows) => {
127
+    const ids = rows.map(r => r.id)
128
+    if (!ids.length) {
129
+      ElMessage.warning(T('PleaseSelectData'))
130
+      return false
131
+    }
132
+    const cf = await ElMessageBox.confirm(T('Confirm?', { param: T('BatchDelete') }), {
133
+      confirmButtonText: T('Confirm'),
134
+      cancelButtonText: T('Cancel'),
135
+      type: 'warning',
136
+    }).catch(_ => false)
137
+    if (!cf) {
138
+      return false
139
+    }
140
+
141
+    const res = await batchDelete({ ids }).catch(_ => false)
142
+    if (res) {
143
+      ElMessage.success(T('OperationSuccess'))
144
+      getList()
145
+    }
146
+  }
147
+
148
+</script>
149
+
150
+<style scoped lang="scss">
151
+.list-query .el-select {
152
+  --el-select-width: 160px;
153
+}
154
+
155
+
156
+</style>