refactor: file vxe

This commit is contained in:
xingyu4j 2022-11-22 16:41:43 +08:00
parent e6acf9e8dc
commit 562282b2ad
8 changed files with 339 additions and 423 deletions

View File

@ -15,7 +15,7 @@ export type FileConfigVO = {
id: number id: number
name: string name: string
storage: string storage: string
primary: number master: boolean
visible: boolean visible: boolean
config: ConfigType config: ConfigType
remark: string remark: string

View File

@ -1,7 +1,21 @@
import request from '@/config/axios' import request from '@/config/axios'
export type FileVO = {
id: number
path: string
url: string
size: string
type: string
createTime: string
}
export interface FilePageReqVO extends PageParam {
name?: string
createTime?: string[]
}
// 查询文件列表 // 查询文件列表
export const getFilePageApi = (params) => { export const getFilePageApi = (params: FilePageReqVO) => {
return request.get({ url: '/infra/file/page', params }) return request.get({ url: '/infra/file/page', params })
} }

View File

@ -1,8 +0,0 @@
export type FileVO = {
id: number
path: string
url: string
size: string
type: string
createTime: string
}

View File

@ -1,4 +1,5 @@
import { VXETable } from 'vxe-table' import { VXETable } from 'vxe-table'
import { ElImage } from 'element-plus'
// 图片渲染 // 图片渲染
VXETable.renderer.add('XImg', { VXETable.renderer.add('XImg', {
@ -6,13 +7,13 @@ VXETable.renderer.add('XImg', {
renderDefault(_renderOpts, params) { renderDefault(_renderOpts, params) {
const { row, column } = params const { row, column } = params
return ( return (
<el-image <ElImage
style="width: 80px; height: 50px" style="width: 80px; height: 50px"
src={row[column.field]} src={row[column.field]}
key={row[column.field]} key={row[column.field]}
fit="contain" fit="contain"
lazy lazy
></el-image> ></ElImage>
) )
} }
}) })

View File

@ -1,8 +1,8 @@
import { reactive } from 'vue' import { reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { required } from '@/utils/formRules' import { required } from '@/utils/formRules'
import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE } from '@/utils/dict'
import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
const { t } = useI18n() // 国际化 const { t } = useI18n() // 国际化
// 表单校验 // 表单校验
@ -25,80 +25,56 @@ export const rules = reactive({
}) })
// CrudSchema // CrudSchema
const crudSchemas = reactive<CrudSchema[]>([ const crudSchemas = reactive<VxeCrudSchema>({
{ primaryKey: 'id',
label: t('common.index'), primaryType: 'seq',
field: 'id', action: true,
type: 'index', actionWidth: '400px',
form: { columns: [
show: false {
title: '配置名',
field: 'name',
isSearch: true
}, },
detail: { {
show: false title: '存储器',
} field: 'storage',
}, dictType: DICT_TYPE.INFRA_FILE_STORAGE,
{ dictClass: 'number',
label: '配置名', isSearch: true
field: 'name', },
search: { {
show: true title: '主配置',
} field: 'master',
}, dictType: DICT_TYPE.INFRA_BOOLEAN_STRING,
{ dictClass: 'boolean'
label: '存储器', },
field: 'storage', {
dictType: DICT_TYPE.INFRA_FILE_STORAGE, title: t('form.remark'),
dictClass: 'number', field: 'remark',
search: { form: {
show: true component: 'Input',
} componentProps: {
}, type: 'textarea',
{ rows: 4
label: '主配置', },
field: 'primary', colProps: {
dictType: DICT_TYPE.INFRA_BOOLEAN_STRING, span: 24
dictClass: 'number' }
}, }
{ },
label: t('form.remark'), {
field: 'remark', title: t('common.createTime'),
form: { field: 'createTime',
component: 'Input', formatter: 'formatDate',
componentProps: { isForm: false,
type: 'textarea', search: {
rows: 4 show: true,
}, itemRender: {
colProps: { name: 'XDataTimePicker'
span: 24 }
} }
} }
}, ]
{ })
label: t('common.createTime'), export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
field: 'createTime',
form: {
show: false
},
search: {
show: true,
component: 'DatePicker',
componentProps: {
type: 'datetimerange',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]
}
}
},
{
label: t('table.action'),
field: 'action',
width: '400px',
form: {
show: false
},
detail: {
show: false
}
}
])
export const { allSchemas } = useCrudSchemas(crudSchemas)

