Commit 562282b2ad6c608abf257bd7d3ada3e22dc1abed

Authored by xingyu4j
1 parent e6acf9e8

refactor: file vxe

yudao-ui-admin-vue3/src/api/infra/fileConfig/types.ts
@@ -15,7 +15,7 @@ export type FileConfigVO = { @@ -15,7 +15,7 @@ export type FileConfigVO = {
15 id: number 15 id: number
16 name: string 16 name: string
17 storage: string 17 storage: string
18 - primary: number 18 + master: boolean
19 visible: boolean 19 visible: boolean
20 config: ConfigType 20 config: ConfigType
21 remark: string 21 remark: string
yudao-ui-admin-vue3/src/api/infra/fileList/index.ts
1 import request from '@/config/axios' 1 import request from '@/config/axios'
2 2
  3 +export type FileVO = {
  4 + id: number
  5 + path: string
  6 + url: string
  7 + size: string
  8 + type: string
  9 + createTime: string
  10 +}
  11 +
  12 +export interface FilePageReqVO extends PageParam {
  13 + name?: string
  14 + createTime?: string[]
  15 +}
  16 +
3 // 查询文件列表 17 // 查询文件列表
4 -export const getFilePageApi = (params) => { 18 +export const getFilePageApi = (params: FilePageReqVO) => {
5 return request.get({ url: '/infra/file/page', params }) 19 return request.get({ url: '/infra/file/page', params })
6 } 20 }
7 21
yudao-ui-admin-vue3/src/api/infra/fileList/types.ts deleted
1 -export type FileVO = {  
2 - id: number  
3 - path: string  
4 - url: string  
5 - size: string  
6 - type: string  
7 - createTime: string  
8 -}  
yudao-ui-admin-vue3/src/plugins/vxeTable/renderer/img.tsx
1 import { VXETable } from 'vxe-table' 1 import { VXETable } from 'vxe-table'
  2 +import { ElImage } from 'element-plus'
2 3
3 // 图片渲染 4 // 图片渲染
4 VXETable.renderer.add('XImg', { 5 VXETable.renderer.add('XImg', {
@@ -6,13 +7,13 @@ VXETable.renderer.add('XImg', { @@ -6,13 +7,13 @@ VXETable.renderer.add('XImg', {
6 renderDefault(_renderOpts, params) { 7 renderDefault(_renderOpts, params) {
7 const { row, column } = params 8 const { row, column } = params
8 return ( 9 return (
9 - <el-image 10 + <ElImage
10 style="width: 80px; height: 50px" 11 style="width: 80px; height: 50px"
11 src={row[column.field]} 12 src={row[column.field]}
12 key={row[column.field]} 13 key={row[column.field]}
13 fit="contain" 14 fit="contain"
14 lazy 15 lazy
15 - ></el-image> 16 + ></ElImage>
16 ) 17 )
17 } 18 }
18 }) 19 })
yudao-ui-admin-vue3/src/views/infra/fileConfig/fileConfig.data.ts
1 import { reactive } from 'vue' 1 import { reactive } from 'vue'
2 import { useI18n } from '@/hooks/web/useI18n' 2 import { useI18n } from '@/hooks/web/useI18n'
3 import { required } from '@/utils/formRules' 3 import { required } from '@/utils/formRules'
4 -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'  
5 import { DICT_TYPE } from '@/utils/dict' 4 import { DICT_TYPE } from '@/utils/dict'
  5 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
6 const { t } = useI18n() // 国际化 6 const { t } = useI18n() // 国际化
7 7
8 // 表单校验 8 // 表单校验
@@ -25,80 +25,56 @@ export const rules = reactive({ @@ -25,80 +25,56 @@ export const rules = reactive({
25 }) 25 })
26 26
27 // CrudSchema 27 // CrudSchema
28 -const crudSchemas = reactive<CrudSchema[]>([  
29 - {  
30 - label: t('common.index'),  
31 - field: 'id',  
32 - type: 'index',  
33 - form: {  
34 - show: false 28 +const crudSchemas = reactive<VxeCrudSchema>({
  29 + primaryKey: 'id',
  30 + primaryType: 'seq',
  31 + action: true,
  32 + actionWidth: '400px',
  33 + columns: [
  34 + {
  35 + title: '配置名',
  36 + field: 'name',
  37 + isSearch: true
35 }, 38 },
36 - detail: {  
37 - show: false  
38 - }  
39 - },  
40 - {  
41 - label: '配置名',  
42 - field: 'name',  
43 - search: {  
44 - show: true  
45 - }  
46 - },  
47 - {  
48 - label: '存储器',  
49 - field: 'storage',  
50 - dictType: DICT_TYPE.INFRA_FILE_STORAGE,  
51 - dictClass: 'number',  
52 - search: {  
53 - show: true  
54 - }  
55 - },  
56 - {  
57 - label: '主配置',  
58 - field: 'primary',  
59 - dictType: DICT_TYPE.INFRA_BOOLEAN_STRING,  
60 - dictClass: 'number'  
61 - },  
62 - {  
63 - label: t('form.remark'),  
64 - field: 'remark',  
65 - form: {  
66 - component: 'Input',  
67 - componentProps: {  
68 - type: 'textarea',  
69 - rows: 4  
70 - },  
71 - colProps: {  
72 - span: 24  
73 - }  
74 - }  
75 - },  
76 - {  
77 - label: t('common.createTime'),  
78 - field: 'createTime',  
79 - form: {  
80 - show: false 39 + {
  40 + title: '存储器',
  41 + field: 'storage',
  42 + dictType: DICT_TYPE.INFRA_FILE_STORAGE,
  43 + dictClass: 'number',
  44 + isSearch: true
81 }, 45 },
82 - search: {  
83 - show: true,  
84 - component: 'DatePicker',  
85 - componentProps: {  
86 - type: 'datetimerange',  
87 - valueFormat: 'YYYY-MM-DD HH:mm:ss',  
88 - defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] 46 + {
  47 + title: '主配置',
  48 + field: 'master',
  49 + dictType: DICT_TYPE.INFRA_BOOLEAN_STRING,
  50 + dictClass: 'boolean'
  51 + },
  52 + {
  53 + title: t('form.remark'),
  54 + field: 'remark',
  55 + form: {
  56 + component: 'Input',
  57 + componentProps: {
  58 + type: 'textarea',
  59 + rows: 4
  60 + },
  61 + colProps: {
  62 + span: 24
  63 + }
89 } 64 }
90 - }  
91 - },  
92 - {  
93 - label: t('table.action'),  
94 - field: 'action',  
95 - width: '400px',  
96 - form: {  
97 - show: false  
98 }, 65 },
99 - detail: {  
100 - show: false 66 + {
  67 + title: t('common.createTime'),
  68 + field: 'createTime',
  69 + formatter: 'formatDate',
  70 + isForm: false,
  71 + search: {
  72 + show: true,
  73 + itemRender: {
  74 + name: 'XDataTimePicker'
  75 + }
  76 + }
101 } 77 }
102 - }  
103 -])  
104 -export const { allSchemas } = useCrudSchemas(crudSchemas) 78 + ]
  79 +})
  80 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
yudao-ui-admin-vue3/src/views/infra/fileConfig/index.vue
  1 +<template>
  2 + <ContentWrap>
  3 + <!-- 列表 -->
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
  6 + <!-- 操作:新增 -->
  7 + <XButton
  8 + type="primary"
  9 + preIcon="ep:zoom-in"
  10 + :title="t('action.add')"
  11 + v-hasPermi="['infra:file-config:create']"
  12 + @click="handleCreate()"
  13 + />
  14 + </template>
  15 + <template #actionbtns_default="{ row }">
  16 + <XTextButton
  17 + preIcon="ep:edit"
  18 + :title="t('action.edit')"
  19 + v-hasPermi="['infra:file-config:update']"
  20 + @click="handleUpdate(row.id)"
  21 + />
  22 + <XTextButton
  23 + preIcon="ep:view"
  24 + :title="t('action.detail')"
  25 + v-hasPermi="['infra:file-config:query']"
  26 + @click="handleDetail(row.id)"
  27 + />
  28 + <XTextButton
  29 + preIcon="ep:flag"
  30 + title="主配置"
  31 + v-hasPermi="['infra:file-config:update']"
  32 + @click="handleMaster(row)"
  33 + />
  34 + <XTextButton
  35 + preIcon="ep:share"
  36 + :title="t('action.test')"
  37 + v-hasPermi="['infra:file-config:update']"
  38 + @click="handleUpdate(row.id)"
  39 + />
  40 + <XTextButton
  41 + preIcon="ep:delete"
  42 + :title="t('action.del')"
  43 + v-hasPermi="['infra:file-config:delete']"
  44 + @click="handleDelete(row.id)"
  45 + />
  46 + </template>
  47 + </vxe-grid>
  48 + </ContentWrap>
  49 +
  50 + <XModal v-model="dialogVisible" :title="dialogTitle">
  51 + <!-- 对话框(添加 / 修改) -->
  52 + <Form
  53 + v-if="['create', 'update'].includes(actionType)"
  54 + :schema="allSchemas.formSchema"
  55 + :rules="rules"
  56 + ref="formRef"
  57 + />
  58 + <!-- 对话框(详情) -->
  59 + <Descriptions
  60 + v-if="actionType === 'detail'"
  61 + :schema="allSchemas.detailSchema"
  62 + :data="detailData"
  63 + />
  64 + <!-- 操作按钮 -->
  65 + <template #footer>
  66 + <!-- 按钮:保存 -->
  67 + <XButton
  68 + v-if="['create', 'update'].includes(actionType)"
  69 + type="primary"
  70 + :title="t('action.save')"
  71 + :loading="actionLoading"
  72 + @click="submitForm()"
  73 + />
  74 + <!-- 按钮:关闭 -->
  75 + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
  76 + </template>
  77 + </XModal>
  78 +</template>
1 <script setup lang="ts"> 79 <script setup lang="ts">
  80 +// 全局相关的 import
2 import { ref, unref } from 'vue' 81 import { ref, unref } from 'vue'
3 -import dayjs from 'dayjs'  
4 -import { DICT_TYPE } from '@/utils/dict'  
5 -import { useTable } from '@/hooks/web/useTable'  
6 import { useI18n } from '@/hooks/web/useI18n' 82 import { useI18n } from '@/hooks/web/useI18n'
  83 +import { useMessage } from '@/hooks/web/useMessage'
  84 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  85 +import { VxeGridInstance } from 'vxe-table'
7 import { FormExpose } from '@/components/Form' 86 import { FormExpose } from '@/components/Form'
  87 +// 业务相关的 import
  88 +import * as FileConfigApi from '@/api/infra/fileConfig'
8 import type { FileConfigVO } from '@/api/infra/fileConfig/types' 89 import type { FileConfigVO } from '@/api/infra/fileConfig/types'
9 import { rules, allSchemas } from './fileConfig.data' 90 import { rules, allSchemas } from './fileConfig.data'
10 -import * as FileConfigApi from '@/api/infra/fileConfig'  
11 -import { useMessage } from '@/hooks/web/useMessage'  
12 -const message = useMessage()  
13 -const { t } = useI18n() // 国际化  
14 91
15 -// ========== 列表相关 ==========  
16 -const { register, tableObject, methods } = useTable<FileConfigVO>({ 92 +const { t } = useI18n() // 国际化
  93 +const message = useMessage() // 消息弹窗
  94 +// 列表相关的变量
  95 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  96 +const { gridOptions, getList, deleteData } = useVxeGrid<FileConfigVO>({
  97 + allSchemas: allSchemas,
17 getListApi: FileConfigApi.getFileConfigPageApi, 98 getListApi: FileConfigApi.getFileConfigPageApi,
18 - delListApi: FileConfigApi.deleteFileConfigApi 99 + deleteApi: FileConfigApi.deleteFileConfigApi
19 }) 100 })
20 -const { getList, setSearchParams, delList } = methods  
21 101
22 // ========== CRUD 相关 ========== 102 // ========== CRUD 相关 ==========
23 const actionLoading = ref(false) // 遮罩层 103 const actionLoading = ref(false) // 遮罩层
@@ -25,7 +105,7 @@ const actionType = ref(&#39;&#39;) // 操作按钮的类型 @@ -25,7 +105,7 @@ const actionType = ref(&#39;&#39;) // 操作按钮的类型
25 const dialogVisible = ref(false) // 是否显示弹出层 105 const dialogVisible = ref(false) // 是否显示弹出层
26 const dialogTitle = ref('edit') // 弹出层标题 106 const dialogTitle = ref('edit') // 弹出层标题
27 const formRef = ref<FormExpose>() // 表单 Ref 107 const formRef = ref<FormExpose>() // 表单 Ref
28 - 108 +const detailData = ref() // 详情 Ref
29 // 设置标题 109 // 设置标题
30 const setDialogTile = (type: string) => { 110 const setDialogTile = (type: string) => {
31 dialogTitle.value = t('action.' + type) 111 dialogTitle.value = t('action.' + type)
@@ -39,23 +119,36 @@ const handleCreate = () =&gt; { @@ -39,23 +119,36 @@ const handleCreate = () =&gt; {
39 } 119 }
40 120
41 // 修改操作 121 // 修改操作
42 -const handleUpdate = async (row: FileConfigVO) => { 122 +const handleUpdate = async (rowId: number) => {
43 setDialogTile('update') 123 setDialogTile('update')
44 // 设置数据 124 // 设置数据
45 - const res = await FileConfigApi.getFileConfigApi(row.id) 125 + const res = await FileConfigApi.getFileConfigApi(rowId)
46 unref(formRef)?.setValues(res) 126 unref(formRef)?.setValues(res)
47 } 127 }
48 128
  129 +// 详情操作
  130 +const handleDetail = async (rowId: number) => {
  131 + setDialogTile('detail')
  132 + // 设置数据
  133 + const res = await FileConfigApi.getFileConfigApi(rowId)
  134 + detailData.value = res
  135 +}
  136 +
49 // 主配置操作 137 // 主配置操作
50 const handleMaster = (row: FileConfigVO) => { 138 const handleMaster = (row: FileConfigVO) => {
51 message 139 message
52 .confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder')) 140 .confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder'))
53 .then(async () => { 141 .then(async () => {
54 await FileConfigApi.updateFileConfigMasterApi(row.id) 142 await FileConfigApi.updateFileConfigMasterApi(row.id)
55 - await getList() 143 + await getList(xGrid)
56 }) 144 })
57 } 145 }
58 146
  147 +// 删除操作
  148 +const handleDelete = async (rowId: number) => {
  149 + await deleteData(xGrid, rowId)
  150 +}
  151 +
59 // 提交按钮 152 // 提交按钮
60 const submitForm = async () => { 153 const submitForm = async () => {
61 const elForm = unref(formRef)?.getElFormRef() 154 const elForm = unref(formRef)?.getElFormRef()
@@ -73,135 +166,12 @@ const submitForm = async () =&gt; { @@ -73,135 +166,12 @@ const submitForm = async () =&gt; {
73 await FileConfigApi.updateFileConfigApi(data) 166 await FileConfigApi.updateFileConfigApi(data)
74 message.success(t('common.updateSuccess')) 167 message.success(t('common.updateSuccess'))
75 } 168 }
76 - // 操作成功,重新加载列表  
77 dialogVisible.value = false 169 dialogVisible.value = false
78 - await getList()  
79 } finally { 170 } finally {
80 actionLoading.value = false 171 actionLoading.value = false
  172 + await getList(xGrid)
81 } 173 }
82 } 174 }
83 }) 175 })
84 } 176 }
85 -  
86 -// ========== 详情相关 ==========  
87 -const detailRef = ref() // 详情 Ref  
88 -  
89 -// 详情操作  
90 -const handleDetail = async (row: FileConfigVO) => {  
91 - // 设置数据  
92 - detailRef.value = row  
93 - setDialogTile('detail')  
94 -}  
95 -  
96 -// ========== 初始化 ==========  
97 -getList()  
98 </script> 177 </script>
99 -  
100 -<template>  
101 - <!-- 搜索工作区 -->  
102 - <ContentWrap>  
103 - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />  
104 - </ContentWrap>  
105 - <ContentWrap>  
106 - <!-- 操作工具栏 -->  
107 - <div class="mb-10px">  
108 - <el-button type="primary" v-hasPermi="['infra:file-config:create']" @click="handleCreate">  
109 - <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}  
110 - </el-button>  
111 - </div>  
112 - <!-- 列表 -->  
113 - <Table  
114 - :columns="allSchemas.tableColumns"  
115 - :selection="false"  
116 - :data="tableObject.tableList"  
117 - :loading="tableObject.loading"  
118 - :pagination="{  
119 - total: tableObject.total  
120 - }"  
121 - v-model:pageSize="tableObject.pageSize"  
122 - v-model:currentPage="tableObject.currentPage"  
123 - @register="register"  
124 - >  
125 - <template #storage="{ row }">  
126 - <DictTag :type="DICT_TYPE.INFRA_FILE_STORAGE" :value="row.storage" />  
127 - </template>  
128 - <template #primary="{ row }">  
129 - <DictTag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.master" />  
130 - </template>  
131 - <template #createTime="{ row }">  
132 - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>  
133 - </template>  
134 - <template #action="{ row }">  
135 - <el-button  
136 - link  
137 - type="primary"  
138 - v-hasPermi="['infra:file-config:update']"  
139 - @click="handleUpdate(row)"  
140 - >  
141 - <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}  
142 - </el-button>  
143 - <el-button  
144 - link  
145 - type="primary"  
146 - v-hasPermi="['infra:file-config:update']"  
147 - @click="handleDetail(row)"  
148 - >  
149 - <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}  
150 - </el-button>  
151 - <el-button  
152 - link  
153 - type="primary"  
154 - v-hasPermi="['infra:file-config:update']"  
155 - @click="handleMaster(row)"  
156 - >  
157 - <Icon icon="ep:flag" class="mr-1px" /> 主配置  
158 - </el-button>  
159 - <el-button  
160 - link  
161 - type="primary"  
162 - v-hasPermi="['infra:file-config:update']"  
163 - @click="handleUpdate(row)"  
164 - >  
165 - <Icon icon="ep:share" class="mr-1px" /> {{ t('action.test') }}  
166 - </el-button>  
167 - <el-button  
168 - link  
169 - type="primary"  
170 - v-hasPermi="['infra:file-config:delete']"  
171 - @click="delList(row.id, false)"  
172 - >  
173 - <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}  
174 - </el-button>  
175 - </template>  
176 - </Table>  
177 - </ContentWrap>  
178 -  
179 - <XModal v-model="dialogVisible" :title="dialogTitle">  
180 - <!-- 对话框(添加 / 修改) -->  
181 - <Form  
182 - v-if="['create', 'update'].includes(actionType)"  
183 - :schema="allSchemas.formSchema"  
184 - :rules="rules"  
185 - ref="formRef"  
186 - />  
187 - <!-- 对话框(详情) -->  
188 - <Descriptions  
189 - v-if="actionType === 'detail'"  
190 - :schema="allSchemas.detailSchema"  
191 - :data="detailRef"  
192 - />  
193 - <!-- 操作按钮 -->  
194 - <template #footer>  
195 - <!-- 按钮:保存 -->  
196 - <XButton  
197 - v-if="['create', 'update'].includes(actionType)"  
198 - type="primary"  
199 - :title="t('action.save')"  
200 - :loading="actionLoading"  
201 - @click="submitForm()"  
202 - />  
203 - <!-- 按钮:关闭 -->  
204 - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />  
205 - </template>  
206 - </XModal>  
207 -</template>  
yudao-ui-admin-vue3/src/views/infra/fileList/fileList.data.ts
1 import { reactive } from 'vue' 1 import { reactive } from 'vue'
2 import { useI18n } from '@/hooks/web/useI18n' 2 import { useI18n } from '@/hooks/web/useI18n'
3 -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' 3 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
4 const { t } = useI18n() // 国际化 4 const { t } = useI18n() // 国际化
5 5
6 // CrudSchema 6 // CrudSchema
7 -const crudSchemas = reactive<CrudSchema[]>([  
8 - {  
9 - label: t('common.index'),  
10 - field: 'id',  
11 - type: 'index',  
12 - form: {  
13 - show: false  
14 - },  
15 - detail: {  
16 - show: false  
17 - }  
18 - },  
19 - {  
20 - label: '文件名',  
21 - field: 'path',  
22 - search: {  
23 - show: true  
24 - }  
25 - },  
26 - {  
27 - label: 'URL',  
28 - field: 'url'  
29 - },  
30 - {  
31 - label: '文件类型',  
32 - field: 'type'  
33 - },  
34 - {  
35 - label: t('common.createTime'),  
36 - field: 'createTime',  
37 - form: {  
38 - show: false 7 +const crudSchemas = reactive<VxeCrudSchema>({
  8 + primaryKey: 'id',
  9 + primaryType: 'seq',
  10 + action: true,
  11 + columns: [
  12 + {
  13 + title: '文件名',
  14 + field: 'path',
  15 + search: {
  16 + show: true
  17 + }
39 }, 18 },
40 - search: {  
41 - show: true,  
42 - component: 'DatePicker',  
43 - componentProps: {  
44 - type: 'datetimerange',  
45 - valueFormat: 'YYYY-MM-DD HH:mm:ss',  
46 - defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] 19 + {
  20 + title: 'URL',
  21 + field: 'url',
  22 + table: {
  23 + cellRender: {
  24 + name: 'XImg'
  25 + }
47 } 26 }
48 - }  
49 - },  
50 - {  
51 - label: t('table.action'),  
52 - field: 'action',  
53 - width: '300px',  
54 - form: {  
55 - show: false  
56 }, 27 },
57 - detail: {  
58 - show: false 28 + {
  29 + title: '文件类型',
  30 + field: 'type'
  31 + },
  32 + {
  33 + title: t('common.createTime'),
  34 + field: 'createTime',
  35 + formatter: 'formatDate',
  36 + isForm: false,
  37 + search: {
  38 + show: true,
  39 + itemRender: {
  40 + name: 'XDataTimePicker'
  41 + }
  42 + }
59 } 43 }
60 - }  
61 -])  
62 -export const { allSchemas } = useCrudSchemas(crudSchemas) 44 + ]
  45 +})
  46 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
