index.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. <XModal v-model="dialogVisible" :title="dialogTitle">
  30. <!-- 对话框(详情) -->
  31. <Descriptions :schema="allSchemas.detailSchema" :data="detailData">
  32. <template #url="{ row }">
  33. <el-image
  34. v-if="row.type === 'jpg' || 'png' || 'gif'"
  35. style="width: 100px; height: 100px"
  36. :src="row.url"
  37. :key="row.url"
  38. lazy
  39. />
  40. <span>{{ row.url }}</span>
  41. </template>
  42. </Descriptions>
  43. <!-- 操作按钮 -->
  44. <template #footer>
  45. <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
  46. </template>
  47. </XModal>
  48. <XModal v-model="uploadDialogVisible" :title="uploadDialogTitle">
  49. <el-upload
  50. ref="uploadRef"
  51. :action="updateUrl + '?updateSupport=' + updateSupport"
  52. :headers="uploadHeaders"
  53. :drag="true"
  54. :limit="1"
  55. :multiple="true"
  56. :show-file-list="true"
  57. :disabled="uploadDisabled"
  58. :before-upload="beforeUpload"
  59. :on-exceed="handleExceed"
  60. :on-success="handleFileSuccess"
  61. :on-error="excelUploadError"
  62. :auto-upload="false"
  63. accept=".jpg, .png, .gif"
  64. >
  65. <Icon icon="ep:upload-filled" />
  66. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  67. <template #tip>
  68. <div class="el-upload__tip">请上传 .jpg, .png, .gif 标准格式文件</div>
  69. </template>
  70. </el-upload>
  71. <template #footer>
  72. <el-button type="primary" @click="submitFileForm">
  73. <Icon icon="ep:upload-filled" />
  74. {{ t('action.save') }}
  75. </el-button>
  76. <el-button @click="uploadDialogVisible = false">{{ t('dialog.close') }}</el-button>
  77. </template>
  78. </XModal>
  79. </template>
  80. <script setup lang="ts" name="FileList">
  81. import { ref, unref } from 'vue'
  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'
  86. import { ElUpload, ElImage, UploadInstance, UploadRawFile } from 'element-plus'
  87. // 业务相关的 import
  88. // TODO 星语:貌似这个界面打开 404
  89. import { allSchemas } from './fileList.data'
  90. import * as FileApi from '@/api/infra/fileList'
  91. import { getAccessToken, getTenantId } from '@/utils/auth'
  92. import { useClipboard } from '@vueuse/core'
  93. const { t } = useI18n() // 国际化
  94. const message = useMessage() // 消息弹窗
  95. // 列表相关的变量
  96. const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  97. const { gridOptions, getList, deleteData } = useVxeGrid<FileApi.FileVO>({
  98. allSchemas: allSchemas,
  99. getListApi: FileApi.getFilePageApi,
  100. deleteApi: FileApi.deleteFileApi
  101. })
  102. const detailData = ref() // 详情 Ref
  103. const dialogVisible = ref(false) // 是否显示弹出层
  104. const dialogTitle = ref('') // 弹出层标题
  105. const uploadDialogVisible = ref(false)
  106. const uploadDialogTitle = ref('上传')
  107. const updateSupport = ref(0)
  108. const uploadDisabled = ref(false)
  109. const uploadRef = ref<UploadInstance>()
  110. let updateUrl = import.meta.env.VITE_UPLOAD_URL
  111. const uploadHeaders = ref()
  112. // 文件上传之前判断
  113. const beforeUpload = (file: UploadRawFile) => {
  114. const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
  115. const isLt5M = file.size / 1024 / 1024 < 5
  116. if (!isImg) message.error('上传文件只能是 jpeg / gif / png 格式!')
  117. if (!isLt5M) message.error('上传文件大小不能超过 5MB!')
  118. return isImg && isLt5M
  119. }
  120. // 处理上传的文件发生变化
  121. // const handleFileChange = (uploadFile: UploadFile): void => {
  122. // uploadRef.value.data.path = uploadFile.name
  123. // }
  124. // 文件上传
  125. const submitFileForm = () => {
  126. uploadHeaders.value = {
  127. Authorization: 'Bearer ' + getAccessToken(),
  128. 'tenant-id': getTenantId()
  129. }
  130. uploadDisabled.value = true
  131. uploadRef.value!.submit()
  132. }
  133. // 文件上传成功
  134. const handleFileSuccess = async (response: any): Promise<void> => {
  135. if (response.code !== 0) {
  136. message.error(response.msg)
  137. return
  138. }
  139. message.success('上传成功')
  140. uploadDialogVisible.value = false
  141. uploadDisabled.value = false
  142. await getList(xGrid)
  143. }
  144. // 文件数超出提示
  145. const handleExceed = (): void => {
  146. message.error('最多只能上传一个文件!')
  147. }
  148. // 上传错误提示
  149. const excelUploadError = (): void => {
  150. message.error('导入数据失败,请您重新上传!')
  151. }
  152. // 详情操作
  153. const handleDetail = (row: FileApi.FileVO) => {
  154. // 设置数据
  155. detailData.value = row
  156. dialogTitle.value = t('action.detail')
  157. dialogVisible.value = true
  158. }
  159. // 删除操作
  160. const handleDelete = async (rowId: number) => {
  161. await deleteData(xGrid, rowId)
  162. }
  163. // ========== 复制相关 ==========
  164. const handleCopy = async (text: string) => {
  165. const { copy, copied, isSupported } = useClipboard({ source: text })
  166. if (!isSupported) {
  167. message.error(t('common.copyError'))
  168. } else {
  169. await copy()
  170. if (unref(copied)) {
  171. message.success(t('common.copySuccess'))
  172. }
  173. }
  174. }
  175. </script>