From 17b1cc476f66145470ffed57c4534ef15811aa1b Mon Sep 17 00:00:00 2001 From: wangxiaoshuang <825034831@qq.com> Date: Thu, 25 Dec 2025 14:50:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=9Edicom=E9=98=85=E7=89=87=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E4=BF=AE=E6=94=B9=E3=80=81IVUS=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=A4=9A=E9=80=89=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/customSort.js | 346 ++++++++++++++++++ src/views/none-dicom-show/index.vue | 28 +- .../dicoms/components/IVUS/QuestionList.vue | 18 +- .../components/IVUS/QuestionTableFormItem.vue | 183 +++------ .../dicoms/components/OCT/QuestionList.vue | 8 +- .../reading/dicoms/none-dicoms.vue | 24 +- .../none-dicoms/components/VisitReview.vue | 24 +- 7 files changed, 473 insertions(+), 158 deletions(-) create mode 100644 src/utils/customSort.js diff --git a/src/utils/customSort.js b/src/utils/customSort.js new file mode 100644 index 00000000..ba42c940 --- /dev/null +++ b/src/utils/customSort.js @@ -0,0 +1,346 @@ +class FileNameSorter { + /** + * 判断是否为纯数字字符串 + * @param {any} value - 要检查的值 + * @returns {boolean} 是否为纯数字 + */ + static isPureNumber(value) { + if (typeof value !== 'string') return false; + return /^\d+$/.test(value); + } + + /** + * 获取排序键值 + * @param {any} item - 要排序的项目 + * @returns {Array} 排序键值数组 + */ + static getSortKey(item) { + const str = String(item); + const isNumber = this.isPureNumber(str); + + // 排序优先级: [类型优先级, 数字值/字符串值] + if (isNumber) { + // 纯数字: 类型优先级为0, 使用数字值排序 + return [0, BigInt(str)]; + } else { + // 非纯数字: 类型优先级为1, 使用字符串排序 + return [1, str.toLowerCase()]; + } + } + + /** + * 文件名排序 + * @param {Array} arr - 要排序的数组 + * @param {Object} options - 排序选项 + * @returns {Array} 排序后的数组 + */ + static sortFileNames(arr, options = {}) { + if (!Array.isArray(arr)) { + throw new TypeError('输入必须是一个数组'); + } + + const { + direction = 'asc', // 'asc' 升序, 'desc' 降序 + caseSensitive = false, // 是否区分大小写 + trim = true, // 是否去除前后空格 + key = null + } = options; + + // 创建数组的副本 + const result = [...arr]; + + return result.sort((a, b) => { + let aStr = key ? String(a[key]).split(".")[0] : String(a); + let bStr = key ? String(b[key]).split(".")[0] : String(b); + // 处理空格 + if (trim) { + aStr = aStr.trim(); + bStr = bStr.trim(); + } + + // 处理大小写 + if (!caseSensitive) { + aStr = aStr.toLowerCase(); + bStr = bStr.toLowerCase(); + } + + // 获取排序键值 + const aKey = this.getSortKey(aStr); + const bKey = this.getSortKey(bStr); + + // 比较类型优先级 + if (aKey[0] !== bKey[0]) { + // 纯数字(0) < 非纯数字(1) + return direction === 'asc' ? aKey[0] - bKey[0] : bKey[0] - aKey[0]; + } + + // 相同类型下的比较 + if (aKey[0] === 0) { + // 都是纯数字,按数字大小比较 + if (aKey[1] < bKey[1]) return direction === 'asc' ? -1 : 1; + if (aKey[1] > bKey[1]) return direction === 'asc' ? 1 : -1; + return 0; + } else { + // 都是非纯数字,按字符串比较 + if (aStr < bStr) return direction === 'asc' ? -1 : 1; + if (aStr > bStr) return direction === 'asc' ? 1 : -1; + return 0; + } + }); + } + + /** + * 自然排序 - 处理文件名中的数字序列 + * 例如: file1, file2, file10 + * @param {Array} arr - 要排序的数组 + * @param {Object} options - 排序选项 + * @returns {Array} 排序后的数组 + */ + static naturalSort(arr, options = {}) { + const { + direction = 'asc', + caseSensitive = false + } = options; + + return [...arr].sort((a, b) => { + const aStr = String(a); + const bStr = String(b); + + // 检查是否都是纯数字 + const aIsPureNumber = this.isPureNumber(aStr); + const bIsPureNumber = this.isPureNumber(bStr); + + // 如果一个纯数字,一个非纯数字 + if (aIsPureNumber && !bIsPureNumber) { + return direction === 'asc' ? -1 : 1; + } + if (!aIsPureNumber && bIsPureNumber) { + return direction === 'asc' ? 1 : -1; + } + + // 都是纯数字,按数字比较 + if (aIsPureNumber && bIsPureNumber) { + const aNum = BigInt(aStr); + const bNum = BigInt(bStr); + + if (aNum < bNum) return direction === 'asc' ? -1 : 1; + if (aNum > bNum) return direction === 'asc' ? 1 : -1; + return 0; + } + + // 都是非纯数字,使用自然排序算法 + return this.naturalCompare(aStr, bStr, direction, caseSensitive); + }); + } + + /** + * 自然比较算法 + * @private + */ + static naturalCompare(a, b, direction = 'asc', caseSensitive = false) { + let aStr = caseSensitive ? a : a.toLowerCase(); + let bStr = caseSensitive ? b : b.toLowerCase(); + + const regex = /(\d+|\D+)/g; + const aParts = aStr.match(regex) || []; + const bParts = bStr.match(regex) || []; + + const maxLength = Math.max(aParts.length, bParts.length); + + for (let i = 0; i < maxLength; i++) { + const aPart = aParts[i] || ''; + const bPart = bParts[i] || ''; + + const aIsNumber = /^\d+$/.test(aPart); + const bIsNumber = /^\d+$/.test(bPart); + + // 如果都是数字,按数字比较 + if (aIsNumber && bIsNumber) { + const aNum = BigInt(aPart); + const bNum = BigInt(bPart); + + if (aNum < bNum) return direction === 'asc' ? -1 : 1; + if (aNum > bNum) return direction === 'asc' ? 1 : -1; + continue; + } + + // 都是文本,按字符串比较 + if (aPart < bPart) return direction === 'asc' ? -1 : 1; + if (aPart > bPart) return direction === 'asc' ? 1 : -1; + } + + return 0; + } + + /** + * 分组排序 - 将纯数字和非纯数字分开显示 + * @param {Array} arr - 要排序的数组 + * @param {Object} options - 排序选项 + * @returns {Array} 排序后的数组 + */ + static groupSort(arr, options = {}) { + const { + direction = 'asc', + groupOrder = 'numbers-first' // 'numbers-first' 或 'names-first' + } = options; + + // 分组 + const numbers = []; + const names = []; + + arr.forEach(item => { + const str = String(item); + if (this.isPureNumber(str)) { + numbers.push(item); + } else { + names.push(item); + } + }); + + // 对各组排序 + const sortedNumbers = this.sortFileNames(numbers, { direction }); + const sortedNames = this.sortFileNames(names, { direction }); + + // 按指定顺序合并 + if (groupOrder === 'numbers-first') { + return [...sortedNumbers, ...sortedNames]; + } else { + return [...sortedNames, ...sortedNumbers]; + } + } + + /** + * 文件扩展名排序 - 先按扩展名排序,再按文件名排序 + * @param {Array} arr - 要排序的数组 + * @param {Object} options - 排序选项 + * @returns {Array} 排序后的数组 + */ + static sortByExtension(arr, options = {}) { + const { + direction = 'asc', + extensionsFirst = false // 扩展名优先还是文件名优先 + } = options; + + return [...arr].sort((a, b) => { + const aStr = String(a); + const bStr = String(b); + + // 分离文件名和扩展名 + const getFileParts = (str) => { + const lastDotIndex = str.lastIndexOf('.'); + if (lastDotIndex > 0) { + return { + name: str.substring(0, lastDotIndex), + ext: str.substring(lastDotIndex + 1) + }; + } + return { name: str, ext: '' }; + }; + + const aParts = getFileParts(aStr); + const bParts = getFileParts(bStr); + + let compareResult; + + if (extensionsFirst) { + // 先比较扩展名 + compareResult = this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1; + if (compareResult !== 0) return compareResult; + + // 扩展名相同,再比较文件名 + return this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1; + } else { + // 先比较文件名 + compareResult = this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1; + if (compareResult !== 0) return compareResult; + + // 文件名相同,再比较扩展名 + return this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1; + } + }); + } + + /** + * 测试和演示函数 + */ + static demonstrate() { + const testData = [ + '100', + '23', + '1', + '003', + 'file.txt', + '10', + '5', + 'alpha', + 'beta', + 'gamma', + '00100', + 'zebra', + 'apple', + 'banana', + '123', + 'file10.txt', + 'file2.txt', + 'File1.txt', + 'file20.txt', + 'image.jpg', + 'document.pdf', + 'data.xlsx' + ]; + + console.log('=== 文件名排序演示 ===\n'); + + console.log('原始数据:'); + console.log(testData); + + console.log('\n1. 基本排序 (纯数字 < 非纯数字):'); + const basicSorted = this.sortFileNames(testData); + console.log(basicSorted); + + console.log('\n2. 自然排序 (智能数字识别):'); + const naturalSorted = this.naturalSort(testData); + console.log(naturalSorted); + + console.log('\n3. 分组排序 (数字组和文件组):'); + const groupSorted = this.groupSort(testData); + console.log(groupSorted); + + console.log('\n4. 降序排序:'); + const descSorted = this.sortFileNames(testData, { direction: 'desc' }); + console.log(descSorted); + + console.log('\n5. 按扩展名排序:'); + const extSorted = this.sortByExtension(testData); + console.log(extSorted); + + console.log('\n6. 大小写敏感排序:'); + const caseSensitiveSorted = this.sortFileNames(testData, { caseSensitive: true }); + console.log(caseSensitiveSorted); + + // 验证排序规则 + console.log('\n=== 排序规则验证 ==='); + const validationData = ['100', '23', 'file.txt', '1', 'alpha', '003', '10']; + console.log('验证数据:', validationData); + console.log('排序结果:', this.sortFileNames(validationData)); + console.log('规则验证:'); + console.log(' - 纯数字: 1, 3(003), 10, 23, 100 (按数字大小)'); + console.log(' - 非纯数字: alpha, file.txt (按字母顺序)'); + console.log(' - 非纯数字 > 纯数字'); + + return { + basic: basicSorted, + natural: naturalSorted, + group: groupSorted, + descending: descSorted, + byExtension: extSorted, + caseSensitive: caseSensitiveSorted + }; + } +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = FileNameSorter; +} else if (typeof window !== 'undefined') { + window.FileNameSorter = FileNameSorter; +} \ No newline at end of file diff --git a/src/views/none-dicom-show/index.vue b/src/views/none-dicom-show/index.vue index 4b6a63f8..be3040c7 100644 --- a/src/views/none-dicom-show/index.vue +++ b/src/views/none-dicom-show/index.vue @@ -3,8 +3,10 @@
- - + +
{{ $t('trials:none-dicom-show:fileList') }}
@@ -103,6 +105,7 @@ import zip from '@/assets/zip.jpg' import { changeURLStatic } from '@/utils/history.js' import Preview from './components/preview' import PreviewFile from '@/components/PreviewFile' +import FileNameSorter from "@/utils/customSort"; // import CheckForm from './components/form' export default { name: 'Notice', @@ -162,6 +165,11 @@ export default { this.getNoneDicomList() // 默认选择第一个文件 }, + computed: { + CriterionType() { + return this.OtherInfo.CriterionType ? this.OtherInfo.CriterionType : 0 + } + }, methods: { sortFile() { if (this.Asc) { @@ -169,15 +177,13 @@ export default { } else { this.Asc = true } - console.log(this.Asc, 'Asc') + console.log(this.Asc, 'this.Asc') this.studyList.forEach(study => { if (study.NoneDicomStudyFileList.length > 0) { - if (this.Asc) { - study.NoneDicomStudyFileList.sort((a, b) => b.FileName.localeCompare(a.FileName)) - } else { - study.NoneDicomStudyFileList.sort((a, b) => a.FileName.localeCompare(b.FileName)) - } - + study.NoneDicomStudyFileList = FileNameSorter.sortFileNames(study.NoneDicomStudyFileList, { + direction: this.Asc ? 'asc' : 'desc', + key: 'FileName' + }) } }) this.previewImage.imgList = this.studyList[this.currentStudyIndex].NoneDicomStudyFileList @@ -316,11 +322,13 @@ export default { return item.NoneDicomStudyFileList.length > 0 }) this.activeNames = this.studyList.map((item) => item.CodeView) - console.log(this.activeNames) if (studyIndex > -1) { var fileObj = this.studyList[studyIndex]['NoneDicomStudyFileList'] this.selected(fileObj[0], studyIndex, 0, true) } + if (this.CriterionType === 19 || this.CriterionType === 20) { + this.sortFile() + } }) .catch(() => { this.loading = false diff --git a/src/views/trials/trials-panel/reading/dicoms/components/IVUS/QuestionList.vue b/src/views/trials/trials-panel/reading/dicoms/components/IVUS/QuestionList.vue index 6302e20a..9cc80593 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/IVUS/QuestionList.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/IVUS/QuestionList.vue @@ -65,7 +65,11 @@ {{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }} - {{ `${$fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}` }} + {{`${scope.row[q.Id] instanceof Array ? scope.row[q.Id].map(item => $fd(q.DictionaryCode, + parseInt(item))).join(',') : $fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}`}} + + + {{ `${scope.row[q.Id] instanceof Array ? scope.row[q.Id].join(',') : scope.row[q.Id]}` }} {{ `${scope.row[q.Id]}` }} @@ -108,7 +112,7 @@