yudao-ui-admin-vue3/src/views/infra/fileList/index.vue
  1 +<template>
  2 + <ContentWrap>
  3 + <!-- 列表 -->
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
  6 + <XButton
  7 + type="primary"
  8 + preIcon="ep:upload"
  9 + title="上传文件"
  10 + @click="uploadDialogVisible = true"
  11 + />
  12 + </template>
  13 + <template #actionbtns_default="{ row }">
  14 + <XTextButton
  15 + preIcon="ep:copy-document"
  16 + :title="t('common.copy')"
  17 + @click="handleCopy(row.url)"
  18 + />
  19 + <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
  20 + <XTextButton
  21 + preIcon="ep:delete"
  22 + :title="t('action.del')"
  23 + v-hasPermi="['infra:file:delete']"
  24 + @click="handleDelete(row.id)"
  25 + />
  26 + </template>
  27 + </vxe-grid>
  28 + </ContentWrap>
  29 +
  30 + <XModal v-model="dialogVisible" :title="dialogTitle">
  31 + <!-- 对话框(详情) -->
  32 + <Descriptions :schema="allSchemas.detailSchema" :data="detailData">
  33 + <template #url="{ row }">
  34 + <el-image
  35 + v-if="row.type === 'jpg' || 'png' || 'gif'"
  36 + style="width: 100px; height: 100px"
  37 + :src="row.url"
  38 + :key="row.url"
  39 + lazy
  40 + />
  41 + <span>{{ row.url }}</span>
  42 + </template>
  43 + </Descriptions>
  44 + <!-- 操作按钮 -->
  45 + <template #footer>
  46 + <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
  47 + </template>
  48 + </XModal>
  49 + <XModal v-model="uploadDialogVisible" :title="uploadDialogTitle">
  50 + <el-upload
  51 + ref="uploadRef"
  52 + :action="updateUrl + '?updateSupport=' + updateSupport"
  53 + :headers="uploadHeaders"
  54 + :drag="true"
  55 + :limit="1"
  56 + :multiple="true"
  57 + :show-file-list="true"
  58 + :disabled="uploadDisabled"
  59 + :before-upload="beforeUpload"
  60 + :on-exceed="handleExceed"
  61 + :on-success="handleFileSuccess"
  62 + :on-error="excelUploadError"
  63 + :auto-upload="false"
  64 + accept=".jpg, .png, .gif"
  65 + >
  66 + <Icon icon="ep:upload-filled" />
  67 + <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  68 + <template #tip>
  69 + <div class="el-upload__tip">请上传 .jpg, .png, .gif 标准格式文件</div>
  70 + </template>
  71 + </el-upload>
  72 + <template #footer>
  73 + <el-button type="primary" @click="submitFileForm">
  74 + <Icon icon="ep:upload-filled" />
  75 + {{ t('action.save') }}
  76 + </el-button>
  77 + <el-button @click="uploadDialogVisible = false">{{ t('dialog.close') }}</el-button>
  78 + </template>
  79 + </XModal>
  80 +</template>
