Merge branch 'uat' into uat_us

uat_us
DESKTOP-6C3NK6N\WXS 2024-07-19 13:24:35 +08:00
commit f0e6c5b9de
24 changed files with 623 additions and 294 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -89,6 +89,7 @@ import {
batchAddOrUpdateFrontInternationalization,
getFrontInternationalizationList,
} from "@/api/dictionary/dictionary";
import { getTrialExtralConfig } from "@/api/trials";
import Vue from "vue";
import i18n from "./lang";
export default {
@ -105,6 +106,28 @@ export default {
mounted() {
this.show = process.env.VUE_APP_OSS_PATH === "/test/dist";
},
watch: {
"$route.query": {
async handler() {
if (
this.$route.query.trialId &&
this.$route.query.trialId !== this.$store.state.trials.config.trialId
) {
let res = await getTrialExtralConfig({
TrialId: this.$route.query.trialId,
});
if (res.IsSuccess) {
this.$store.dispatch("trials/setConfig", {
trialId: this.$route.query.trialId,
...res.Result,
});
}
}
},
immediate: true,
deep: true,
},
},
methods: {
changeValue(target, attr, e) {
this.$set(target, attr, e);

View File

@ -171,3 +171,19 @@ export function getCustomTag(param) {
data: param
})
}
export function clearSkipReadingCache(param) {
return request({
url: `/ReadingImageTask/clearSkipReadingCache`,
method: 'post',
data: param
})
}
export function setSkipReadingCache(param) {
return request({
url: `/ReadingImageTask/setSkipReadingCache`,
method: 'post',
data: param
})
}

View File

@ -3675,3 +3675,11 @@ export function getTrialSiteSelectList(params) {
params
})
}
// 获取项目配置
export function getTrialExtralConfig(params) {
return request({
url: `/TrialConfig/getTrialExtralConfig`,
method: 'get',
params
})
}

View File

