index.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <ContentWrap>
  3. <!-- 列表 -->
  4. <XTable @register="registerTable">
  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="deleteData(row.id)"
  25. />
  26. </template>
  27. </XTable>
  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. <XButton :title="t('dialog.close')" @click="dialogVisible = false" />
  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. :on-change="handleFileChange"
  63. :before-remove="beforeRemove"
  64. :auto-upload="false"
  65. accept=".jpg, .png, .gif"
  66. >
  67. <Icon icon="ep:upload-filled" />
  68. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  69. <template #tip>
  70. <div class="el-upload__tip">请上传 .jpg, .png, .gif 标准格式文件</div>
  71. </template>
  72. </el-upload>
  73. <template #footer>
  74. <!-- 按钮:保存 -->
  75. <XButton
  76. type="primary"
  77. preIcon="ep:upload-filled"
  78. :title="t('action.save')"
  79. @click="submitFileForm()"
  80. />
  81. <!-- 按钮:关闭 -->
  82. <XButton :title="t('dialog.close')" @click="uploadDialogVisible = false" />
  83. </template>
  84. </XModal>
  85. </template>
  86. <script setup lang="ts" name="FileList">
  87. import type { UploadInstance, UploadRawFile, UploadProps, UploadFile } from 'element-plus'
  88. // 业务相关的 import
  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 [registerTable, { reload, deleteData }] = useXTable({
  97. allSchemas: allSchemas,
  98. getListApi: FileApi.getFilePageApi,
  99. deleteApi: FileApi.deleteFileApi
  100. })
  101. const detailData = ref() // 详情 Ref
  102. const dialogVisible = ref(false) // 是否显示弹出层
  103. const dialogTitle = ref('') // 弹出层标题
  104. const uploadDialogVisible = ref(false)
  105. const uploadDialogTitle = ref('上传')
  106. const updateSupport = ref(0)
  107. const uploadDisabled = ref(false)
  108. const uploadRef = ref<UploadInstance>()
  109. let updateUrl = import.meta.env.VITE_UPLOAD_URL
  110. const uploadHeaders = ref()
  111. // 文件上传之前判断
  112. const beforeUpload = (file: UploadRawFile) => {
  113. const isImg = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
  114. const isLt5M = file.size / 1024 / 1024 < 5
  115. if (!isImg) message.error('上传文件只能是 jpeg / gif / png 格式!')
  116. if (!isLt5M) message.error('上传文件大小不能超过 5MB!')
  117. return isImg && isLt5M
  118. }
  119. // 处理上传的文件发生变化
  120. const handleFileChange = (uploadFile: UploadFile): void => {
  121. // uploadRef.value.data.path = uploadFile.name
  122. console.log(uploadFile, 'uploadFile')
  123. uploadDisabled.value = false
  124. }
  125. // 文件上传
  126. const submitFileForm = () => {
  127. uploadHeaders.value = {
  128. Authorization: 'Bearer ' + getAccessToken(),
  129. 'tenant-id': getTenantId()
  130. }
  131. uploadDisabled.value = true
  132. uploadRef.value!.submit()
  133. }
  134. // 文件上传成功
  135. const handleFileSuccess = async (response: any): Promise<void> => {
  136. if (response.code !== 0) {
  137. message.error(response.msg)
  138. return
  139. }
  140. message.success('上传成功')
  141. uploadDialogVisible.value = false
  142. uploadDisabled.value = false
  143. await reload()
  144. }
  145. const beforeRemove: UploadProps['beforeRemove'] = () => {
  146. uploadDisabled.value = false
  147. }
  148. // 文件数超出提示
  149. const handleExceed = (): void => {
  150. message.error('最多只能上传一个文件!')
  151. uploadDisabled.value = false
  152. }
  153. // 上传错误提示
  154. const excelUploadError = (): void => {
  155. message.error('导入数据失败,请您重新上传!')
  156. uploadDisabled.value = false
  157. }
  158. // 详情操作
  159. const handleDetail = (row: FileApi.FileVO) => {
  160. // 设置数据
  161. detailData.value = row
  162. dialogTitle.value = t('action.detail')
  163. dialogVisible.value = true
  164. }
  165. // ========== 复制相关 ==========
  166. const handleCopy = async (text: string) => {
  167. let url = text
  168. let oInput = document.createElement('textarea')
  169. oInput.value = url
  170. document.body.appendChild(oInput)
  171. oInput.select() // 选择对象;
  172. // console.log(oInput.value)
  173. document.execCommand('Copy') // 执行浏览器复制命令
  174. message.success(t('common.copySuccess'))
  175. oInput.remove()
  176. // const { copy, copied, isSupported } = useClipboard({ source: text, read: true })
  177. // console.log(copy, 'copycopycopy')
  178. // console.log(copied, 'copiedcopiedcopied')
  179. // console.log(isSupported, 'isSupportedisSupportedisSupported')
  180. // if (!isSupported.value) {
  181. // message.error(t('common.copyError'))
  182. // } else {
  183. // await copy()
  184. // if (unref(copied.value)) {
  185. // message.success(t('common.copySuccess'))
  186. // }
  187. // }
  188. }
  189. </script>