1 <script setup lang="ts"> 81 <script setup lang="ts">
2 import { ref, unref } from 'vue' 82 import { ref, unref } from 'vue'
3 -import dayjs from 'dayjs'  
4 -import { ElMessage, ElUpload, UploadInstance, UploadRawFile, ElImage } from 'element-plus'  
5 -import { useTable } from '@/hooks/web/useTable'  
6 import { useI18n } from '@/hooks/web/useI18n' 83 import { useI18n } from '@/hooks/web/useI18n'
7 -import type { FileVO } from '@/api/infra/fileList/types' 84 +import { useMessage } from '@/hooks/web/useMessage'
  85 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  86 +import { VxeGridInstance } from 'vxe-table'
  87 +import { ElUpload, ElImage, UploadInstance, UploadRawFile } from 'element-plus'
8 import { allSchemas } from './fileList.data' 88 import { allSchemas } from './fileList.data'
9 import * as FileApi from '@/api/infra/fileList' 89 import * as FileApi from '@/api/infra/fileList'
10 import { getAccessToken, getTenantId } from '@/utils/auth' 90 import { getAccessToken, getTenantId } from '@/utils/auth'
11 import { useClipboard } from '@vueuse/core' 91 import { useClipboard } from '@vueuse/core'
12 92
13 const { t } = useI18n() // 国际化 93 const { t } = useI18n() // 国际化
  94 +const message = useMessage() // 消息弹窗
