@@ -229,7 +264,7 @@
-
+
@@ -247,7 +282,8 @@
import CRUD, { crud } from '@crud/crud'
import { collectionLibraryCrud } from '../mixins/index'
import { FetchInitCategoryInputFieldByPid, FetchCategoryMenu } from '@/api/system/category/category'
-import { FetchDetailsById, collectDel, FetchRemoveArchivesSingle, FetchDeleteArchivesFile, FetchUpdateArchivesNo, FetchDisbandArchives, FetchReturnReDocument, FetchCompleteDelArchives, FetchRestoreArchives, FetchAIResultZhulu } from '@/api/collect/collect'
+import { FetchDetailsById, collectDel, FetchRemoveArchivesSingle, FetchDeleteArchivesFile, FetchUpdateArchivesNo, FetchDisbandArchives, FetchReturnReDocument, FetchCompleteDelArchives, FetchRestoreArchives } from '@/api/collect/collect'
+import { FetchInitAssistEnter, FetchDoHandleEnterAnalysis } from '@/api/ai/ai'
import { FetchArchivesClassTree } from '@/api/system/archivesClass'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
@@ -266,8 +302,7 @@ import QuickPaper from './quickPaper/index'
import PackingBox from './packingBox/index'
import ArchivesFilling from './archivesFilling/index'
import qs from 'qs'
-import { archivesUpload } from '@/utils/upload'
-import { downloadFile, exportFile, getCurrentTime } from '@/utils/index'
+import { downloadFile, exportFile } from '@/utils/index'
import { mapGetters } from 'vuex'
export default {
@@ -309,6 +344,7 @@ export default {
inject: ['parentsData'],
data() {
return {
+ archivesBtnLoading: false,
activeMenuIndex: '1',
formVisible: false,
formTitle: '项目',
@@ -324,15 +360,14 @@ export default {
totalSumAll: 0,
categoryMenu: [],
isAiAutoCategory: false,
- aiLoading: false,
- nowDate: '',
- fileList: [],
- aiJsonData: null,
displayedText: '',
- typingInterval: null,
- typingFinished: false,
- currentLineIndex: 0,
- shouldContinueFetching: true
+ formIsAddOrEdit: '',
+ aIAssistEnterVisible: false,
+ aiCategoryData: [],
+ aiCategoryloading: false,
+ aiResultCaLoading: true, // ai分析得内容结果前得loading
+ isDialogClosed: false, // 新增标志位,用于控制是否继续处理流式响应
+ reader: null // 用于存储响应体的读取器
}
},
computed: {
@@ -489,6 +524,7 @@ export default {
},
// 著录界面-form/详情-api
handleForm(type, isPaper) {
+ this.formIsAddOrEdit = type
if (type === 'add') {
if (this.parentsData.parentsProjectId && this.isTitleType === 3) {
console.log('项目下的案卷')
@@ -530,6 +566,14 @@ export default {
})
},
getFormInfo(type) {
+ const currentPageSize = localStorage.getItem('currentPageSize')
+ if (currentPageSize) {
+ this.page.size = parseInt(currentPageSize)
+ } else {
+ this.page.size = 10
+ }
+ console.log('this.page.size', this.page.size)
+ console.log('this.page.page', this.page.page)
if (type === 'edit') {
const params = {
'categoryId': this.selectedCategory.id,
@@ -557,38 +601,76 @@ export default {
FetchInitCategoryInputFieldByPid(params).then(data => {
this.formPreviewData = data
this.isDesFormType = 'arcives'
+
this.$nextTick(() => {
this.$refs.previewForm.archivesType = 'add'
this.$refs.previewForm.activeIndex = this.activeIndex
+ const savePrevFromData = JSON.parse(localStorage.getItem('savePrevFromData'))
+ console.log('savePrevFromData', savePrevFromData)
+ if (savePrevFromData) {
+ if ('record_no' in savePrevFromData && 'item_no' in savePrevFromData) {
+ if (savePrevFromData.item_no && !isNaN(Number(savePrevFromData.item_no))) {
+ savePrevFromData.item_no = (parseInt(savePrevFromData.item_no) + 1).toString()
+ }
+ } else if ('record_no' in savePrevFromData) {
+ if (savePrevFromData.record_no && !isNaN(Number(savePrevFromData.record_no))) {
+ savePrevFromData.record_no = (parseInt(savePrevFromData.record_no) + 1).toString()
+ }
+ } else if ('item_no' in savePrevFromData) {
+ if (savePrevFromData.item_no && !isNaN(Number(savePrevFromData.item_no))) {
+ savePrevFromData.item_no = (parseInt(savePrevFromData.item_no) + 1).toString()
+ }
+ }
+
+ // 查找 item_no 或 record_no 字段并进行补零操作
+ const findAndPadField = (fieldName) => {
+ const field = this.formPreviewData.find(item => item.fieldName === fieldName)
+ if (field && field.isFilling) {
+ const fillingDigit = field.fillingDigit
+ if (savePrevFromData[fieldName]) {
+ savePrevFromData[fieldName] = savePrevFromData[fieldName].toString().padStart(fillingDigit, '0')
+ }
+ }
+ }
+
+ findAndPadField('item_no')
+ findAndPadField('record_no')
+
+ this.$refs.previewForm.addOrUpdateForm = savePrevFromData
+ }
this.$refs.previewForm.FetchNoFormatField(this.selectedCategory.id)
})
})
}
},
// form - submit
- handlerArchivesSubmit() {
+ handlerArchivesSubmit(type) {
+ this.$refs.previewForm.submitForm('addOrUpdateForm', this.selectedCategory.id, this.quickPaperArcId, type)
+ },
+ handlerArchivesSubmitAndAdd() {
this.$refs.previewForm.submitForm('addOrUpdateForm', this.selectedCategory.id, this.quickPaperArcId)
},
+ formLoadingShow(loadingType) {
+ this.archivesBtnLoading = loadingType
+ },
// 关闭
handleClose(done) {
- this.shouldContinueFetching = false
this.formVisible = false
this.quickPaper = false
-
+ localStorage.removeItem('savePrevFromData')
+ this.aiCategoryData = []
this.isAiAutoCategory = false
- this.aiJsonData = null
- this.currentLineIndex = 0
- this.displayedText = ''
- this.typingFinished = false
- if (this.typingInterval) {
- clearInterval(this.typingInterval)
+ this.displayedText = '' // 清空 displayedText
+ this.isDialogClosed = true // 设置标志位为 true
+ if (this.reader) {
+ this.reader.cancel() // 取消读取器,终止流式响应
}
- this.fileList = []
- this.aiLoading = false
done()
},
// 删除
toDelete() {
+ console.log('this.page.page333', this.page.page)
+ console.log('this.page.total33333', this.page.total)
if (this.selections.length === 0) {
this.$message({ message: '您还未勾选需要操作的条目,请先确认!', offset: 8 })
return false
@@ -629,6 +711,8 @@ export default {
FetchCompleteDelArchives(params).then((res) => {
if (res.code !== 500) {
this.$message({ message: res, type: 'success', offset: 8 })
+ localStorage.removeItem('currentPageSize')
+ localStorage.removeItem('currentPage')
this.handleSearch(this.collectLevel)
} else {
this.$message({ message: '删除所选档案失败', type: 'error', offset: 8 })
@@ -669,6 +753,8 @@ export default {
})
FetchDeleteArchivesFile(params).then((res) => {
if (res === 'SUCCESS') {
+ localStorage.removeItem('currentPageSize')
+ localStorage.removeItem('currentPage')
this.$message({ message: '删除成功', type: 'success', offset: 8 })
this.handleSearch(this.collectLevel)
} else {
@@ -689,6 +775,8 @@ export default {
}
collectDel(params).then((res) => {
if (res.includes('成功')) {
+ localStorage.removeItem('currentPageSize')
+ localStorage.removeItem('currentPage')
this.$message({ message: '删除成功', type: 'success', offset: 8 })
this.handleSearch(this.collectLevel)
} else {
@@ -713,6 +801,8 @@ export default {
}
FetchRemoveArchivesSingle(params).then((res) => {
if (res === true) {
+ localStorage.removeItem('currentPageSize')
+ localStorage.removeItem('currentPage')
this.$message({ message: '移出成功', type: 'success', offset: 8 })
this.handleSearch(this.collectLevel)
} else {
@@ -996,6 +1086,12 @@ export default {
}
this.$refs.archivesFillingRef.archivesFillingVisible = true
},
+ handleFillingToFourTest(resultList) {
+ this.$refs.fourTestRef.fourTestVisible = true
+ this.$refs.fourTestRef.tableData = this.selections
+ this.$refs.fourTestRef.updateTableData(resultList, this.selections)
+ this.$refs.fourTestRef.isCheck = true
+ },
// 退回预归档库
handleReturn() {
if (this.selections.length === 0) {
@@ -1170,6 +1266,8 @@ export default {
// this.$message('所选条目中存在已装盒档案,请勿重复操作!')
// return false
// }
+ console.log('this.parentsData', this.parentsData)
+ console.log('this.parentsData.listCategory', this.parentsData.listCategory.id)
this.$refs.packingBox.packingVisible = true
this.$refs.packingBox.isPackingOrPartType = type
this.$refs.packingBox.packFileCategory = this.parentsData.listCategory
@@ -1226,6 +1324,8 @@ export default {
}
FetchRestoreArchives(params).then((res) => {
if (res.code !== 500) {
+ localStorage.removeItem('currentPageSize')
+ localStorage.removeItem('currentPage')
if (res.includes('成功')) {
this.$message({ message: res, type: 'success', offset: 8 })
} else {
@@ -1283,232 +1383,132 @@ export default {
})
},
handleAiCategory() {
- this.isAiAutoCategory = !this.isAiAutoCategory
- if (!this.isAiAutoCategory) {
- this.fileList = []
+ this.aIAssistEnterVisible = true
+ this.aiCategoryloading = true
+ const params = {
+ 'page': 0,
+ 'size': 10,
+ 'isHandle': 0
}
+ FetchInitAssistEnter(params).then(data => {
+ this.aiCategoryData = data
+ this.aiCategoryloading = false
+ setTimeout(() => {
+ this.getDoHandleEnterAnalysis()
+ }, 1000)
+ })
},
- async changeAiFile(e) {
- // 替换文件时清空 aiJsonData
- this.aiJsonData = null
- this.currentLineIndex = 0
- this.displayedText = ''
- this.typingFinished = false
- this.typingInterval = null
- // 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
+ // 获取自动分析内容和提问
+ getDoHandleEnterAnalysis(row) {
+ this.isAiAutoCategory = true
+ this.aIAssistEnterVisible = false
+ const params = {
+ 'categoryId': this.selectedCategory.id,
+ 'anId': null
}
+ FetchDoHandleEnterAnalysis(params).then(data => {
+ console.log(data)
+ // const inputMessage = data.query + '需要提取得内容部分是' + data.context
+ this.sendMessage(data.query, data.context)
+ })
+ },
+ // 向deepseek发出提问和分析内容
+ async sendMessage(prompt, context) {
+ const linkSrc = process.env.NODE_ENV === 'production' ? window.g.AIDeepSeekUrl : process.env.VUE_APP_AIDEEPSEEK_API
+ this.displayedText = ''
+ this.isDialogClosed = false // 重置标志位
+ try {
+ // { 'role': 'system', 'content': '你是一个数据分析助手' },
+ const messages = [
+ { 'role': 'user', 'content': `${context}\n\n${prompt}` }
+ ]
+ const response = await fetch(linkSrc + '/api/generate', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ model: 'deepseek-r1:14b',
+ // model: 'qwen:7b',
+ prompt: messages[0].content,
+ stream: true
+ })
+ })
- 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
- // }
- if (existingNonImageFiles.length > 0) {
- // 若已有非图片文件,清空已有非图片文件
- this.fileList = this.fileList.filter(item => item.formatType === 'image')
- }
-
- 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.FetchAiFileUplaod(this.fileList)
- } 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 (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`)
}
- // 检查非图片文件数量
- if (nonImageFiles.length > 1) {
- this.$message.error('非图片文件最多只能选择 1 个,请重新选择')
- return
- }
+ this.reader = response.body.getReader() // 存储读取器
+ const decoder = new TextDecoder('utf-8')
+ let done = false
- for (const file of nonImageFiles) {
- // 检查文件是否已存在
- if (this.fileList.some(item => item.name === file.name)) {
- this.$message.warning(`文件 ${file.name} 已存在,请勿重复上传`)
- continue
- }
+ while (!done && !this.isDialogClosed) { // 检查标志位
+ this.aiResultCaLoading = false
+ const { done: isDone, value } = await this.reader.read()
+ done = isDone
+ if (done) break
- 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.FetchAiFileUplaod(this.fileList)
- }
- },
- FetchAiFileUplaod(files) {
- this.aiLoading = true
- this.nowDate = getCurrentTime()
- const promiseArray = files.map(async(item, index) => {
- const json = {}
- json.file_name = item.name
- json.file_size = item.size
- json.file_type = item.postfix
- json.file_path = ''
- json.archive_id = this.arcId
- json.file_dpi = item.px
- json.file_thumbnail = ''
- json.create_time = this.nowDate
- json.id = null
- json.last_modified = item.file.lastModified
- return json
- })
- console.log('promiseArray', promiseArray)
- const fileDefault = files.map(item => item.file)
+ const chunk = decoder.decode(value)
+ const lines = chunk.split('\n')
- Promise.all(promiseArray)
- .then((arrayUpload) => {
- archivesUpload(this.baseApi + '/api/collect/uploadAssistEnterFiles',
- fileDefault,
- this.selectedCategory.id,
- this.arcId,
- JSON.stringify(arrayUpload)
- ).then(res => {
- if (res.data.data !== null) {
- const params = {
- 'code': res.data.data.code,
- 'id': res.data.data.id
+ lines.forEach(line => {
+ if (line.trim() !== '') {
+ try {
+ const data = JSON.parse(line)
+ if (data.response && !this.isDialogClosed) { // 再次检查标志位
+ this.displayedText += data.response
+ }
+ } catch (error) {
+ console.error('解析JSON数据出错:', error)
}
- const fetchAiZhuluResult = () => {
- // 检查是否应该继续请求
- if (!this.shouldContinueFetching) return
-
- FetchAIResultZhulu(params).then((res) => {
- const data = JSON.parse(res)
- console.log('data', data)
- if (data.result !== null && data.status === 'success') {
- this.$message({ message: '解析著录附件成功', type: 'success', offset: 8 })
- this.aiJsonData = data.result
- this.startTypingEffect()
- } else {
- setTimeout(fetchAiZhuluResult, 3000)
- }
- }).catch(err => {
- console.log(err)
- })
- }
- fetchAiZhuluResult()
- } else {
- this.$message({ message: '著录附件传输失败', type: 'error', offset: 8 })
}
})
- })
- .catch((error) => {
- console.error(error)
- })
- },
- startTypingEffect() {
- const lines = this.aiJsonData.split('\n')
- this.currentLineIndex = 0
- this.displayedText = ''
- this.typingFinished = false
-
- this.typingInterval = setInterval(() => {
- if (this.currentLineIndex < lines.length) {
- this.displayedText += lines[this.currentLineIndex] + '\n'
- this.currentLineIndex++
- } else {
- clearInterval(this.typingInterval)
- setTimeout(() => {
- this.typingFinished = true
- if (this.aiJsonData) {
- // this.$refs.previewForm.archivesType = 'add'
- // this.$refs.previewForm.addOrUpdateForm = JSON.parse(this.aiJsonData)
- this.aiLoading = false
- }
- }, 1000)
+ // 滚动条始终保持在底部
+ const container = this.$refs.typingContainer
+ if (container) {
+ container.scrollTop = container.scrollHeight
+ }
}
+ } catch (error) {
+ console.error('请求出错:', error)
+ this.displayedText = '请求出错,请稍后再试。'
+ this.aiResultCaLoading = false
+ } finally {
+ this.aiResultCaLoading = false
+ if (!this.isDialogClosed) {
+ console.log('this.displayedText.', this.displayedText)
- // 滚动条始终保持在底部
- const container = this.$refs.typingContainer
- if (container) {
- container.scrollTop = container.scrollHeight
- }
- }, 200)
- },
- // 将上传的图片转为base64
- getBase64(file) {
- const reader = new FileReader()
- reader.readAsDataURL(file)
- return new Promise((resolve) => {
- reader.onload = () => {
- resolve(reader.result)
+ // 去除
和 之间的内容
+ const thinkStartIndex = this.displayedText.indexOf('
')
+ const thinkEndIndex = this.displayedText.indexOf('')
+ let lastContent = this.displayedText
+ if (thinkStartIndex !== -1 && thinkEndIndex !== -1) {
+ lastContent = lastContent.slice(0, thinkStartIndex) + lastContent.slice(thinkEndIndex + ''.length)
+ }
+ console.log('lastContent', lastContent)
+ // 提取 JSON 部分
+ const startIndex = lastContent.indexOf('{')
+ const endIndex = lastContent.lastIndexOf('}')
+ if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
+ const jsonStr = lastContent.slice(startIndex, endIndex + 1)
+ console.log('jsonStr', jsonStr)
+ const jsonData = JSON.parse(jsonStr)
+ console.log('提取并过滤后的 JSON 数据:', jsonData)
+ console.log('this.selectedCategory', this.selectedCategory)
+ jsonData.fonds_no = this.selectedCategory.fondsNo
+ jsonData.archival_category_code = this.selectedCategory.code
+ jsonData.is_entity = 1
+ console.log('jsonData', jsonData)
+ this.$refs.previewForm.addOrUpdateForm = jsonData
+ }
}
- })
+ this.reader = null // 清空读取器
+ }
},
- // 获取图片的分辨率
- 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 })
- }
- })
+ replaceSeparators(str) {
+ return str.replace(/[,,、]/g, ' ')
}
}
}
@@ -1553,6 +1553,11 @@ export default {
}
}
}
+.aiAssist-dialog{
+ ::v-deep .el-dialog{
+ width: 1000px !important;
+ }
+}
pre {
background-color: #f4f4f4;
@@ -1561,7 +1566,7 @@ pre {
border-radius: 4px;
white-space: pre-wrap;
word-wrap: break-word;
- height: calc(100vh - 430px);
+ height: calc(100vh - 330px);
overflow: hidden;
overflow-y: auto;
}
diff --git a/src/views/collectReorganizi/collectionLibrary/module/collectMoveFile/index.vue b/src/views/collectReorganizi/collectionLibrary/module/collectMoveFile/index.vue
index 65323d1..7bdebc9 100644
--- a/src/views/collectReorganizi/collectionLibrary/module/collectMoveFile/index.vue
+++ b/src/views/collectReorganizi/collectionLibrary/module/collectMoveFile/index.vue
@@ -77,7 +77,7 @@