阅行客电子档案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
13 KiB

1 month ago
  1. <template>
  2. <div class="upload-file">
  3. <!-- 上传附件curd -->
  4. <div v-if="isUploadDetail" class="upload-curd">
  5. <div class="upload-btn">
  6. <el-button icon="el-icon-plus" size="small" type="primary">添加</el-button>
  7. <input id="upFile" type="file" name="upFile" @change="changeFile($event)">
  8. </div>
  9. <el-button icon="el-icon-delete" :disabled="selections.length === 0" @click="toDelete(selections)">删除</el-button>
  10. <el-button icon="el-icon-sort" @click="showSort">排序</el-button>
  11. </div>
  12. <!--表格渲染-->
  13. <el-table
  14. ref="table"
  15. :data="tableData"
  16. style="min-width: 100%"
  17. height="calc(100vh - 382px)"
  18. @row-click="clickRowHandler"
  19. @selection-change="selectionChangeHandler"
  20. >
  21. <el-table-column v-if="isUploadDetail" type="selection" width="55" align="center" />
  22. <el-table-column type="index" label="序号" width="55" align="center" />
  23. <el-table-column prop="file_name" label="文件名称" show-overflow-tooltip min-width="140" />
  24. <el-table-column prop="file_type" label="格式" min-width="60" align="center" />
  25. <el-table-column prop="file_size" label="大小" min-width="85" align="right">
  26. <template slot-scope="scope">
  27. {{ getFileSize(scope.row.file_size) }}
  28. </template>
  29. </el-table-column>
  30. <!-- <el-table-column prop="file_dpi" label="分辨率" min-width="120" align="center">
  31. <template slot-scope="scope">
  32. <div v-if="!scope.row.file_dpi || scope.row.file_dpi === 'null'"> - </div>
  33. <div v-else> {{ scope.row.file_dpi }} </div>
  34. </template>
  35. </el-table-column> -->
  36. <el-table-column prop="file_thumbnail" label="缩略图" min-width="60" align="center">
  37. <template slot-scope="scope">
  38. <div v-if="scope.row.file_type === 'jpg' || scope.row.file_type === 'jpeg' || scope.row.file_type === 'png' || scope.row.file_type === 'bmp'|| scope.row.file_type === 'gif'">
  39. <i class="fileIcon icon-image" />
  40. </div>
  41. <div v-else-if="scope.row.file_type === 'xlsx' || scope.row.file_type === 'xls'">
  42. <i class="fileIcon icon-excel" />
  43. </div>
  44. <div v-else-if="scope.row.file_type === 'docx' || scope.row.file_type === 'doc'">
  45. <i class="fileIcon icon-word" />
  46. </div>
  47. <div v-else-if="scope.row.file_type === 'pdf'">
  48. <i class="fileIcon icon-pdf" />
  49. </div>
  50. <div v-else-if="scope.row.file_type === 'ppt' || scope.row.file_type === 'pptx'">
  51. <i class="fileIcon icon-ppt" />
  52. </div>
  53. <div v-else-if="scope.row.file_type === 'zip' || scope.row.file_type === 'rar'">
  54. <i class="fileIcon icon-zip" />
  55. </div>
  56. <div v-else-if="scope.row.file_type === 'txt'">
  57. <i class="fileIcon icon-txt" />
  58. </div>
  59. <div v-else-if="scope.row.file_type === 'ofd'">
  60. <i class="fileIcon icon-ofd" />
  61. </div>
  62. <div v-else>
  63. <i class="fileIcon icon-other" />
  64. </div>
  65. </template>
  66. </el-table-column>
  67. <el-table-column prop="create_time" label="创建时间" min-width="130" align="center" />
  68. </el-table>
  69. <!-- 排序 -->
  70. <el-dialog :close-on-click-modal="false" :append-to-body="true" title="排序" :visible.sync="sortVisible" @opened="opened">
  71. <span class="dialog-right-top" />
  72. <span class="dialog-left-bottom" />
  73. <div class="setting-dialog">
  74. <i class="drag-tip">提示请通过拖动鼠标来调整当前顺序</i>
  75. <el-table :data="sortTableData" class="file-sort" style="width: 100%;max-height: 70vh;" row-key="id">
  76. <el-table-column type="index" label="序号" width="100" align="center" />
  77. <el-table-column prop="file_name" label="文件名称" />
  78. </el-table>
  79. <div slot="footer" class="dialog-footer">
  80. <el-button type="primary" @click.native="handleSort">保存</el-button>
  81. </div>
  82. </div>
  83. </el-dialog>
  84. <!-- 删除附件 -->
  85. <el-dialog title="删除附件" :append-to-body="true" :close-on-click-modal="false" :visible.sync="deleteVisible" :before-close="handleClose">
  86. <span class="dialog-right-top" />
  87. <span class="dialog-left-bottom" />
  88. <div class="setting-dialog">
  89. <div class="dialog-delt">
  90. <p><span>确定删除已选择的附件吗</span></p>
  91. </div>
  92. <div slot="footer" class="dialog-footer">
  93. <el-button type="primary" @click.native="handleDeltConfirm">确定</el-button>
  94. </div>
  95. </div>
  96. </el-dialog>
  97. </div>
  98. </template>
  99. <script>
  100. // import { FetchInitArchiveFilesView, FetchEditFile, FetchDeleteFile, FetchFileSort } from '@/api/archivesManage/archivesList'
  101. import { FetchInitFileCategoryView } from '@/api/collect/collect'
  102. import { archivesUpload } from '@/utils/upload'
  103. import { downloadFile, getCurrentTime } from '@/utils/index'
  104. import { mapGetters } from 'vuex'
  105. import { form } from '@crud/crud'
  106. import Sortable from 'sortablejs'
  107. export default {
  108. name: 'UploadFile',
  109. components: {},
  110. mixins: [
  111. form({})
  112. ],
  113. inject: ['parentsData'],
  114. props: {
  115. isUploadDetail: {
  116. type: Boolean,
  117. default: true
  118. },
  119. storageCategory: {
  120. type: Object,
  121. default: function() {
  122. return {}
  123. }
  124. },
  125. arcId: {
  126. type: String,
  127. default: function() {
  128. return ''
  129. }
  130. }
  131. },
  132. data() {
  133. return {
  134. defaultImg: 'this.src="' + require('@/assets/images/cover-bg.png') + '"',
  135. tableData: [], // 附件list
  136. selections: [], // table - 选中的
  137. showCoverVisible: false, // 查看大图dialog
  138. sortTableData: [], // 排序data
  139. sortVisible: false, // 排序dialog
  140. deleteVisible: false, // 删除附件 dialog
  141. deleteData: [], // 删除选中的data
  142. file: null, // 附件 change
  143. fileNames: '', // 附件 - name
  144. formatType: '', // 附件 - type
  145. postfix: '', // 附件 - 文件后缀
  146. fileSize: '', // 附件 - 大小
  147. filePath: '', // 附件 - path
  148. px: '', // 附件 - 分辨率
  149. nowDate: '', // 当前时间
  150. previewSrc: '' // 查看大图src
  151. }
  152. },
  153. computed: {
  154. ...mapGetters([
  155. 'baseApi'
  156. ])
  157. },
  158. watch: {
  159. arcId: function(newValue, oldValue) {
  160. }
  161. },
  162. methods: {
  163. getFileSize(fileSize) {
  164. // 1. 先将接口返回的KB值转为数字,处理非数字/空值情况
  165. const sizeInKB = Number(fileSize)
  166. if (isNaN(sizeInKB) || sizeInKB < 0) {
  167. return '0 KB' // 异常值默认显示0 KB
  168. }
  169. // 2. 定义单位换算关系(1 MB = 1024 KB,1 GB = 1024 MB)
  170. const KB = 1
  171. const MB = 1024 * KB
  172. const GB = 1024 * MB
  173. // 3. 根据大小自动选择单位并格式化
  174. if (sizeInKB >= GB) {
  175. // 大于等于1GB,显示GB(保留2位小数)
  176. return (sizeInKB / GB).toFixed(2) + ' GB'
  177. } else if (sizeInKB >= MB) {
  178. // 大于等于1MB且小于1GB,显示MB(保留2位小数)
  179. return (sizeInKB / MB).toFixed(2) + ' MB'
  180. } else if (sizeInKB < 1) {
  181. // 不足1KB,统一显示1 KB(保持你之前的需求)
  182. return '1 KB'
  183. } else {
  184. // 1KB到1MB之间,显示KB(保留2位小数)
  185. return sizeInKB + ' KB'
  186. }
  187. },
  188. // 选择附件
  189. async changeFile(e) {
  190. this.file = e.target.files[0]
  191. this.fileSize = this.file.size
  192. this.formatType = this.file.type.substring(0, this.file.type.indexOf('/'))
  193. this.fileNames = this.file.name
  194. this.postfix = this.file.name.substring(
  195. this.fileNames.lastIndexOf('.') + 1,
  196. this.fileNames.length
  197. )
  198. if (this.formatType === 'image') {
  199. const fileBase64 = await this.getBase64(this.file)
  200. const res = await this.getImgPx(fileBase64)
  201. this.px = res.width + 'px*' + res.height + 'px'
  202. } else {
  203. this.px = ''
  204. }
  205. // 上传附件
  206. archivesUpload(this.baseApi + '/api/archives/uploadFile', this.file, this.categoryId).then(res => {
  207. if (res.data.code === 200) {
  208. this.filePath = res.data.data
  209. this.uploadSave()
  210. }
  211. })
  212. },
  213. // 上传附件 - 选择上传即保存
  214. uploadSave() {
  215. this.nowDate = getCurrentTime()
  216. const json = {
  217. 'file_name': this.fileNames,
  218. 'file_size': this.fileSize,
  219. 'file_type': this.postfix,
  220. 'file_path': this.filePath,
  221. 'sequence': null,
  222. 'archive_id': this.arcId,
  223. 'file_dpi': this.px,
  224. 'file_thumbnail': '',
  225. 'create_time': this.nowDate,
  226. 'id': null
  227. }
  228. const arrayUpload = []
  229. arrayUpload.push(json)
  230. const params = {
  231. 'categoryId': this.categoryId,
  232. 'jsonString': JSON.stringify(arrayUpload)
  233. }
  234. console.log(params)
  235. // FetchEditFile(params).then(data => {
  236. // this.$message.success('上传附件成功!')
  237. // this.crud.refresh()
  238. // this.getFileList()
  239. // })
  240. },
  241. // 将上传的图片转为base64
  242. getBase64(file) {
  243. const reader = new FileReader()
  244. reader.readAsDataURL(file)
  245. return new Promise((resolve) => {
  246. reader.onload = () => {
  247. resolve(reader.result)
  248. }
  249. })
  250. },
  251. // 获取图片的分辨率
  252. getImgPx(img) {
  253. const image = new Image()
  254. image.src = img
  255. return new Promise((resolve) => {
  256. image.onload = () => {
  257. const width = image.width
  258. const height = image.height
  259. resolve({ width, height })
  260. }
  261. })
  262. },
  263. // 上传list
  264. getFileList() {
  265. const params = {
  266. 'categoryId': this.storageCategory.id,
  267. 'archivesId': this.arcId,
  268. 'page': 0,
  269. 'size': 10
  270. }
  271. console.log(params)
  272. FetchInitFileCategoryView(params).then(data => {
  273. console.log('darta', data)
  274. this.tableData = data.returnlist
  275. })
  276. },
  277. // 下载附件
  278. downloadFile(row) {
  279. const url = this.baseApi + '/downloadFile' + row.file_path
  280. fetch(url).then(res => res.blob()).then(blob => {
  281. downloadFile(blob, row.file_name.split('.')[0], row.file_type)
  282. }).catch(() => {
  283. this.$message({ message: '下载文件失败', type: 'error', offset: 8 })
  284. })
  285. },
  286. // 选择删除
  287. toDelete(data) {
  288. this.deleteData = data
  289. this.deleteVisible = true
  290. },
  291. // 确认删除
  292. handleDeltConfirm() {
  293. this.deleteVisible = false
  294. const ids = []
  295. this.deleteData.forEach(val => {
  296. ids.push(val.id)
  297. })
  298. const params = {
  299. 'ids': ids,
  300. 'categoryId': this.categoryId
  301. }
  302. console.log(params)
  303. // 删除fetch
  304. // FetchDeleteFile(params).then(res => {
  305. // this.crud.delAllLoading = false
  306. // this.$message.success('删除成功!')
  307. // this.crud.refresh()
  308. // this.getFileList()
  309. // })
  310. },
  311. // 排序 - 行拖拽
  312. rowDrop(className, targetName) {
  313. // 此时找到的元素是要拖拽元素的父容器
  314. const tbody = document.querySelector('.' + className + ' .el-table__body-wrapper tbody')
  315. const that = this
  316. Sortable.create(tbody, {
  317. // 指定父元素下可被拖拽的子元素
  318. draggable: '.el-table__row',
  319. onEnd({ newIndex, oldIndex }) {
  320. if (newIndex === oldIndex) return
  321. that[targetName].splice(newIndex, 0, that[targetName].splice(oldIndex, 1)[0])
  322. }
  323. })
  324. },
  325. // 排序
  326. opened() {
  327. this.rowDrop('file-sort', 'sortTableData')
  328. },
  329. showSort() {
  330. this.sortVisible = true
  331. this.sortTableData = JSON.parse(JSON.stringify(this.tableData))
  332. },
  333. // 排序 - 保存
  334. handleSort() {
  335. const ids = []
  336. const sequences = []
  337. this.sortTableData.map((value, index) => {
  338. ids.push(value.id)
  339. sequences.push(index + 1)
  340. })
  341. const params = {
  342. 'categoryId': this.categoryId,
  343. 'ids': ids,
  344. 'sequences': sequences
  345. }
  346. console.log(params)
  347. // FetchFileSort(params).then((res) => {
  348. // this.sortVisible = false
  349. // this.$message.success('附件排序成功!')
  350. // this.crud.refresh()
  351. // this.getFileList()
  352. // })
  353. },
  354. // table
  355. clickRowHandler(row) {
  356. this.$refs.table.toggleRowSelection(row)
  357. },
  358. // table
  359. selectionChangeHandler(val) {
  360. this.selections = val
  361. },
  362. // dialog - close
  363. handleClose(done) {
  364. this.showCoverVisible = false
  365. done()
  366. },
  367. // 查看大图
  368. showCoverPreview(row) {
  369. this.showCoverVisible = true
  370. this.previewSrc = this.baseApi + '/downloadFile' + row.file_path
  371. }
  372. }
  373. }
  374. </script>
  375. <style lang="scss" scoped>
  376. .svg-style{
  377. width: 60px;
  378. height: 32px;
  379. }
  380. </style>