From 9448805f36221cdf5534d0026c45fad4fef7d6e7 Mon Sep 17 00:00:00 2001 From: wangxiaoshuang <825034831@qq.com> Date: Mon, 10 Aug 2026 17:07:01 +0800 Subject: [PATCH 01/37] =?UTF-8?q?=E9=9D=B6=E6=AE=B5=E6=A0=87=E6=B3=A8?= =?UTF-8?q?=E4=B8=8B=E8=BD=BDdicom=E6=96=87=E4=BB=B6=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/downloadDicomAndNonedicom/index.vue | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/downloadDicomAndNonedicom/index.vue b/src/components/downloadDicomAndNonedicom/index.vue index 49bd1582..4ff5820c 100644 --- a/src/components/downloadDicomAndNonedicom/index.vue +++ b/src/components/downloadDicomAndNonedicom/index.vue @@ -336,6 +336,14 @@ export default { if (data.StudyList && data.StudyList.length > 0) { let StudyList = data.StudyList StudyList.forEach((study) => { + let arr = [] + study.SeriesList.forEach(item => { + if (!arr.includes(item.Modality)) { + arr.push(item.Modality) + } + }) + let str = arr.join('_') + let time = study.StudyTime.split(' ')[0] if (study.StudyDIRPath) { let obj = { name: `${data.SubjectCode}/${data.TaskBlindName @@ -347,7 +355,7 @@ export default { obj = { name: `${data.SubjectCode}/${data.VisitName }/${this.$fd('IsDicom', true)}/${study.StudyCode - }/DICOMDIR`, + }_${time}_${str}/DICOMDIR`, url: this.OSSclientConfig.basePath + study.StudyDIRPath, } } else if (this.IsReadingTaskViewInOrder === 0) { @@ -380,7 +388,7 @@ export default { obj = { name: `${data.SubjectCode}/${data.VisitName }/${this.$fd('IsDicom', true)}/${study.StudyCode - }/IMAGE/${fileName}`, + }_${time}_${str}/IMAGE/${fileName}`, url: this.OSSclientConfig.basePath + instance.Path, IsEncapsulated: instance.IsEncapsulated } From 0bbb93d6632d076970bf1479cef7f91d2d71ac5b Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Wed, 12 Aug 2026 10:39:36 +0800 Subject: [PATCH 02/37] =?UTF-8?q?=E4=B8=AD=E5=BF=83=E8=B0=83=E7=A0=94?= =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/research.js | 28 + src/views/research/components/LogList.vue | 111 +++ src/views/research/form.vue | 82 +- .../site-research/components/Equipments.vue | 298 +++++++ .../site-research/components/Questions.vue | 389 +++++++++ .../site-research/components/ResearchList.vue | 707 ++++++++++++++++ .../site-research/components/users.vue | 3 +- .../attachments/site-research/index.vue | 770 +++--------------- 8 files changed, 1737 insertions(+), 651 deletions(-) create mode 100644 src/views/research/components/LogList.vue create mode 100644 src/views/trials/trials-panel/attachments/site-research/components/Equipments.vue create mode 100644 src/views/trials/trials-panel/attachments/site-research/components/Questions.vue create mode 100644 src/views/trials/trials-panel/attachments/site-research/components/ResearchList.vue diff --git a/src/api/research.js b/src/api/research.js index 66f1b54c..3efefb7e 100644 --- a/src/api/research.js +++ b/src/api/research.js @@ -129,3 +129,31 @@ export function getUserTypeList(userTypeEnum) { method: 'get' }) } + +export function getSiteSurveyLogList(param) { + return request({ + url: `/TrialSiteSurvey/getSiteSurveyLogList`, + method: 'post', + data: param + }) +} +export function getTrialIsSPMJoin(trialId) { + return request({ + url: `/TrialSiteSurvey/getTrialIsSPMJoin?trialId=${trialId}`, + method: 'get' + }) +} +export function getSiteSurveyEquipmentList(param) { + return request({ + url: `/TrialSiteSurvey/getSiteSurveyEquipmentList`, + method: 'post', + data: param + }) +} +export function getSiteSurveyInfoList(param) { + return request({ + url: `/TrialSiteSurvey/getSiteSurveyInfoList`, + method: 'post', + data: param + }) +} diff --git a/src/views/research/components/LogList.vue b/src/views/research/components/LogList.vue new file mode 100644 index 00000000..9abd5d7f --- /dev/null +++ b/src/views/research/components/LogList.vue @@ -0,0 +1,111 @@ + + + diff --git a/src/views/research/form.vue b/src/views/research/form.vue index c0393445..227bfa95 100644 --- a/src/views/research/form.vue +++ b/src/views/research/form.vue @@ -35,6 +35,10 @@ {{ $t('trials:researchForm:button:historicalRecord') }} + + + {{ $t('trials:researchForm:button:log') }} + {{ $t('trials:researchForm:button:loginOut') }} @@ -133,11 +137,32 @@ -
+
+ + +
+
+ {{ $t('trials:researchForm:button:log') }} +
+
+ + +
+
+
+
+ +
+
+
@@ -399,5 +433,45 @@ export default { } } + .history-dialog-content, + .log-dialog-content { + height: 100%; + margin: 0; + } + + .log-dialog-content { + overflow: hidden; + } + +} + + diff --git a/src/views/trials/trials-panel/attachments/site-research/components/Equipments.vue b/src/views/trials/trials-panel/attachments/site-research/components/Equipments.vue new file mode 100644 index 00000000..58df29af --- /dev/null +++ b/src/views/trials/trials-panel/attachments/site-research/components/Equipments.vue @@ -0,0 +1,298 @@ + + diff --git a/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue b/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue new file mode 100644 index 00000000..5d05ecbc --- /dev/null +++ b/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue @@ -0,0 +1,389 @@ + + diff --git a/src/views/trials/trials-panel/attachments/site-research/components/ResearchList.vue b/src/views/trials/trials-panel/attachments/site-research/components/ResearchList.vue new file mode 100644 index 00000000..3eeb0679 --- /dev/null +++ b/src/views/trials/trials-panel/attachments/site-research/components/ResearchList.vue @@ -0,0 +1,707 @@ + + + diff --git a/src/views/trials/trials-panel/attachments/site-research/components/users.vue b/src/views/trials/trials-panel/attachments/site-research/components/users.vue index c992470c..4a5f130c 100644 --- a/src/views/trials/trials-panel/attachments/site-research/components/users.vue +++ b/src/views/trials/trials-panel/attachments/site-research/components/users.vue @@ -119,7 +119,7 @@ - - - - - - - -
- +
+ + + + + + + + + + +
+
- - - - - - - - - - - - - - +
From 967688e94eb6daa95ecfc66e65c6412c502f8911 Mon Sep 17 00:00:00 2001 From: wangxiaoshuang <825034831@qq.com> Date: Wed, 12 Aug 2026 14:28:19 +0800 Subject: [PATCH 03/37] =?UTF-8?q?=E8=B0=83=E7=A0=94=E8=A1=A8=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=97=A5=E5=BF=97=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/index.js | 6 + src/utils/whiteList.js | 2 +- src/views/research/components/LogList.vue | 89 ++++------ src/views/research/form.vue | 114 ++++++++---- .../attachments/site-research/index.vue | 167 ++++++++---------- 5 files changed, 197 insertions(+), 181 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index f9649f17..93dbf25f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -228,6 +228,12 @@ export const constantRoutes = [ component: () => import('@/views/research/form'), hidden: true }, + { + path: '/researchLog', + name: 'researchLog', + component: () => import('@/views/research/form'), + hidden: true + }, { path: '/researchLogin_m', name: 'researchLogin_m', diff --git a/src/utils/whiteList.js b/src/utils/whiteList.js index 7ade7116..741ae39e 100644 --- a/src/utils/whiteList.js +++ b/src/utils/whiteList.js @@ -1,2 +1,2 @@ -const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/link_expired', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms', '/ecrfList'] +const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/link_expired', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms', '/ecrfList', '/researchLog'] export default WHITELIST diff --git a/src/views/research/components/LogList.vue b/src/views/research/components/LogList.vue index 9abd5d7f..b614c4f3 100644 --- a/src/views/research/components/LogList.vue +++ b/src/views/research/components/LogList.vue @@ -1,65 +1,29 @@ + diff --git a/src/views/trials/trials-panel/setting/reading-unit/index.vue b/src/views/trials/trials-panel/setting/reading-unit/index.vue index 53694695..ed14c8d2 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/index.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/index.vue @@ -240,7 +240,6 @@ export default { if (ReadingTool === 3) { this.readingSegmentTools = getCustomizeStandardsSegmentDicomTools(readingSegmentTools) } - console.log(this.readingSegmentTools, 'this.readingSegmentTools') }, setIsClinicalReading(isClinicalReading) { this.isClinicalReading = isClinicalReading; @@ -300,11 +299,15 @@ export default { this.$refs["arbitrationRules" + this.TrialReadingCriterionId] .length ) { - var arbitrationRules = await this.$refs[ + const arbitrationRulesRef = this.$refs[ "arbitrationRules" + this.TrialReadingCriterionId - ][0].saveAllSync(); + ][0]; + var judgeRuleSaved = await arbitrationRulesRef.saveJugeRule(false); + var arbitrationRules = judgeRuleSaved + ? await arbitrationRulesRef.saveAllSync() + : false; isCheckList.push({ - isCheck: arbitrationRules, + isCheck: judgeRuleSaved && arbitrationRules, msg: this.$t("trials:readingUnit:adRules"), // '仲裁规则' }); } From de5c46c9161905a2546023d002b52f07ae2d3479 Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Mon, 17 Aug 2026 16:21:19 +0800 Subject: [PATCH 18/37] =?UTF-8?q?=E8=AE=A1=E5=88=92=E5=A4=96=E8=AE=BF?= =?UTF-8?q?=E8=A7=86=E8=A3=81=E5=88=A4=E8=A7=84=E5=88=99=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reading-unit/components/ArbitrationRulesByVisit.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue index 325060dd..c398ccf7 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue @@ -396,6 +396,14 @@ export default { this.visitPlanOptions = res.Result || [] if (!this.activeVisitTab && this.visitPlanOptions.length > 0) { this.activeVisitTab = this.visitPlanOptions[0].Id + this.visitPlanOptions.push( + { + "Id": "00000000-0000-0000-0000-000000000000", + "VisitNum": -1, + "VisitName": "Out of Plan", + "IsBaseLine": false + } + ) } } } catch (e) { From e2b105cf39f90c781ba6ce180c9c821adb52475f Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Mon, 17 Aug 2026 17:18:54 +0800 Subject: [PATCH 19/37] =?UTF-8?q?=E9=98=85=E7=89=87=E8=A7=84=E5=88=99?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reading-unit/components/ArbitrationRules.vue | 16 +++++++++++++++- .../components/ArbitrationRulesByVisit.vue | 10 ++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue index 91f8fc5d..ca107947 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue @@ -396,6 +396,10 @@ export default { ], }, judgeRuleEnum: -1, + savedJudgyInfo: { + JudgeModeEnum: null, + JudgeRuleEnum: null, + }, } }, watch: { @@ -408,6 +412,15 @@ export default { await this.initData() }, methods: { + resetJudgeTypeRelatedFields(question = {}) { + this.$set(question, 'AnswerGroup2List', []) + this.$set(question, 'AnswerGroupList', []) + this.$set(question, 'grouping', []) + this.$set(question, 'groupingA', []) + this.$set(question, 'groupingB', []) + this.$set(question, 'JudgeDifferenceValue', 0) + this.$set(question, 'JudgeDifferenceType', 0) + }, async initData() { await this.getTrialJudgyInfo() if (this.judgeRuleEnum !== 1) { @@ -427,9 +440,10 @@ export default { } }, JudgeTypeChange(value, index) { + this.resetJudgeTypeRelatedFields(this.QuestionList[index]) this.$nextTick(() => { if (value === 4 || value === 5) { - if (this.$refs['JudgeDifferenceValue' + value + index][0]) { + if (this.$refs['JudgeDifferenceValue' + value + index] && this.$refs['JudgeDifferenceValue' + value + index][0]) { this.$refs['JudgeDifferenceValue' + value + index][0].resetFields() // this.QuestionList[index].JudgeDifferenceValue = 0; } diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue index c398ccf7..a493811d 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRulesByVisit.vue @@ -366,6 +366,15 @@ export default { this.activeVisitTab = '' await this.getVisitPlanOptions() }, + resetVisitJudgeTypeRelatedFields(question = {}) { + this.$set(question, 'AnswerGroup2List', []) + this.$set(question, 'AnswerGroupList', []) + this.$set(question, 'grouping', []) + this.$set(question, 'groupingA', []) + this.$set(question, 'groupingB', []) + this.$set(question, 'JudgeDifferenceValue', null) + this.$set(question, 'JudgeDifferenceType', 0) + }, normalizeQuestionList(questionList = []) { return questionList.map((item) => ({ ...item, @@ -448,6 +457,7 @@ export default { } }, visitJudgeTypeChange(value, index, visitKey) { + this.resetVisitJudgeTypeRelatedFields(this.questionListMap[visitKey][index]) this.$nextTick(() => { if (value === 4 || value === 5) { const refName = `JudgeDifferenceValue${value}_${visitKey}_${index}` From a6c3ae8e0588a50820269c1eeef820d979edbd16 Mon Sep 17 00:00:00 2001 From: wangxiaoshuang <825034831@qq.com> Date: Tue, 18 Aug 2026 09:32:10 +0800 Subject: [PATCH 20/37] =?UTF-8?q?IVUS&OCT=E9=98=85=E7=89=87=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=82=B9=EF=BC=9A=E9=9D=B6=E6=AE=B5=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E5=92=8C=E9=98=85=E7=89=87=E9=A1=B5=E9=9D=A2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=92=8C=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 10 + package.json | 1 + .../uploadDicomAndNonedicom/index.vue | 8 +- .../uploadDicomAndNonedicom/nonedicomFile.vue | 45 +++- .../site-research/components/Questions.vue | 4 +- .../reading-task/components/TargetSection.vue | 196 +++++++++++------- vue.config.js | 3 +- 7 files changed, 184 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39fcd597..205955d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "sortablejs": "^1.15.5", "streamsaver": "^2.0.6", "svgo": "^1.2.2", + "unzipit": "^2.0.3", "v-viewer": "^1.7.4", "vcrontab": "^0.3.5", "vue": "2.7.16", @@ -21835,6 +21836,15 @@ "node": ">=0.10.0" } }, + "node_modules/unzipit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unzipit/-/unzipit-2.0.3.tgz", + "integrity": "sha512-e6+ftgSQRj9Hwf2mIWFwYIGqBoKV7AziG/d7pep2Uv3NCzHbhLO5d9dGRwpahVlnpQ7aQC+5kWk72dnWocdYyA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/unzipper": { "version": "0.10.14", "resolved": "https://registry.npmmirror.com/unzipper/-/unzipper-0.10.14.tgz", diff --git a/package.json b/package.json index e10c42e7..3be3af68 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "sortablejs": "^1.15.5", "streamsaver": "^2.0.6", "svgo": "^1.2.2", + "unzipit": "^2.0.3", "v-viewer": "^1.7.4", "vcrontab": "^0.3.5", "vue": "2.7.16", diff --git a/src/components/uploadDicomAndNonedicom/index.vue b/src/components/uploadDicomAndNonedicom/index.vue index c5f19dbd..98510f22 100644 --- a/src/components/uploadDicomAndNonedicom/index.vue +++ b/src/components/uploadDicomAndNonedicom/index.vue @@ -3,7 +3,7 @@ :append-to-body="true" class="uploadDicomAndNonedicom"> {{ title }} - + { return { SubjectId: null, @@ -332,6 +333,34 @@ export default { store.dispatch('trials/setUnLock', false) }, methods: { + async readZipFileListRaw(zipFile) { + try { + // 1. 使用 unzipRaw 读取原始条目列表 + const { entries } = await unzipRaw(zipFile); + + // 2. entries 是一个数组,需要手动处理 + const fileList = entries.map(entry => { + // 3. 使用 TextDecoder 指定编码来解码文件名 + // 例如,对于简体中文 ZIP 包,可以使用 'gbk' + const decoder = new TextDecoder('gbk'); // 或者 'big5' + const name = decoder.decode(entry.nameBytes); + + return { + path: name, + name: name.split('/').pop(), + isDirectory: entry.isDirectory, + size: entry.size, + lastModified: entry.lastModDate + }; + }); + + console.log('解码后的文件列表:', fileList); + return fileList; + } catch (error) { + console.error('读取 ZIP 失败:', error); + throw error; + } + }, async getList() { try { this.searchData.SubjectId = this.SubjectId @@ -370,11 +399,15 @@ export default { // 扫描待上传文件 beginScanFiles(e) { var files = [...e.target.files] - var sameFiles = [] + var sameFiles = [], zipFiles = [], f = false files.forEach((file) => { var extendName = file.name .substring(file.name.lastIndexOf('.')) .toLocaleLowerCase() + if (extendName === '.zip' && this.IsImageSegment) { + if (file.name.indexOf('筛选期') > -1 || file.name.indexOf('研究结束') > -1) f = true + zipFiles.push(file) + } if ( this.faccept.indexOf(extendName) !== -1 && this.fileList.findIndex((v) => v.name === file.name) > -1 @@ -382,6 +415,16 @@ export default { sameFiles.push(file.name) } }) + if (zipFiles.length > 0) { + zipFiles.forEach(async file => { + let list = await this.readZipFileListRaw(file) + if (!f) f = list.some(i => i.path.indexOf('筛选期') > -1 || i.path.indexOf('研究结束') > -1) + list = null + }) + } + if (f) return this.$confirm(this.$t("trials:uploadNonDicoms:confirm:zipNameNonCompliant"), '', { + type: "warning" + }) var scope = this if (sameFiles.length > 0) { const h = this.$createElement diff --git a/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue b/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue index 35db4ecd..60d4ffc7 100644 --- a/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue +++ b/src/views/trials/trials-panel/attachments/site-research/components/Questions.vue @@ -166,7 +166,7 @@