View File

@ -1,23 +1,103 @@
<template>
<ContentWrap>
<!-- 列表 -->
<vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
<template #toolbar_buttons>
<!-- 操作新增 -->
<XButton
type="primary"
preIcon="ep:zoom-in"
:title="t('action.add')"
v-hasPermi="['infra:file-config:create']"
@click="handleCreate()"
/>
</template>
<template #actionbtns_default="{ row }">
<XTextButton
preIcon="ep:edit"
:title="t('action.edit')"
v-hasPermi="['infra:file-config:update']"
@click="handleUpdate(row.id)"
/>
<XTextButton
preIcon="ep:view"
:title="t('action.detail')"
v-hasPermi="['infra:file-config:query']"
@click="handleDetail(row.id)"
/>
<XTextButton
preIcon="ep:flag"
title="主配置"
v-hasPermi="['infra:file-config:update']"
@click="handleMaster(row)"
/>
<XTextButton
preIcon="ep:share"
:title="t('action.test')"
v-hasPermi="['infra:file-config:update']"
@click="handleUpdate(row.id)"
/>
<XTextButton
preIcon="ep:delete"
:title="t('action.del')"
v-hasPermi="['infra:file-config:delete']"
@click="handleDelete(row.id)"
/>
</template>
</vxe-grid>
</ContentWrap>
<XModal v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form
v-if="['create', 'update'].includes(actionType)"
:schema="allSchemas.formSchema"
:rules="rules"
ref="formRef"
/>
<!-- 对话框(详情) -->
<Descriptions
v-if="actionType === 'detail'"
:schema="allSchemas.detailSchema"
:data="detailData"
/>
<!-- 操作按钮 -->
<template #footer>
<!-- 按钮保存 -->
<XButton
v-if="['create', 'update'].includes(actionType)"
type="primary"
:title="t('action.save')"
:loading="actionLoading"
@click="submitForm()"
/>
<!-- 按钮关闭 -->
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
</template>
</XModal>
</template>
<script setup lang="ts"> <script setup lang="ts">
// import
import { ref, unref } from 'vue' import { ref, unref } from 'vue'
import dayjs from 'dayjs'
import { DICT_TYPE } from '@/utils/dict'
import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
import { VxeGridInstance } from 'vxe-table'
import { FormExpose } from '@/components/Form' import { FormExpose } from '@/components/Form'
// import
import * as FileConfigApi from '@/api/infra/fileConfig'
import type { FileConfigVO } from '@/api/infra/fileConfig/types' import type { FileConfigVO } from '@/api/infra/fileConfig/types'
import { rules, allSchemas } from './fileConfig.data' import { rules, allSchemas } from './fileConfig.data'
import * as FileConfigApi from '@/api/infra/fileConfig'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() //
// ========== ========== const { t } = useI18n() //
const { register, tableObject, methods } = useTable<FileConfigVO>({ const message = useMessage() //
//
const xGrid = ref<VxeGridInstance>() // Grid Ref
const { gridOptions, getList, deleteData } = useVxeGrid<FileConfigVO>({
allSchemas: allSchemas,
getListApi: FileConfigApi.getFileConfigPageApi, getListApi: FileConfigApi.getFileConfigPageApi,
delListApi: FileConfigApi.deleteFileConfigApi deleteApi: FileConfigApi.deleteFileConfigApi
}) })
const { getList, setSearchParams, delList } = methods
// ========== CRUD ========== // ========== CRUD ==========
const actionLoading = ref(false) // const actionLoading = ref(false) //
@ -25,7 +105,7 @@ const actionType = ref('') // 操作按钮的类型
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const dialogTitle = ref('edit') // const dialogTitle = ref('edit') //
const formRef = ref<FormExpose>() // Ref const formRef = ref<FormExpose>() // Ref
const detailData = ref() // Ref
// //
const setDialogTile = (type: string) => { const setDialogTile = (type: string) => {
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
@ -39,23 +119,36 @@ const handleCreate = () => {
} }
// //
const handleUpdate = async (row: FileConfigVO) => { const handleUpdate = async (rowId: number) => {
setDialogTile('update') setDialogTile('update')
// //
const res = await FileConfigApi.getFileConfigApi(row.id) const res = await FileConfigApi.getFileConfigApi(rowId)
unref(formRef)?.setValues(res) unref(formRef)?.setValues(res)
} }
//
const handleDetail = async (rowId: number) => {
setDialogTile('detail')
//
const res = await FileConfigApi.getFileConfigApi(rowId)
detailData.value = res
}
// //
const handleMaster = (row: FileConfigVO) => { const handleMaster = (row: FileConfigVO) => {
message message
.confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder')) .confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder'))
.then(async () => { .then(async () => {
await FileConfigApi.updateFileConfigMasterApi(row.id) await FileConfigApi.updateFileConfigMasterApi(row.id)
await getList() await getList(xGrid)
}) })
} }
//
const handleDelete = async (rowId: number) => {
await deleteData(xGrid, rowId)
}
// //
const submitForm = async () => { const submitForm = async () => {
const elForm = unref(formRef)?.getElFormRef() const elForm = unref(formRef)?.getElFormRef()
@ -73,135 +166,12 @@ const submitForm = async () => {
await FileConfigApi.updateFileConfigApi(data) await FileConfigApi.updateFileConfigApi(data)
message.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
//
dialogVisible.value = false dialogVisible.value = false
await getList()
} finally { } finally {
actionLoading.value = false actionLoading.value = false
await getList(xGrid)
} }
} }
}) })
} }
// ========== ==========
const detailRef = ref() // Ref
//
const handleDetail = async (row: FileConfigVO) => {
//
detailRef.value = row
setDialogTile('detail')
}
// ========== ==========
getList()
</script> </script>
<template>
<!-- 搜索工作区 -->
<ContentWrap>
<Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
</ContentWrap>
<ContentWrap>
<!-- 操作工具栏 -->
<div class="mb-10px">
<el-button type="primary" v-hasPermi="['infra:file-config:create']" @click="handleCreate">
<Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
</el-button>
</div>
<!-- 列表 -->
<Table
:columns="allSchemas.tableColumns"
:selection="false"
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="{
total: tableObject.total
}"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
@register="register"
>
<template #storage="{ row }">
<DictTag :type="DICT_TYPE.INFRA_FILE_STORAGE" :value="row.storage" />
</template>
<template #primary="{ row }">
<DictTag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.master" />
</template>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template #action="{ row }">
<el-button
link
type="primary"
v-hasPermi="['infra:file-config:update']"
@click="handleUpdate(row)"
>
<Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
</el-button>
<el-button
link
type="primary"
v-hasPermi="['infra:file-config:update']"
@click="handleDetail(row)"
>
<Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
</el-button>
<el-button
link
type="primary"
v-hasPermi="['infra:file-config:update']"
@click="handleMaster(row)"
>
<Icon icon="ep:flag" class="mr-1px" /> 主配置
</el-button>
<el-button
link
type="primary"
v-hasPermi="['infra:file-config:update']"
@click="handleUpdate(row)"
>
<Icon icon="ep:share" class="mr-1px" /> {{ t('action.test') }}
</el-button>
<el-button
link
type="primary"
v-hasPermi="['infra:file-config:delete']"
@click="delList(row.id, false)"
>
<Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
</el-button>
</template>
</Table>
</ContentWrap>
<XModal v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form
v-if="['create', 'update'].includes(actionType)"
:schema="allSchemas.formSchema"
:rules="rules"
ref="formRef"
/>
<!-- 对话框(详情) -->
<Descriptions
v-if="actionType === 'detail'"
:schema="allSchemas.detailSchema"
:data="detailRef"
/>
<!-- 操作按钮 -->
<template #footer>
<!-- 按钮保存 -->
<XButton
v-if="['create', 'update'].includes(actionType)"
type="primary"
:title="t('action.save')"
:loading="actionLoading"
@click="submitForm()"
/>
<!-- 按钮关闭 -->
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
</template>
</XModal>
</template>