14 95
15 -// ========== 列表相关 ==========  
16 -const { register, tableObject, methods } = useTable<FileVO>({ 96 +// 列表相关的变量
  97 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  98 +const { gridOptions, getList, deleteData } = useVxeGrid<FileApi.FileVO>({
  99 + allSchemas: allSchemas,
17 getListApi: FileApi.getFilePageApi, 100 getListApi: FileApi.getFilePageApi,
18 - delListApi: FileApi.deleteFileApi 101 + deleteApi: FileApi.deleteFileApi
19 }) 102 })
20 -const { getList, setSearchParams, delList } = methods  
21 -// ========== 上传相关 ========== 103 +
  104 +const detailData = ref() // 详情 Ref
  105 +const dialogVisible = ref(false) // 是否显示弹出层
  106 +const dialogTitle = ref('') // 弹出层标题
22 const uploadDialogVisible = ref(false) 107 const uploadDialogVisible = ref(false)
23 const uploadDialogTitle = ref('上传') 108 const uploadDialogTitle = ref('上传')
24 const updateSupport = ref(0) 109 const updateSupport = ref(0)
@@ -30,8 +115,8 @@ const uploadHeaders = ref() @@ -30,8 +115,8 @@ const uploadHeaders = ref()
30 const beforeUpload = (file: UploadRawFile) => { 115 const beforeUpload = (file: UploadRawFile) => {
31 const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png' 116 const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
32 const isLt5M = file.size / 1024 / 1024 < 5 117 const isLt5M = file.size / 1024 / 1024 < 5
33 - if (!isImg) ElMessage.error('上传文件只能是 jpeg / gif / png 格式!')  
34 - if (!isLt5M) ElMessage.error('上传文件大小不能超过 5MB!') 118 + if (!isImg) message.error('上传文件只能是 jpeg / gif / png 格式!')
  119 + if (!isLt5M) message.error('上传文件大小不能超过 5MB!')
35 return isImg && isLt5M 120 return isImg && isLt5M
36 } 121 }
37 // 处理上传的文件发生变化 122 // 处理上传的文件发生变化
@@ -48,154 +133,48 @@ const submitFileForm = () =&gt; { @@ -48,154 +133,48 @@ const submitFileForm = () =&gt; {
48 uploadRef.value!.submit() 133 uploadRef.value!.submit()
49 } 134 }
50 // 文件上传成功 135 // 文件上传成功
51 -const handleFileSuccess = (response: any): void => { 136 +const handleFileSuccess = async (response: any): Promise<void> => {
52 if (response.code !== 0) { 137 if (response.code !== 0) {
53 - ElMessage.error(response.msg) 138 + message.error(response.msg)
54 return 139 return
55 } 140 }
56 - ElMessage.success('上传成功')  
57 - getList() 141 + message.success('上传成功')
58 uploadDialogVisible.value = false 142 uploadDialogVisible.value = false
59 uploadDisabled.value = false 143 uploadDisabled.value = false
  144 + await getList(xGrid)
60 } 145 }
61 // 文件数超出提示 146 // 文件数超出提示
62 const handleExceed = (): void => { 147 const handleExceed = (): void => {
63 - ElMessage.error('最多只能上传一个文件!') 148 + message.error('最多只能上传一个文件!')
64 } 149 }
65 // 上传错误提示 150 // 上传错误提示
66 const excelUploadError = (): void => { 151 const excelUploadError = (): void => {
67 - ElMessage.error('导入数据失败,请您重新上传!') 152 + message.error('导入数据失败,请您重新上传!')
68 } 153 }
69 -// ========== 详情相关 ==========  
70 -const detailRef = ref() // 详情 Ref  
71 -const dialogVisible = ref(false) // 是否显示弹出层  
72 -const dialogTitle = ref('') // 弹出层标题 154 +
73 // 详情操作 155 // 详情操作
74 -const handleDetail = (row: FileVO) => { 156 +const handleDetail = (row: FileApi.FileVO) => {
75 // 设置数据 157 // 设置数据
76 - detailRef.value = row 158 + detailData.value = row
77 dialogTitle.value = t('action.detail') 159 dialogTitle.value = t('action.detail')
78 dialogVisible.value = true 160 dialogVisible.value = true
79 } 161 }
  162 +
  163 +// 删除操作
  164 +const handleDelete = async (rowId: number) => {
  165 + await deleteData(xGrid, rowId)
  166 +}
  167 +
