Commit f09a1a4b8eeb1fd1a5266311b2ae0dabf58d4223

Authored by xingyu4j
1 parent 4a692ed2

refactor: operatelog

yudao-ui-admin-vue3/src/api/system/operatelog/index.ts
1 1 import request from '@/config/axios'
2 2  
  3 +export type OperateLogVO = {
  4 + id: number
  5 + userNickname: string
  6 + traceId: string
  7 + userId: number
  8 + module: string
  9 + name: string
  10 + type: number
  11 + content: string
  12 + exts: object
  13 + requestMethod: string
  14 + requestUrl: string
  15 + userIp: string
  16 + userAgent: string
  17 + javaMethod: string
  18 + javaMethodArgs: string
  19 + startTime: string
  20 + duration: number
  21 + resultCode: number
  22 + resultMsg: string
  23 + resultData: string
  24 +}
  25 +export interface OperateLogPageReqVO extends BasePage {
  26 + module?: string
  27 + userNickname?: string
  28 + type?: number
  29 + success?: boolean
  30 + startTime?: string[]
  31 +}
  32 +
3 33 // 查询操作日志列表
4   -export const getOperateLogPageApi = (params) => {
  34 +export const getOperateLogPageApi = (params: OperateLogPageReqVO) => {
5 35 return request.get({ url: '/system/operate-log/page', params })
6 36 }
7 37 // 导出操作日志
8   -export const exportOperateLogApi = (params) => {
  38 +export const exportOperateLogApi = (params: OperateLogPageReqVO) => {
9 39 return request.download({ url: '/system/operate-log/export', params })
10 40 }
... ...
yudao-ui-admin-vue3/src/api/system/operatelog/types.ts deleted
1   -export type OperateLogVO = {
2   - id: number
3   - userNickname: string
4   - traceId: string
5   - userId: number
6   - module: string
7   - name: string
8   - type: number
9   - content: string
10   - exts: object
11   - requestMethod: string
12   - requestUrl: string
13   - userIp: string
14   - userAgent: string
15   - javaMethod: string
16   - javaMethodArgs: string
17   - startTime: string
18   - duration: number
19   - resultCode: number
20   - resultMsg: string
21   - resultData: string
22   -}
yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts
... ... @@ -20,6 +20,7 @@ export type VxeCrudSchema = {
20 20 primaryType?: VxeColumnPropTypes.Type
21 21 // 是否开启操作栏插槽
22 22 action?: boolean
  23 + actionWidth?: string
23 24 columns: VxeCrudColumns[]
24 25 }
25 26 type VxeCrudColumns = Omit<VxeTableColumn, 'children'> & {
... ... @@ -204,7 +205,7 @@ const filterTableSchema = (crudSchema: VxeCrudSchema): VxeGridPropTypes.Columns
204 205 const tableSchemaItem = {
205 206 title: t('table.action'),
206 207 field: 'actionbtns',
207   - width: '240px',
  208 + width: crudSchema.actionWidth ? crudSchema.actionWidth : '240px',
208 209 slots: {
209 210 default: 'actionbtns_default'
210 211 }
... ...
yudao-ui-admin-vue3/src/views/system/dept/index.vue
... ... @@ -10,11 +10,6 @@ import { DeptVO } from &#39;@/api/system/dept/types&#39;
10 10 import { useMessage } from '@/hooks/web/useMessage'
11 11 import { getListSimpleUsersApi } from '@/api/system/user'
12 12 const message = useMessage()
13   -interface Tree {
14   - id: number
15   - name: string
16   - children?: Tree[]
17   -}
18 13  
19 14 const defaultProps = {
20 15 children: 'children',
... ...
yudao-ui-admin-vue3/src/views/system/loginlog/loginLog.data.ts
... ... @@ -9,6 +9,7 @@ const crudSchemas = reactive&lt;VxeCrudSchema&gt;({
9 9 primaryKey: 'id',
10 10 primaryType: 'seq',
11 11 action: true,
  12 + actionWidth: '80px',
12 13 columns: [
13 14 {
14 15 title: '日志类型',
... ...
yudao-ui-admin-vue3/src/views/system/operatelog/index.vue
1   -<script setup lang="ts">
2   -import dayjs from 'dayjs'
3   -import { useTable } from '@/hooks/web/useTable'
4   -import { allSchemas } from './operatelog.data'
5   -import { DICT_TYPE } from '@/utils/dict'
6   -import { useI18n } from '@/hooks/web/useI18n'
7   -import type { OperateLogVO } from '@/api/system/operatelog/types'
8   -import * as OperateLogApi from '@/api/system/operatelog'
9   -import { ref } from 'vue'
10   -const { t } = useI18n() // 国际化
11   -// ========== 列表相关 ==========
12   -const { register, tableObject, methods } = useTable<OperateLogVO>({
13   - getListApi: OperateLogApi.getOperateLogPageApi,
14   - exportListApi: OperateLogApi.exportOperateLogApi
15   -})
16   -// ========== 详情相关 ==========
17   -const detailRef = ref() // 详情 Ref
18   -const dialogVisible = ref(false) // 是否显示弹出层
19   -const dialogTitle = ref(t('action.detail')) // 弹出层标题
20   -const { getList, setSearchParams, exportList } = methods
21   -// 详情
22   -const handleDetail = (row: OperateLogVO) => {
23   - // 设置数据
24   - detailRef.value = row
25   - dialogVisible.value = true
26   -}
27   -getList()
28   -</script>
29 1 <template>
30 2 <ContentWrap>
31   - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
32   - </ContentWrap>
33   - <ContentWrap>
34   - <!-- 操作工具栏 -->
35   - <div class="mb-10px">
36   - <el-button
37   - type="warning"
38   - v-hasPermi="['system:operate-log:export']"
39   - :loading="tableObject.exportLoading"
40   - @click="exportList('操作日志.xls')"
41   - >
42   - <Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }}
43   - </el-button>
44   - </div>
45   - <Table
46   - :columns="allSchemas.tableColumns"
47   - :selection="false"
48   - :data="tableObject.tableList"
49   - :loading="tableObject.loading"
50   - :pagination="{
51   - total: tableObject.total
52   - }"
53   - v-model:pageSize="tableObject.pageSize"
54   - v-model:currentPage="tableObject.currentPage"
55   - @register="register"
56   - >
57   - <template #type="{ row }">
58   - <DictTag :type="DICT_TYPE.SYSTEM_OPERATE_TYPE" :value="row.type" />
  3 + <!-- 列表 -->
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <!-- 操作:新增 -->
  6 + <template #toolbar_buttons>
  7 + <XButton
  8 + type="warning"
  9 + preIcon="ep:download"
  10 + :title="t('action.export')"
  11 + v-hasPermi="['system:operate-log:export']"
  12 + @click="handleExport()"
  13 + />
59 14 </template>
60 15 <template #duration="{ row }">
61 16 <span>{{ row.duration + 'ms' }}</span>
... ... @@ -63,35 +18,68 @@ getList()
63 18 <template #resultCode="{ row }">
64 19 <span>{{ row.resultCode === 0 ? '成功' : '失败' }}</span>
65 20 </template>
66   - <template #startTime="{ row }">
67   - <span>{{ dayjs(row.startTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
  21 + <template #actionbtns_default="{ row }">
  22 + <!-- 操作:详情 -->
  23 + <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
68 24 </template>
69   - <template #action="{ row }">
70   - <el-button link type="primary" @click="handleDetail(row)">
71   - <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
72   - </el-button>
73   - </template>
74   - </Table>
  25 + </vxe-grid>
75 26 </ContentWrap>
76   - <Dialog v-model="dialogVisible" :title="dialogTitle">
77   - <!-- 对话框(详情) -->
78   - <Descriptions :schema="allSchemas.detailSchema" :data="detailRef">
79   - <template #resultCode="{ row }">
80   - <span>{{ row.resultCode === 0 ? '成功' : '失败' }}</span>
81   - </template>
82   - <template #type="{ row }">
83   - <DictTag :type="DICT_TYPE.SYSTEM_OPERATE_TYPE" :value="row.type" />
84   - </template>
85   - <template #duration="{ row }">
86   - <span>{{ row.duration + 'ms' }}</span>
87   - </template>
88   - <template #startTime="{ row }">
89   - <span>{{ dayjs(row.startTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
90   - </template>
91   - </Descriptions>
92   - <!-- 操作按钮 -->
  27 + <!-- 弹窗 -->
  28 + <XModal id="postModel" v-model="dialogVisible" :title="dialogTitle">
  29 + <template #default>
  30 + <!-- 对话框(详情) -->
  31 + <Descriptions :schema="allSchemas.detailSchema" :data="detailRef">
  32 + <template #resultCode="{ row }">
  33 + <span>{{ row.resultCode === 0 ? '成功' : '失败' }}</span>
  34 + </template>
  35 + <template #duration="{ row }">
  36 + <span>{{ row.duration + 'ms' }}</span>
  37 + </template>
  38 + </Descriptions>
  39 + </template>
93 40 <template #footer>
94   - <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
  41 + <!-- 按钮:关闭 -->
  42 + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
95 43 </template>
96   - </Dialog>
  44 + </XModal>
97 45 </template>
  46 +<script setup lang="ts">
  47 +// 全局相关的 import
  48 +import { ref } from 'vue'
  49 +import { useI18n } from '@/hooks/web/useI18n'
  50 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  51 +import { VxeGridInstance } from 'vxe-table'
  52 +// 业务相关的 import
  53 +import * as OperateLogApi from '@/api/system/operatelog'
  54 +import { allSchemas } from './operatelog.data'
  55 +import download from '@/utils/download'
  56 +
  57 +const { t } = useI18n() // 国际化
  58 +// 列表相关的变量
  59 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  60 +const { gridOptions } = useVxeGrid<OperateLogApi.OperateLogVO>({
  61 + allSchemas: allSchemas,
  62 + getListApi: OperateLogApi.getOperateLogPageApi
  63 +})
  64 +// 弹窗相关的变量
  65 +const dialogVisible = ref(false) // 是否显示弹出层
  66 +const dialogTitle = ref('edit') // 弹出层标题
  67 +const actionLoading = ref(false) // 按钮 Loading
  68 +const detailRef = ref() // 详情 Ref
  69 +// 详情
  70 +const handleDetail = (row: OperateLogApi.OperateLogVO) => {
  71 + // 设置数据
  72 + detailRef.value = row
  73 + dialogVisible.value = true
  74 +}
  75 +
  76 +// 导出操作
  77 +const handleExport = async () => {
  78 + const queryParams = Object.assign(
  79 + {},
  80 + JSON.parse(JSON.stringify(xGrid.value?.getRefMaps().refForm.value.data))
  81 + )
  82 + const res = await OperateLogApi.exportOperateLogApi(queryParams)
  83 + download.excel(res, '岗位列表.xls')
  84 +}
  85 +</script>
... ...
yudao-ui-admin-vue3/src/views/system/operatelog/operatelog.data.ts
1 1 import { reactive } from 'vue'
2 2 import { DICT_TYPE } from '@/utils/dict'
3   -import { useI18n } from '@/hooks/web/useI18n'
4   -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
5   -const { t } = useI18n() // 国际化
6   -const crudSchemas = reactive<CrudSchema[]>([
7   - {
8   - label: t('common.index'),
9   - field: 'id',
10   - type: 'index',
11   - form: {
12   - show: false
13   - }
14   - },
15   - {
16   - label: '操作模块',
17   - field: 'module',
18   - search: {
19   - show: true
20   - }
21   - },
22   - {
23   - label: '操作名',
24   - field: 'name'
25   - },
26   - {
27   - label: '操作类型',
28   - field: 'type',
29   - dictType: DICT_TYPE.SYSTEM_OPERATE_TYPE,
30   - search: {
31   - show: true
32   - }
33   - },
34   - {
35   - label: '请求方法名',
36   - field: 'requestMethod'
37   - },
38   - {
39   - label: '请求地址',
40   - field: 'requestUrl'
41   - },
42   - {
43   - label: '操作人员',
44   - field: 'userNickname',
45   - search: {
46   - show: true
47   - }
48   - },
49   - {
50   - label: '操作明细',
51   - field: 'content',
52   - table: {
53   - show: false
54   - }
55   - },
56   - {
57   - label: '用户 IP',
58   - field: 'userIp',
59   - table: {
60   - show: false
61   - }
62   - },
63   - {
64   - label: 'userAgent',
65   - field: 'userAgent'
66   - },
67   - {
68   - label: '操作结果',
69   - field: 'resultCode',
70   - search: {
71   - show: true,
72   - component: 'Select',
73   - componentProps: {
74   - options: [
75   - { label: '成功', value: true },
76   - { label: '失败', value: false }
77   - ]
  3 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
  4 +
  5 +const crudSchemas = reactive<VxeCrudSchema>({
  6 + primaryKey: 'id',
  7 + primaryType: 'seq',
  8 + action: true,
  9 + actionWidth: '80px',
  10 + columns: [
  11 + {
  12 + title: '操作模块',
  13 + field: 'module',
  14 + isSearch: true
  15 + },
  16 + {
  17 + title: '操作名',
  18 + field: 'name'
  19 + },
  20 + {
  21 + title: '操作类型',
  22 + field: 'type',
  23 + dictType: DICT_TYPE.SYSTEM_OPERATE_TYPE,
  24 + isSearch: true
  25 + },
  26 + {
  27 + title: '请求方法名',
  28 + field: 'requestMethod'
  29 + },
  30 + {
  31 + title: '请求地址',
  32 + field: 'requestUrl'
  33 + },
  34 + {
  35 + title: '操作人员',
  36 + field: 'userNickname',
  37 + isSearch: true
  38 + },
  39 + {
  40 + title: '操作明细',
  41 + field: 'content',
  42 + isTable: false
  43 + },
  44 + {
  45 + title: '用户 IP',
  46 + field: 'userIp',
  47 + isTable: false
  48 + },
  49 + {
  50 + title: 'userAgent',
  51 + field: 'userAgent'
  52 + },
  53 + {
  54 + title: '操作结果',
  55 + field: 'resultCode',
  56 + table: {
  57 + slots: {
  58 + default: 'resultCode'
  59 + }
78 60 }
79   - }
80   - },
81   - {
82   - label: '操作日期',
83   - field: 'startTime',
84   - form: {
85   - show: false
86 61 },
87   - search: {
88   - show: true,
89   - component: 'DatePicker',
90   - componentProps: {
91   - type: 'daterange',
92   - valueFormat: 'YYYY-MM-DD HH:mm:ss',
93   - defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]
  62 + {
  63 + title: '操作日期',
  64 + field: 'startTime',
  65 + formatter: 'formatDate',
  66 + isForm: false,
  67 + search: {
  68 + itemRender: {
  69 + name: 'XDataTimePicker'
  70 + }
94 71 }
95   - }
96   - },
97   - {
98   - label: '执行时长',
99   - field: 'duration'
100   - },
101   - {
102   - label: t('table.action'),
103   - field: 'action',
104   - width: '120px',
105   - form: {
106   - show: false
107 72 },
108   - detail: {
109   - show: false
  73 + {
  74 + title: '执行时长',
  75 + field: 'duration',
  76 + table: {
  77 + slots: {
  78 + default: 'duration'
  79 + }
  80 + }
110 81 }
111   - }
112   -])
113   -export const { allSchemas } = useCrudSchemas(crudSchemas)
  82 + ]
  83 +})
  84 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
... ...
yudao-ui-admin-vue3/src/views/system/user/index.vue
... ... @@ -39,11 +39,6 @@ import { getAccessToken, getTenantId } from &#39;@/utils/auth&#39;
39 39 import { useMessage } from '@/hooks/web/useMessage'
40 40  
41 41 const message = useMessage()
42   -interface Tree {
43   - id: number
44   - name: string
45   - children?: Tree[]
46   -}
47 42  
48 43 const defaultProps = {
49 44 children: 'children',
... ...