View File

@ -1,62 +1,46 @@
import { reactive } from 'vue' import { reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
const { t } = useI18n() // 国际化 const { t } = useI18n() // 国际化
// CrudSchema // CrudSchema
const crudSchemas = reactive<CrudSchema[]>([ const crudSchemas = reactive<VxeCrudSchema>({
{ primaryKey: 'id',
label: t('common.index'), primaryType: 'seq',
field: 'id', action: true,
type: 'index', columns: [
form: { {
show: false title: '文件名',
field: 'path',
search: {
show: true
}
}, },
detail: { {
show: false title: 'URL',
} field: 'url',
}, table: {
{ cellRender: {
label: '文件名', name: 'XImg'
field: 'path', }
search: { }
show: true
}
},
{
label: 'URL',
field: 'url'
},
{
label: '文件类型',
field: 'type'
},
{
label: t('common.createTime'),
field: 'createTime',
form: {
show: false
}, },
search: { {
show: true, title: '文件类型',
component: 'DatePicker', field: 'type'
componentProps: { },
type: 'datetimerange', {
valueFormat: 'YYYY-MM-DD HH:mm:ss', title: t('common.createTime'),
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] field: 'createTime',
formatter: 'formatDate',
isForm: false,
search: {
show: true,
itemRender: {
name: 'XDataTimePicker'
}
} }
} }
}, ]
{ })
label: t('table.action'), export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
field: 'action',
width: '300px',
form: {
show: false
},
detail: {
show: false
}
}
])
export const { allSchemas } = useCrudSchemas(crudSchemas)