80 // ========== 复制相关 ========== 168 // ========== 复制相关 ==========
81 const handleCopy = async (text: string) => { 169 const handleCopy = async (text: string) => {
82 const { copy, copied, isSupported } = useClipboard({ source: text }) 170 const { copy, copied, isSupported } = useClipboard({ source: text })
83 if (!isSupported) { 171 if (!isSupported) {
84 - ElMessage.error(t('common.copyError')) 172 + message.error(t('common.copyError'))
85 } else { 173 } else {
86 await copy() 174 await copy()
87 if (unref(copied)) { 175 if (unref(copied)) {
88 - ElMessage.success(t('common.copySuccess')) 176 + message.success(t('common.copySuccess'))
89 } 177 }
90 } 178 }
91 } 179 }
92 -// ========== 初始化 ==========  
93 -getList()  
94 </script> 180 </script>
95 -  
96 -<template>  
97 - <!-- 搜索工作区 -->  
98 - <ContentWrap>  
99 - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />  
100 - </ContentWrap>  
101 - <ContentWrap>  
102 - <el-button type="primary" @click="uploadDialogVisible = true">  
103 - <Icon icon="ep:upload" class="mr-5px" /> 上传文件  
104 - </el-button>  
105 - <!-- 列表 -->  
106 - <Table  
107 - :columns="allSchemas.tableColumns"  
108 - :selection="false"  
109 - :data="tableObject.tableList"  
110 - :loading="tableObject.loading"  
111 - :pagination="{  
112 - total: tableObject.total  
113 - }"  
114 - v-model:pageSize="tableObject.pageSize"  
115 - v-model:currentPage="tableObject.currentPage"  
116 - @register="register"  
117 - >  
118 - <template #url="{ row }">  
119 - <el-image  
120 - v-if="row.type === 'jpg' || 'png' || 'gif'"  
121 - style="width: 80px; height: 50px"  
122 - :src="row.url"  
123 - :key="row.url"  
124 - fit="contain"  
125 - lazy  
126 - />  
127 - <span v-else>{{ row.url }}</span>  
128 - </template>  
129 - <template #createTime="{ row }">  
130 - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>  
131 - </template>  
132 - <template #action="{ row }">  
133 - <el-button link type="primary" @click="handleCopy(row.url)">  
134 - <Icon icon="ep:copy-document" class="mr-1px" /> {{ t('common.copy') }}  
135 - </el-button>  
136 - <el-button link type="primary" @click="handleDetail(row)">  
137 - <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}  
138 - </el-button>  
139 - <el-button  
140 - link  
141 - type="primary"  
142 - v-hasPermi="['infra:file:delete']"  
143 - @click="delList(row.id, false)"  
144 - >  
145 - <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}  
146 - </el-button>  
147 - </template>  
148 - </Table>  
149 - </ContentWrap>  
150 -  
151 - <XModal v-model="dialogVisible" :title="dialogTitle">  
152 - <!-- 对话框(详情) -->  
153 - <Descriptions :schema="allSchemas.detailSchema" :data="detailRef">  
154 - <template #url="{ row }">  
155 - <el-image  
156 - v-if="row.type === 'jpg' || 'png' || 'gif'"  
157 - style="width: 100px; height: 100px"  
158 - :src="row.url"  
159 - :key="row.url"  
160 - lazy  
161 - />  
162 - <span>{{ row.url }}</span>  
163 - </template>  
164 - </Descriptions>  
165 - <!-- 操作按钮 -->  
166 - <template #footer>  
167 - <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>  
168 - </template>  
169 - </XModal>  
170 - <XModal v-model="uploadDialogVisible" :title="uploadDialogTitle">  
171 - <el-upload  
172 - ref="uploadRef"  
173 - :action="updateUrl + '?updateSupport=' + updateSupport"  
174 - :headers="uploadHeaders"  
175 - :drag="true"  
176 - :limit="1"  
177 - :multiple="true"  
178 - :show-file-list="true"  
179 - :disabled="uploadDisabled"  
180 - :before-upload="beforeUpload"  
181 - :on-exceed="handleExceed"  
182 - :on-success="handleFileSuccess"  
183 - :on-error="excelUploadError"  
184 - :auto-upload="false"  
185 - accept=".jpg, .png, .gif"  
186 - >  
187 - <Icon icon="ep:upload-filled" />  
188 - <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>  
189 - <template #tip>  
190 - <div class="el-upload__tip">请上传 .jpg, .png, .gif 标准格式文件</div>  
191 - </template>  
192 - </el-upload>  
193 - <template #footer>  
194 - <el-button type="primary" @click="submitFileForm">  
195 - <Icon icon="ep:upload-filled" />  
196 - {{ t('action.save') }}  
197 - </el-button>  
198 - <el-button @click="uploadDialogVisible = false">{{ t('dialog.close') }}</el-button>  
199 - </template>  
200 - </XModal>  
201 -</template>