diff --git a/src/views/archivesManage/managementLibrary/module/collectHeader.vue b/src/views/archivesManage/managementLibrary/module/collectHeader.vue index 3e9302b..e02eaff 100644 --- a/src/views/archivesManage/managementLibrary/module/collectHeader.vue +++ b/src/views/archivesManage/managementLibrary/module/collectHeader.vue @@ -168,7 +168,7 @@ :category-menu="categoryMenu" @close-dialog="closeDialog" /> - diff --git a/src/views/collectReorganizi/collectionLibrary/module/collectHeader.vue b/src/views/collectReorganizi/collectionLibrary/module/collectHeader.vue index 975c187..0314df6 100644 --- a/src/views/collectReorganizi/collectionLibrary/module/collectHeader.vue +++ b/src/views/collectReorganizi/collectionLibrary/module/collectHeader.vue @@ -138,26 +138,46 @@ - +
- +
+ +
+ +
+
+ + {{ aiLoading ? 'AI辅助著录识别中' : '选择文件' }} +
+
+
+ + {{ item.name }} + +
+
+
+
{{ displayedText }}
+
+
@@ -244,6 +264,7 @@ import QuickPaper from './quickPaper/index' import PackingBox from './packingBox/index' import ArchivesFilling from './archivesFilling/index' import qs from 'qs' +// getCurrentTime import { downloadFile, exportFile } from '@/utils/index' import { mapGetters } from 'vuex' @@ -299,7 +320,14 @@ export default { quickPaper: false, quickPaperArcId: [], totalSumAll: 0, - categoryMenu: [] + categoryMenu: [], + isAiAutoCategory: false, + aiLoading: false, + fileList: [], + aiJsonData: null, + displayedText: '', + typingInterval: null, + typingFinished: false } }, computed: { @@ -1232,6 +1260,197 @@ export default { setTimeout(() => { this.handleSearch(this.collectLevel) }) + }, + handleAiCategory() { + this.isAiAutoCategory = !this.isAiAutoCategory + if (!this.isAiAutoCategory) { + this.fileList = [] + } + }, + async changeAiFile(e) { + // 替换文件时清空 aiJsonData + this.aiJsonData = null + this.displayedText = '' + this.typingFinished = false + if (this.typingInterval) { + clearInterval(this.typingInterval) + } + + const selectedFiles = Array.from(e.target.files) + const imageFiles = selectedFiles.filter(file => file.type.startsWith('image/')) + const nonImageFiles = selectedFiles.filter(file => !file.type.startsWith('image/')) + + // 不允许同时选择图片和非图片文件 + if (imageFiles.length > 0 && nonImageFiles.length > 0) { + this.$message.error('不能同时选择图片和其他类型文件,请重新选择') + return + } + + const existingImageFiles = this.fileList.filter(item => item.formatType === 'image') + const existingNonImageFiles = this.fileList.filter(item => item.formatType !== 'image') + + if (imageFiles.length > 0) { + if (existingImageFiles.length > 0) { + if (existingImageFiles.length + imageFiles.length > 3) { + // 若加入新图片会超过 3 张,清空已有图片 + this.fileList = this.fileList.filter(item => item.formatType !== 'image') + } + } else if (existingNonImageFiles.length > 0) { + // 若已有非图片文件,清空已有非图片文件 + this.fileList = this.fileList.filter(item => item.formatType === 'image') + } + + // 检查图片文件数量 + if (imageFiles.length > 3) { + this.$message.error('图片文件最多只能选择 3 个,请重新选择') + return + } + + for (const file of imageFiles) { + // 检查文件是否已存在 + if (this.fileList.some(item => item.name === file.name)) { + this.$message.warning(`文件 ${file.name} 已存在,请勿重复上传`) + continue + } + + const fileInfo = { + file: file, + size: file.size, + formatType: file.type.substring(0, file.type.indexOf('/')), + name: file.name, + postfix: file.name.substring( + file.name.lastIndexOf('.') + 1, + file.name.length + ), + px: '' + } + + const fileBase64 = await this.getBase64(file) + const res = await this.getImgPx(fileBase64) + fileInfo.px = res.width + 'px*' + res.height + 'px' + + this.fileList.push(fileInfo) + this.uploadSave() + } + } else if (nonImageFiles.length > 0) { + if (existingNonImageFiles.length > 0) { + // 若已有非图片文件,直接替换 + this.fileList = this.fileList.filter(item => item.formatType === 'image') + } else if (existingImageFiles.length > 0) { + // 若已有图片文件,清空已有图片文件 + this.fileList = this.fileList.filter(item => item.formatType !== 'image') + } + + // 检查非图片文件数量 + if (nonImageFiles.length > 1) { + this.$message.error('非图片文件最多只能选择 1 个,请重新选择') + return + } + + for (const file of nonImageFiles) { + // 检查文件是否已存在 + if (this.fileList.some(item => item.name === file.name)) { + this.$message.warning(`文件 ${file.name} 已存在,请勿重复上传`) + continue + } + + const fileInfo = { + file: file, + size: file.size, + formatType: file.type.substring(0, file.type.indexOf('/')), + name: file.name, + postfix: file.name.substring( + file.name.lastIndexOf('.') + 1, + file.name.length + ), + px: '' + } + + this.fileList.push(fileInfo) + this.uploadSave() + } + } + }, + uploadSave() { + this.aiLoading = true + this.aiJsonData = null + // this.$refs.previewForm.addOrUpdateForm = {} + + setTimeout(() => { + const json = `{ + "fonds_no": "A001", + "archival_category_code": "WSWJ", + "archive_ctg_no": "SCGL", + "archive_year": "2024", + "retention": "永久", + "item_no": "0005", + "archive_no": "A001-WSWJ·SCGL-2024-Y-0005", + "maintitle": "Windows下如何创建FTP文件夹", + "keyword": "", + "doc_no": "武汉飞天[2024]0005", + "is_entity": 1, + "id": "6C91AAD1F6D9940469F8B0" + }` + + this.aiJsonData = json + this.startTypingEffect() + }, 3000) + }, + startTypingEffect() { + const lines = this.aiJsonData.split('\n') + let currentLineIndex = 0 + this.displayedText = '' + this.typingFinished = false + + this.typingInterval = setInterval(() => { + if (currentLineIndex < lines.length) { + this.displayedText += lines[currentLineIndex] + '\n' + currentLineIndex++ + } else { + clearInterval(this.typingInterval) + + setTimeout(() => { + this.typingFinished = true + this.$refs.previewForm.archivesType = 'add' + this.$refs.previewForm.addOrUpdateForm = JSON.parse(this.aiJsonData) + }, 1000) + } + + // 滚动条始终保持在底部 + const container = this.$refs.typingContainer + if (container) { + container.scrollTop = container.scrollHeight + } + this.aiLoading = false + }, 200) + }, + deleteFile(item) { + const index = this.fileList.indexOf(item) + if (index !== -1) { + this.fileList.splice(index, 1) + } + }, + // 将上传的图片转为base64 + getBase64(file) { + const reader = new FileReader() + reader.readAsDataURL(file) + return new Promise((resolve) => { + reader.onload = () => { + resolve(reader.result) + } + }) + }, + // 获取图片的分辨率 + getImgPx(img) { + const image = new Image() + image.src = img + return new Promise((resolve) => { + image.onload = () => { + const width = image.width + const height = image.height + resolve({ width, height }) + } + }) } } } @@ -1268,4 +1487,25 @@ export default { ::v-deep.vue-treeselect--has-value .vue-treeselect__single-value{ font-size: 14px; } +.ai-preview-dialog{ + ::v-deep .el-dialog{ + width: 1300px !important; + .preview-content{ + width: 728px !important; + } + } +} + +pre { + background-color: #f4f4f4; + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; + white-space: pre-wrap; + word-wrap: break-word; + height: calc(100vh - 430px); + overflow: hidden; + overflow-y: auto; +} + diff --git a/src/views/components/archivesDetail/detail.vue b/src/views/components/archivesDetail/detail.vue index 4df81a0..0f97c12 100644 --- a/src/views/components/archivesDetail/detail.vue +++ b/src/views/components/archivesDetail/detail.vue @@ -29,7 +29,7 @@ - +