View File

@ -1,156 +1,35 @@
<script setup lang="ts">
import { ref, unref } from 'vue'
import dayjs from 'dayjs'
import { ElMessage, ElUpload, UploadInstance, UploadRawFile, ElImage } from 'element-plus'
import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n'
import type { FileVO } from '@/api/infra/fileList/types'
import { allSchemas } from './fileList.data'
import * as FileApi from '@/api/infra/fileList'
import { getAccessToken, getTenantId } from '@/utils/auth'
import { useClipboard } from '@vueuse/core'
const { t } = useI18n() //
// ========== ==========
const { register, tableObject, methods } = useTable<FileVO>({
getListApi: FileApi.getFilePageApi,
delListApi: FileApi.deleteFileApi
})
const { getList, setSearchParams, delList } = methods
// ========== ==========
const uploadDialogVisible = ref(false)
const uploadDialogTitle = ref('上传')
const updateSupport = ref(0)
const uploadDisabled = ref(false)
const uploadRef = ref<UploadInstance>()
let updateUrl = import.meta.env.VITE_UPLOAD_URL
const uploadHeaders = ref()
//
const beforeUpload = (file: UploadRawFile) => {
const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
const isLt5M = file.size / 1024 / 1024 < 5
if (!isImg) ElMessage.error('上传文件只能是 jpeg / gif / png 格式!')
if (!isLt5M) ElMessage.error('上传文件大小不能超过 5MB!')
return isImg && isLt5M
}
//
// const handleFileChange = (uploadFile: UploadFile): void => {
// uploadRef.value.data.path = uploadFile.name
// }
//
const submitFileForm = () => {
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}
uploadDisabled.value = true
uploadRef.value!.submit()
}
//
const handleFileSuccess = (response: any): void => {
if (response.code !== 0) {
ElMessage.error(response.msg)
return
}
ElMessage.success('上传成功')
getList()
uploadDialogVisible.value = false
uploadDisabled.value = false
}
//
const handleExceed = (): void => {
ElMessage.error('最多只能上传一个文件!')
}
//
const excelUploadError = (): void => {
ElMessage.error('导入数据失败,请您重新上传!')
}
// ========== ==========
const detailRef = ref() // Ref
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
//
const handleDetail = (row: FileVO) => {
//
detailRef.value = row
dialogTitle.value = t('action.detail')
dialogVisible.value = true
}
// ========== ==========
const handleCopy = async (text: string) => {
const { copy, copied, isSupported } = useClipboard({ source: text })
if (!isSupported) {
ElMessage.error(t('common.copyError'))
} else {
await copy()
if (unref(copied)) {
ElMessage.success(t('common.copySuccess'))
}
}
}
// ========== ==========
getList()
</script>
<template> <template>
<!-- 搜索工作区 -->
<ContentWrap> <ContentWrap>
<Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
</ContentWrap>
<ContentWrap>
<el-button type="primary" @click="uploadDialogVisible = true">
<Icon icon="ep:upload" class="mr-5px" /> 上传文件
</el-button>
<!-- 列表 --> <!-- 列表 -->
<Table <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
:columns="allSchemas.tableColumns" <template #toolbar_buttons>
:selection="false" <XButton
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="{
total: tableObject.total
}"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
@register="register"
>
<template #url="{ row }">
<el-image
v-if="row.type === 'jpg' || 'png' || 'gif'"
style="width: 80px; height: 50px"
:src="row.url"
:key="row.url"
fit="contain"
lazy
/>
<span v-else>{{ row.url }}</span>
</template>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template #action="{ row }">
<el-button link type="primary" @click="handleCopy(row.url)">
<Icon icon="ep:copy-document" class="mr-1px" /> {{ t('common.copy') }}
</el-button>
<el-button link type="primary" @click="handleDetail(row)">
<Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
</el-button>
<el-button
link
type="primary" type="primary"
v-hasPermi="['infra:file:delete']" preIcon="ep:upload"
@click="delList(row.id, false)" title="上传文件"
> @click="uploadDialogVisible = true"
<Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }} />
</el-button>
</template> </template>
</Table> <template #actionbtns_default="{ row }">
<XTextButton
preIcon="ep:copy-document"
:title="t('common.copy')"
@click="handleCopy(row.url)"
/>
<XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" />
<XTextButton
preIcon="ep:delete"
:title="t('action.del')"
v-hasPermi="['infra:file:delete']"
@click="handleDelete(row.id)"
/>
</template>
</vxe-grid>
</ContentWrap> </ContentWrap>
<XModal v-model="dialogVisible" :title="dialogTitle"> <XModal v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(详情) --> <!-- 对话框(详情) -->
<Descriptions :schema="allSchemas.detailSchema" :data="detailRef"> <Descriptions :schema="allSchemas.detailSchema" :data="detailData">
<template #url="{ row }"> <template #url="{ row }">
<el-image <el-image
v-if="row.type === 'jpg' || 'png' || 'gif'" v-if="row.type === 'jpg' || 'png' || 'gif'"
@ -199,3 +78,103 @@ getList()
</template> </template>
</XModal> </XModal>
</template> </template>
<script setup lang="ts">
import { ref, unref } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
import { VxeGridInstance } from 'vxe-table'
import { ElUpload, ElImage, UploadInstance, UploadRawFile } from 'element-plus'
import { allSchemas } from './fileList.data'
import * as FileApi from '@/api/infra/fileList'
import { getAccessToken, getTenantId } from '@/utils/auth'
import { useClipboard } from '@vueuse/core'
const { t } = useI18n() //
const message = useMessage() //
//
const xGrid = ref<VxeGridInstance>() // Grid Ref
const { gridOptions, getList, deleteData } = useVxeGrid<FileApi.FileVO>({
allSchemas: allSchemas,
getListApi: FileApi.getFilePageApi,
deleteApi: FileApi.deleteFileApi
})
const detailData = ref() // Ref
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const uploadDialogVisible = ref(false)
const uploadDialogTitle = ref('上传')
const updateSupport = ref(0)
const uploadDisabled = ref(false)
const uploadRef = ref<UploadInstance>()
let updateUrl = import.meta.env.VITE_UPLOAD_URL
const uploadHeaders = ref()
//
const beforeUpload = (file: UploadRawFile) => {
const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
const isLt5M = file.size / 1024 / 1024 < 5
if (!isImg) message.error('上传文件只能是 jpeg / gif / png 格式!')
if (!isLt5M) message.error('上传文件大小不能超过 5MB!')
return isImg && isLt5M
}
//
// const handleFileChange = (uploadFile: UploadFile): void => {
// uploadRef.value.data.path = uploadFile.name
// }
//
const submitFileForm = () => {
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}
uploadDisabled.value = true
uploadRef.value!.submit()
}
//
const handleFileSuccess = async (response: any): Promise<void> => {
if (response.code !== 0) {
message.error(response.msg)
return
}
message.success('上传成功')
uploadDialogVisible.value = false
uploadDisabled.value = false
await getList(xGrid)
}
//
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
//
const excelUploadError = (): void => {
message.error('导入数据失败,请您重新上传!')
}
//
const handleDetail = (row: FileApi.FileVO) => {
//
detailData.value = row
dialogTitle.value = t('action.detail')
dialogVisible.value = true
}
//
const handleDelete = async (rowId: number) => {
await deleteData(xGrid, rowId)
}
// ========== ==========
const handleCopy = async (text: string) => {
const { copy, copied, isSupported } = useClipboard({ source: text })
if (!isSupported) {
message.error(t('common.copyError'))
} else {
await copy()
if (unref(copied)) {
message.success(t('common.copySuccess'))
}
}
}
</script>