@ -44,7 +44,6 @@ Viewer.setDefaults({
'rotatable': true,
'scalable': true,
'transition': true,
'fullscreen': true,
'keyboard': true,
'url': 'data-source'
}
@ -368,7 +367,9 @@ async function VueInit() {
}
_vm.$store.dispatch('user/logout').then(res => {
// window.location.href = `/login`
if(_vm.$msgbox){
_vm.$msgbox.close();
}
isOpen = false
isLock = null
zzSessionStorage.removeItem('isLock')

View File

@ -12,7 +12,7 @@ NProgress.configure({ showSpinner: false })
const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
router.beforeEach(async(to, from, next) => {
router.beforeEach(async (to, from, next) => {
NProgress.start()
// 设置页面标题
// document.title = getPageTitle(to.meta.title)
@ -56,7 +56,7 @@ router.beforeEach(async(to, from, next) => {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录whiteList中直接进入
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading'){
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading') {
OSSclient()
}
next()

View File

@ -493,11 +493,10 @@ const actions = {
})
},
removeCustomizeMeasuredData({ state }, obj) {
return new Promise(async resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData
console.log('removeCustomizeMeasuredData',obj, state.visitTaskList[index].MeasureData)
console.log('removeCustomizeMeasuredData', obj, state.visitTaskList[index].MeasureData)
// var uuid = obj.measureData.data.uuid
// var idx = measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
// console.log(obj, measureData)
@ -682,7 +681,7 @@ const actions = {
} else {
// state.visitTaskList[index].MeasureData.push(obj.MeasureData.data)
state.visitTaskList[index].MeasureData.push({
MeasureData: obj.measureData ,
MeasureData: obj.measureData,
SeriesId: obj.measureData.seriesId,
StudyId: obj.measureData.studyId,
InstanceId: obj.measureData.instanceId,
@ -898,7 +897,7 @@ const actions = {
},
setImageloadedInfo({ state }, obj) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
let prefetchInstanceCount = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount
const prefetchInstanceCount = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount
state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount = prefetchInstanceCount + 100
state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].imageloadedArr.push(obj.imageId)
},

View File

@ -8,6 +8,7 @@ const getDefaultState = () => {
visitPointQuery: null,
studyListQuery: null,
unlock: false,
config: {},
}
}
@ -20,6 +21,9 @@ const mutations = {
SET_UNLOCK: (state, unlock) => {
state.unlock = unlock
},
SET_CONFIG: (state, config) => {
state.config = config
},
SET_ACTIVENAME: (state, activeName) => {
state.trialDetailActiveName = activeName
},
@ -44,6 +48,9 @@ const actions = {
setUnLock({ commit }, unlock) {
commit('SET_UNLOCK', unlock)
},
setConfig({ commit }, config) {
commit('SET_CONFIG', config)
},
setActiveName({ commit }, activeName) {
commit('SET_ACTIVENAME', activeName)
},

View File

@ -2,44 +2,55 @@ import JSZip from "jszip";
import axios from "axios";
import { saveAs } from "file-saver";
import Vue from 'vue';
import store from "@/store";
import {
requestPackageAndAnonymizImage,
} from "@/api/load.js";
let flag = {};
export const downloadImage = async (id, id2) => {
if (flag[id2]) return
flag[id2] = true
export const resetFlag = () => {
flag = {};
store.dispatch("trials/setUnLock", false);
}
export const downloadImage = async (id, id2, IsDicom = true) => {
if (flag[`${id2}_${IsDicom}`]) return Vue.prototype.$message.warning(Vue.prototype.$t('trials:upload:tip:uploading'));
flag[`${id2}_${IsDicom}`] = true
try {
let params = {
TrialId: id,
SubjectVisitId: id2
SubjectVisitId: id2,
IsDicom: IsDicom
}
store.dispatch("trials/setUnLock", true);
let res = await requestPackageAndAnonymizImage(params);
flag[id2] = false;
if (res.IsSuccess) {
if (!res.Result) {
flag[`${id2}_${IsDicom}`] = false;
Vue.prototype.$message.warning(Vue.prototype.$t("trials:upload:message:not"))
return 1;
}
let a = document.createElement("a");
Vue.prototype.$message.success(Vue.prototype.$t("trials:upload:message:startUpload"));
let href = Vue.prototype.OSSclientConfig.basePath + res.Result;
let fileName =
res.Result.split("/")[res.Result.split("/").length - 1];
a.download = fileName;
a.href = href;
a.click();
URL.revokeObjectURL(href);
let timer = setTimeout(() => {
a = null;
href = null;
timer = null;
}, 500)
download(href, res.OtherInfo.FileName, { id2, IsDicom })
return 2;
// let a = document.createElement("a");
// // let fileName =
// // res.Result.split("/")[res.Result.split("/").length - 1];
// a.download = res.OtherInfo.FileName;
// a.href = href;
// a.click();
// URL.revokeObjectURL(href);
// let timer = setTimeout(() => {
// a = null;
// href = null;
// timer = null;
// }, 500)
// return 2;
} else {
flag[`${id2}_${IsDicom}`] = false;
return false;
}
} catch (err) {
flag[id2] = false;
flag[`${id2}_${IsDicom}`] = false;
console.log(err);
}
};
@ -101,11 +112,11 @@ const setfolder = async (item) => {
})
.then((res) => {
saveAs(res, zipName + ".zip"); // 使用FileSaver.saveAs保存文件文件名可自定义
flag[id2] = false;
flag[`${id2}_${IsDicom}`] = false;
zipObj = null;
});
})
.catch((reason) => { flag[id2] = false; });
.catch((reason) => { flag[`${id2}_${IsDicom}`] = false; });
};
const handleBatchDown = async (item, zip) => {
return new Promise((resolve) => {
@ -142,3 +153,47 @@ export const fileDownload = (content, filename) => {
eleLink.click();
document.body.removeChild(eleLink);
};
let download = async (downloadUrl, downloadFileName, res) => {
const blob = await getBlob(downloadUrl);
flag[`${res.id2}_${res.IsDicom}`] = false;
store.dispatch("trials/setUnLock", false);
saveAsB(blob, downloadFileName);
}
let getBlob = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error(`Request failed with status ${xhr.status}`));
}
};
xhr.onerror = () => {
reject(new Error('Request failed'));
};
xhr.send();
});
}
let saveAsB = (blob, filename) => {
const link = document.createElement('a');
const body = document.body;
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// hide the link
link.style.display = 'none';
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}

View File

@ -183,7 +183,7 @@
{{ $t("login:title:system_title") }}
</p>
<p style="margin-bottom: 20px" v-else>{{ $t("login:title:system") }}</p>
<p style="margin-bottom: 20px">V1.5.2.001</p>
<p style="margin-bottom: 20px">V1.5.3.001</p>
<p style="margin-bottom: 20px" v-if="language === 'zh'">
Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
版权所有

View File

@ -121,7 +121,7 @@ export default {
// Dicom
getNoneDicomList() {
this.loading = true
getNoneDicomStudyList(this.subjectVisitId, this.studyId, true).then(res => {
getNoneDicomStudyList(this.subjectVisitId, this.studyId).then(res => {
this.studyList = res.Result
this.loading = false
const studyIndex = this.studyList.findIndex(item => {

View File

@ -62,7 +62,7 @@ export default {
// Dicom
getNoneDicomList() {
this.loading = true
getNoneDicomStudyList(this.subjectVisitId, '', true).then(res => {
getNoneDicomStudyList(this.subjectVisitId, '').then(res => {
this.noneDicomStudyList = res.Result
this.loading = false
const study = this.noneDicomStudyList.find((item, index) => {

View File

@ -203,6 +203,7 @@
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<viewer :images="images" :ref="file.url">
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
@ -225,23 +226,17 @@
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload>
<el-dialog
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<!-- <img width="100%" :src="imageUrl" alt="图片未找到"> -->
<el-image :src="imageUrl" width="100%" crossorigin="anonymous">
<div slot="placeholder" class="image-slot">
{{ $t('trials:adReview:title:loading') }}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</el-form-item>
<el-form-item v-if="adInfo.ReadingTaskState < 2">
<div style="text-align:center;">
<el-button type="primary" @click="skipTask">
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<!-- 保存 -->
<el-button type="primary" @click="handleSave">{{ $t('common:button:save') }}</el-button>
<!-- 提交 -->
@ -317,12 +312,14 @@ import { getJudgeReadingInfo,
// uploadJudgeTaskImage,
saveJudgeVisitTaskResult, submitJudgeVisitTaskResult, getReadingPastResultList } from '@/api/trials'
import { getAutoCutNextTask } from '@/api/user'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code'
import { getToken } from '@/utils/auth'
import SignForm from '@/views/trials/components/newSignForm'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import store from '@/store'
import { changeURLStatic } from '@/utils/history.js'
import Viewer from 'v-viewer'
export default {
name: 'AdReview',
components: { SignForm },
@ -390,7 +387,8 @@ export default {
judgeResultArmEnum: '',
criterionType: null,
openWindow: null,
isFixed:false
isFixed: false,
images: []
}
},
// watch: {
@ -407,6 +405,7 @@ export default {
// }
// },
mounted() {
this.initializeViewer()
this.criterionType = parseInt(this.$route.query.criterionType)
this.getAdInfo()
if (this.isReadingShowPreviousResults) {
@ -708,14 +707,42 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
this.images = this.fileList.map(f => this.OSSclientConfig.basePath + f.url)
// this.imageUrl = this.OSSclientConfig.basePath + file.url
this.$refs[file.url].$viewer.show()
},
//
handleRemove(file, fileList) {
var idx = this.fileList.findIndex(i => i.url === file.url)
if (idx === -1) return
this.fileList.splice(idx, 1)
},
async skipTask() {
try {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
},
initializeViewer() {
Viewer.setDefaults({
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
})
}
}
}

View File

@ -12,6 +12,15 @@
style="margin-right:5px;"
@change="handleShowDetail"
/>
<el-button
v-if="readingTaskState<2"
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button
v-if="readingTaskState<2"
type="primary"
@ -172,8 +181,7 @@
@change="evaluateReasonChange"
/>
<!-- 系统评估结果为xxx,与当前调整的结果不一致请填写调整原因 -->
<p v-if="currentEvaluateResult !== tumorEvaluate" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;" v-html="getWarningText()">
</p>
<p v-if="currentEvaluateResult !== tumorEvaluate" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;" v-html="getWarningText()" />
<p v-else-if="currentExistDisease !== isExistDisease" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:title:sysEvaluationRes') }}<span style="color:red">{{ $fd('ExistDisease',isExistDisease) }}</span>{{ $t('trials:readingReport:message:msg1') }}
</p>
</template>
@ -262,6 +270,7 @@
</template>
<script>
import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './DicomEvent'
import const_ from '@/const/sign-code'
@ -816,14 +825,36 @@ export default {
var sysRes = ''
var curRes = ''
if (this.CriterionType === 2) {
sysRes = this.$fd('ImagingOverallAssessment_Lugano',this.tumorEvaluate)
curRes = this.$fd('ImagingOverallAssessment_Lugano',this.currentEvaluateResult)
sysRes = this.$fd('ImagingOverallAssessment_Lugano', this.tumorEvaluate)
curRes = this.$fd('ImagingOverallAssessment_Lugano', this.currentEvaluateResult)
} else {
sysRes = this.$fd('OverallAssessment',this.tumorEvaluate)
curRes = this.$fd('OverallAssessment',this.currentEvaluateResult)
sysRes = this.$fd('OverallAssessment', this.tumorEvaluate)
curRes = this.$fd('OverallAssessment', this.currentEvaluateResult)
}
let msg = this.$t('trials:readingReport:message:msg9').replace('xxx','<font color="red">' + sysRes + '</font>').replace('yyy','<font color="red">' + curRes + '</font>')
const msg = this.$t('trials:readingReport:message:msg9').replace('xxx', '<font color="red">' + sysRes + '</font>').replace('yyy', '<font color="red">' + curRes + '</font>')
return msg
},
async skipTask() {
try {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}
}
}

View File

@ -11,6 +11,15 @@
style="margin-right:5px"
@change="handleShowDetail"
/>
<el-button
v-if="readingTaskState<2"
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="getReportInfo">{{$t('trials:readingReport:button:refresh')}}</el-button>
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleSave(true)">{{$t('common:button:save')}}</el-button>
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{$t('common:button:submit')}}</el-button>
@ -260,6 +269,7 @@
</template>
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code'
@ -828,6 +838,28 @@ export default {
reject()
})
})
},
async skipTask() {
try {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}
}
}

View File

@ -25,7 +25,14 @@
</div>
<div v-if=" readingTaskState < 2" style="text-align:right;margin:5px 0;">
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button size="small" type="primary" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
@ -142,6 +149,7 @@
<script>
import { getGlobalReadingInfo, getReadingPastResultList, submitGlobalReadingInfo, saveGlobalReadingInfo } from '@/api/trials'
import { getAutoCutNextTask } from '@/api/user'
import { setSkipReadingCache } from '@/api/reading'
import { getToken } from '@/utils/auth'
import const_ from '@/const/sign-code'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
@ -377,6 +385,28 @@ export default {
handleSave() {
this.$refs['globalTbl'].handleSave(true)
},
async skipTask() {
try {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
},
async handleConfirm() {
// 访
var idx = this.taskList.findIndex(i => !i.AgreeOrNotAnswer)

View File

@ -29,11 +29,22 @@
{{ $t('trials:medicalFeedback:message:msg2') }}
<ol>
<li v-for="file in record.FileList" :key="file.ImagePath" style="list-style: none;">
<el-button
type="text"
size="mini"
@click="previewImage(file.ImagePath)"
>{{ file.FileName }}</el-button>
<viewer
v-if="file.ImagePath"
:ref="file.ImagePath"
style="margin:0 10px;"
:images="[`${OSSclientConfig.basePath}${file.ImagePath}`]"
>
<el-button type="text" @click="previewImage(file.ImagePath)">
{{ file.FileName }}
</el-button>
<img
v-show="false"
crossorigin="anonymous"
:src="`${OSSclientConfig.basePath}${file.ImagePath}`"
alt="Image"
>
</viewer>
</li>
</ol>
</div>
@ -97,22 +108,6 @@
</div>
</div>
<el-dialog
v-if="previewDialog"
append-to-body
:close-on-click-modal="false"
:visible.sync="previewDialog"
width="600px"
>
<!-- <img width="100%" :src="imagePath" alt="图片未找到"> -->
<el-image :src="imagePath" crossorigin="anonymous" width="100%">
<div slot="placeholder" class="image-slot">
<!-- 加载中 -->
{{ $t('trials:medicalFeedback:message:loading') }}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
<el-dialog
v-if="irFeedbackForm.visible"
@ -137,6 +132,7 @@ import { getMedicalReviewDialog } from '@/api/trials'
import FeedbackForm from './FeedbackForm'
import mimAvatar from '@/assets/MIM.png'
import irAvatar from '@/assets/IR.png'
import Viewer from 'v-viewer'
export default {
name: 'ChatForm',
components: { FeedbackForm },
@ -170,6 +166,7 @@ export default {
}
},
mounted() {
this.initializeViewer()
this.getMessageList()
},
methods: {
@ -204,6 +201,12 @@ export default {
previewImage(path) {
this.imagePath = `${this.OSSclientConfig.basePath}${path}`
this.previewDialog = true
this.$refs[path][0].$viewer.show()
},
initializeViewer() {
Viewer.setDefaults({
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
})
}
}

View File

@ -29,11 +29,22 @@
{{ $t('trials:medicalFeedback:message:msg2') }}
<ol>
<li v-for="file in record.FileList" :key="file.ImagePath" style="list-style: none;">
<el-button
type="text"
size="mini"
@click="previewImage(file.ImagePath)"
>{{ file.FileName }}</el-button>
<viewer
v-if="file.ImagePath"
:ref="file.ImagePath"
style="margin:0 10px;"
:images="[`${OSSclientConfig.basePath}${file.ImagePath}`]"
>
<el-button type="text" @click="previewImage(file.ImagePath)">
{{ file.FileName }}
</el-button>
<img
v-show="false"
crossorigin="anonymous"
:src="`${OSSclientConfig.basePath}${file.ImagePath}`"
alt="Image"
>
</viewer>
</li>
</ol>
</div>
@ -125,19 +136,6 @@
</div>
</div>
<el-dialog
append-to-body
:visible.sync="previewDialog"
width="600px"
>
<!-- <img width="100%" :src="imagePath" alt="图片未找到"> -->
<el-image :src="OSSclientConfig.basePath + imagePath" width="100%" crossorigin="anonymous">
<div slot="placeholder" class="image-slot">
{{ $t('trials:medicalFeedback:message:loading') }}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
<el-dialog
v-if="irFeedbackForm.visible"
:visible.sync="irFeedbackForm.visible"
@ -154,6 +152,7 @@
@close="irFeedbackForm.visible = false"
/>
</el-dialog>
</div>
</template>
<script>
@ -161,6 +160,7 @@ import { getMedicalReviewDialog, sendMedicalReviewDialog } from '@/api/trials'
import FeedbackForm from '@/views/trials/trials-panel/reading/medical-feedback/components/FeedbackForm'
import mimAvatar from '@/assets/MIM.png'
import irAvatar from '@/assets/IR.png'
import Viewer from 'v-viewer'
export default {
name: 'ChatForm',
components: {
@ -196,6 +196,7 @@ export default {
}
},
mounted() {
this.initializeViewer()
this.getMessageList()
},
methods: {
@ -242,12 +243,18 @@ export default {
previewImage(path) {
this.imagePath = `${path}`
this.previewDialog = true
this.$refs[path][0].$viewer.show()
},
handleIRReply() {
// ''
this.irFeedbackForm.title = this.$t('trials:medicalFeedback:title:feedback')
this.irFeedbackForm.visible = true
},
initializeViewer() {
Viewer.setDefaults({
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
})
}
}

View File

@ -92,6 +92,7 @@
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<viewer :images="images" :ref="file.url">
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
@ -114,24 +115,26 @@
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload>
<el-dialog
<!-- <el-dialog
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<!-- <img width="100%" :src="imageUrl" alt="图片未找到"> -->
<el-image :src="imageUrl" width="100%" crossorigin="anonymous">
<div slot="placeholder" class="image-slot">
{{ $t('trials:medicalFeedback:message:loading') }}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</el-dialog> -->
</el-form-item>
</el-form>
<!-- <viewer v-if="imgVisible" :images="[imageUrl]" ref="viewer">
<img :src="imageUrl" crossorigin="anonymous" alt="">
</viewer> -->
<el-dialog
v-if="chatVisible"
:visible.sync="chatVisible"
@ -170,6 +173,7 @@
import { saveMedicalReviewInfo } from '@/api/trials'
import ChatForm from './ChatForm'
import CloseQC from './CloseQC'
import Viewer from 'v-viewer'
export default {
name: 'AuditConclusions',
components: {
@ -220,10 +224,12 @@ export default {
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
isClosedDialog: false,
isSendMessage: false,
closeQuestionVisible: false
closeQuestionVisible: false,
images:[]
}
},
mounted() {
this.initializeViewer()
this.initForm()
},
methods: {
@ -379,14 +385,20 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
this.images = this.fileList.map(f => this.OSSclientConfig.basePath + f.url)
// this.imageUrl = this.OSSclientConfig.basePath + file.url
this.$refs[file.url].$viewer.show()
},
//
handleRemove(file, fileList) {
var idx = this.fileList.findIndex(i => i.url === file.url)
if (idx === -1) return
this.fileList.splice(idx, 1)
},
initializeViewer() {
Viewer.setDefaults({
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true}
})
}
}
}

View File

@ -26,6 +26,14 @@
>
{{ $t('trials:oncologyReview:button:clinicalData') }}
</el-button>
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<!-- 保存 -->
<el-button
v-if="oncologyInfo.ReadingTaskState < 2"
@ -253,6 +261,7 @@
</template>
<script>
import { getOncologyReadingInfo, getReadingPastResultList, setOncologyReadingInfo, submitOncologyReadingInfo } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code'
import { getToken } from '@/utils/auth'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
@ -554,6 +563,28 @@ export default {
path: `/clinicalData?subjectId=${this.oncologyInfo.SubjectId}&trialId=${this.trialId}&visitTaskId=${this.oncologyInfo.OncologyTaskId}&TokenKey=${token}`
})
window.open(routeData.href, '_blank')
},
async skipTask() {
try {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}
}
}

View File

@ -78,8 +78,7 @@
? 'warning'
: 'primary'
"
>{{ $fd("YesOrNo", scope.row.IsUrgent) }}</el-tag
>
>{{ $fd("YesOrNo", scope.row.IsUrgent) }}</el-tag>
</template>
</el-table-column>
<!-- 受试者编号 -->
@ -117,8 +116,7 @@
? '#E6A23C'
: '#409EFF',
}"
>{{ scope.row.UrgentCount }}</span
>
>{{ scope.row.UrgentCount }}</span>
</template>
</el-table-column>
<!-- 建议完成时间 -->
@ -157,12 +155,12 @@
/>
<!-- 上传 -->
<el-button
v-hasPermi="['role:ir']"
v-if="
item.CriterionType === 0 &&
item.ImageUploadEnum > 0 &&
item.IsReadingTaskViewInOrder > 0
"
v-hasPermi="['role:ir']"
circle
icon="el-icon-upload2"
:title="$t('trials:pendingReadingTasks:button:upload')"
@ -170,12 +168,12 @@
/>
<!-- 下载 -->
<el-button
v-hasPermi="['role:ir']"
v-if="
item.CriterionType === 0 &&
item.ImageDownloadEnum === 1 &&
item.IsReadingTaskViewInOrder > 0
"
v-hasPermi="['role:ir']"
circle
icon="el-icon-download"
:title="$t('trials:pendingReadingTasks:button:download')"
@ -264,8 +262,8 @@
<upload-image
v-if="uploadImageVisible"
:visible.sync="uploadImageVisible"
:SubjectId="uploadSubjectId"
:Criterion="uploadTrialCriterion"
:subject-id="uploadSubjectId"
:criterion="uploadTrialCriterion"
:status="uploadStatus"
@getList="getList"
/>
@ -274,35 +272,36 @@
<script>
import {
getIRUnReadSubjectTaskList,
verifyReadingRestTime,
} from "@/api/trials";
import { getTrialCriterionList } from "@/api/trials/reading";
import BaseContainer from "@/components/BaseContainer";
import uploadImage from "@/components/uploadImage";
import Pagination from "@/components/Pagination";
import { getToken } from "@/utils/auth";
verifyReadingRestTime
} from '@/api/trials'
import { getTrialCriterionList } from '@/api/trials/reading'
import { clearSkipReadingCache } from '@/api/reading'
import BaseContainer from '@/components/BaseContainer'
import uploadImage from '@/components/uploadImage'
import Pagination from '@/components/Pagination'
import { getToken } from '@/utils/auth'
const searchDataDefault = () => {
return {
SubjectCode: "",
SubjectCode: '',
PageIndex: 1,
PageSize: 20,
};
};
PageSize: 20
}
}
export default {
name: "ReadingTaskList",
components: { BaseContainer, Pagination, "upload-image": uploadImage },
name: 'ReadingTaskList',
components: { BaseContainer, Pagination, 'upload-image': uploadImage },
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
trialId: "",
trialId: '',
isReadingTaskViewInOrder: null,
randomReadInfo: {},
isRender: false,
trialCriterionList: [],
TrialReadingCriterionId: "",
TrialReadingCriterionId: '',
isTableShow: true,
readingTool: null,
criterionType: null,
@ -312,147 +311,146 @@ export default {
uploadImageVisible: false,
uploadSubjectId: null,
uploadTrialCriterion: {},
uploadStatus: "upload",
};
uploadStatus: 'upload'
}
},
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.getList();
this.getList()
}
}
},
},
mounted() {
window.addEventListener("message", this.receiveMsg);
this.trialId = this.$route.query.trialId;
this.getTrialCriterionList();
window.addEventListener('message', this.receiveMsg)
this.trialId = this.$route.query.trialId
this.getTrialCriterionList()
},
beforeDestroy() {
window.removeEventListener("message", this.receiveMsg);
window.removeEventListener('message', this.receiveMsg)
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
},
methods: {
//
openUploadImage(item, trialCriterion, status) {
this.uploadSubjectId = item.SubjectId;
this.uploadTrialCriterion = trialCriterion;
this.uploadStatus = status;
this.uploadImageVisible = true;
this.uploadSubjectId = item.SubjectId
this.uploadTrialCriterion = trialCriterion
this.uploadStatus = status
this.uploadImageVisible = true
},
getTrialCriterionList() {
getTrialCriterionList(this.trialId)
.then((res) => {
this.trialCriterionList = res.Result;
async getTrialCriterionList() {
try {
const res = await getTrialCriterionList(this.trialId)
if (res.IsSuccess) {
this.trialCriterionList = res.Result
this.TrialReadingCriterionId =
this.trialCriterionList[0].TrialReadingCriterionId;
})
.catch(() => {});
},
getList() {
this.loading = true;
this.searchData.TrialId = this.trialId;
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId;
this.isRender = false;
getIRUnReadSubjectTaskList(this.searchData)
.then((res) => {
this.isReadingTaskViewInOrder =
res.OtherInfo.IsReadingTaskViewInOrder;
this.readingTool = res.OtherInfo.ReadingTool;
this.criterionType = res.OtherInfo.CriterionType;
if (res.OtherInfo.IsReadingTaskViewInOrder) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
} else {
this.randomReadInfo = res.OtherInfo.RandomReadInfo;
this.trialCriterionList[0].TrialReadingCriterionId
}
} catch (e) {
console.log(e)
}
},
async getList() {
try {
this.loading = true
this.searchData.TrialId = this.trialId
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId
this.isRender = false
const res = await getIRUnReadSubjectTaskList(this.searchData)
if (res.IsSuccess) {
this.isReadingTaskViewInOrder =
res.OtherInfo.IsReadingTaskViewInOrder
this.readingTool = res.OtherInfo.ReadingTool
this.criterionType = res.OtherInfo.CriterionType
if (res.OtherInfo.IsReadingTaskViewInOrder) {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
} else {
this.randomReadInfo = res.OtherInfo.RandomReadInfo
}
this.isRender = true
this.loading = false
}
} catch (e) {
this.isRender = true
this.loading = false
}
this.isRender = true;
this.loading = false;
})
.catch(() => {
this.isRender = true;
this.loading = false;
});
},
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
handleReset() {
this.searchData = searchDataDefault();
this.getList();
this.searchData = searchDataDefault()
this.getList()
},
handleReadImage(row) {
async handleReadImage(row) {
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
this.loading = true;
verifyReadingRestTime()
.then((_) => {
this.loading = false;
window.localStorage.setItem(
"TrialReadingCriterionId",
this.TrialReadingCriterionId
);
var token = getToken();
var path = "";
try {
this.loading = true
await clearSkipReadingCache()
await verifyReadingRestTime()
this.loading = false
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
var token = getToken()
var path = ''
if (this.readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`;
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
} else {
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`;
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
}
var routeData = this.$router.resolve({ path });
var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, "_blank");
})
.catch(() => {
this.loading = false;
});
this.openWindow = window.open(routeData.href, '_blank')
} catch (e) {
this.loading = false
console.log(e)
}
},
handleOutOfOrderReading() {
async handleOutOfOrderReading() {
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
this.loading = true;
verifyReadingRestTime()
.then((_) => {
this.loading = false;
window.localStorage.setItem(
"TrialReadingCriterionId",
this.TrialReadingCriterionId
);
var token = getToken();
var path = "";
try {
this.loading = true
await clearSkipReadingCache()
await verifyReadingRestTime()
this.loading = false
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
var token = getToken()
var path = ''
if (this.readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`;
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
} else {
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`;
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
}
var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank')
} catch (e) {
this.loading = false
console.log(e)
}
var routeData = this.$router.resolve({ path });
this.openWindow = window.open(routeData.href, "_blank");
})
.catch(() => {
this.loading = false;
});
},
receiveMsg(event) {
if (event.data === "refreshTaskList") {
this.getList();
if (event.data === 'refreshTaskList') {
this.getList()
}
},
//
handleSortChange(column) {
if (column.order === "ascending") {
this.searchData.Asc = true;
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false;
this.searchData.Asc = false
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
},
},
};
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
}
}
}
</script>

View File

@ -412,6 +412,7 @@ import { getToken } from '@/utils/auth'
// import PreviewFiles from './previewFiles'
import uploadVideos from '@/components/videos'
import moment from 'moment'
import store from "@/store";
export default {
name: 'UploadNonDicomFiles',
components: { uploadVideos },
@ -470,7 +471,8 @@ export default {
uploadVideoVisible: false,
trialId: this.$route.query.trialId,
moment,
BodyPart:{}
BodyPart:{},
studyMonitorId: null
};
},
async mounted() {
@ -497,6 +499,12 @@ export default {
});
}
},
btnLoading(){
store.dispatch("trials/setUnLock", this.btnLoading);
}
},
beforeDestroy(){
store.dispatch("trials/setUnLock", false);
},
methods: {
// Dicom
@ -752,12 +760,21 @@ export default {
this.selectArr.forEach(item=>item.status = 0);
let num = this.selectArr.length > 6 ? 6 : this.selectArr.length;
let funArr = [];
let res = await preArchiveStudy({
subjectVisitId: this.subjectVisitId,
isDicom: false
});
if(res.IsSuccess){
this.studyMonitorId = res.Result;
for (let i = 0; i < num; i++) {
funArr.push(this.handleUploadTask(this.selectArr, i));
}
if (funArr.length > 0) {
let res = await Promise.all(funArr);
}
}else{
this.isFail = true;
}
}
},
//
@ -814,16 +831,12 @@ export default {
// Dicom
submitFile(uploadedFileList){
if(!this.uploadVisible) return;
preArchiveStudy({
subjectVisitId: this.subjectVisitId,
isDicom: false
}).then(res => {
this.btnLoading = true
var params = {
trialId: this.trialId,
subjectVisitId: this.subjectVisitId,
noneDicomStudyId:this.currentRow.Id,
studyMonitorId: res.Result,
studyMonitorId: this.studyMonitorId,
uploadedFileList: uploadedFileList
}
uploadNoneDicomFile(params).then(res => {
@ -833,7 +846,6 @@ export default {
this.$emit('getList')
this.$message.success(this.$t('trials:uploadNonDicoms:message:uploadedSuccessfully'))
}).catch(() => { this.btnLoading = false })
})
},
resetFileDiaolg(){
this.btnLoading = false

View File

@ -43,6 +43,16 @@
</el-col>
</el-row>
<div style="text-align: right">
<!-- 下载所有影像 -->
<el-button
v-if="$store.state.trials.config.IsSupportQCDownloadImage"
size="small"
type="primary"
style="margin-left: 10px"
@click="downloadImage(true)"
>
{{ $t("trials:audit:button:downLoadAllDiocms") }}
</el-button>
<!-- 预览所有影像 -->
<el-button
size="small"
@ -285,6 +295,16 @@
</el-col>
</el-row>
<div style="text-align: right">
<!-- 下载所有影像 -->
<el-button
v-if="$store.state.trials.config.IsSupportQCDownloadImage"
size="small"
type="primary"
style="margin-left: 10px"
@click="downloadImage(false)"
>
{{ $t("trials:audit:button:downLoadAllNonDiocms") }}
</el-button>
<!-- 预览 -->
<el-button
size="small"
@ -1198,6 +1218,7 @@ import SignForm from "@/views/trials/components/newSignForm";
import { getToken } from "@/utils/auth";
import const_ from "@/const/sign-code";
import uploadPetClinicalData from "@/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue";
import { downloadImage , resetFlag } from "@/utils/uploadZip.js";
export default {
name: "QualityAssurance",
components: {
@ -1310,6 +1331,9 @@ export default {
BodyPart: {},
};
},
beforeDestroy(){
resetFlag();
},
async mounted() {
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId);
if (this.disabled) {
@ -1332,6 +1356,18 @@ export default {
}
},
methods: {
//
async downloadImage(IsDicom) {
try {
await downloadImage(
this.$route.query.trialId,
this.data.Id,
IsDicom
);
} catch (err) {
console.log(err);
}
},
// QC
getQCInfo() {
this.loading = true;

View File

@ -63,7 +63,8 @@ module.exports = {
// target: 'http://123.56.94.154:8079', // 国内测试环境2
// target: 'http://123.56.94.154:7000', // 国内测试环境2
// target: 'http://123.56.94.154:30668',
target: 'http://106.14.89.110:30000',
// target: 'http://106.14.89.110:30000',
target: 'http://47.117.164.182:7010', // uat
// target: 'http://123.56.181.144:7000',
changeOrigin: true,
secure: false,
@ -94,7 +95,7 @@ module.exports = {
ignore: ['.*']
}
]),
process.env.NODE_ENV === 'development' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
process.env.NODE_ENV === 'development' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function() { }
: new WebpackAliyunOss({
from: ['./dist/**'],
dist: process.env.VUE_APP_OSS_PATH + distDate,
@ -123,7 +124,7 @@ module.exports = {
// 生成文件的最大体积
maxAssetSize: 3000000000,
// 只给出js的性能提示
assetFilter: function (assetFileName) {
assetFilter: function(assetFileName) {
return assetFileName.endsWith('.js')
}
},