33 Commits

Author SHA1 Message Date
wangxiaoshuang e0321bae72 影像预览问题解决
continuous-integration/drone/push Build encountered an error
2025-04-12 12:04:20 +08:00
wangxiaoshuang 1e720e399d 确认收入项,修改选项后,其他文件也改了
continuous-integration/drone/push Build encountered an error
2025-04-03 11:15:54 +08:00
wangxiaoshuang 1368397da9 项目总览—>上传记录:中心编号 查询条件,查询结果不对 2025-04-03 11:15:36 +08:00
wangxiaoshuang c8c049b5d0 DICOM影像中,存在Tag最大像素值、最小像素值等,但是和实际的数据统计结果不同 2025-04-03 11:15:22 +08:00
wangxiaoshuang 7fcbd7f983 生产环境配置修改
continuous-integration/drone/push Build encountered an error
2025-03-24 13:59:21 +08:00
wangxiaoshuang 779badb041 项目文档系统数据中英文转换
continuous-integration/drone/push Build is passing
2025-03-24 09:31:49 +08:00
caiyiling ef5e5527fd 标注更改及检查名称更改
continuous-integration/drone/push Build is passing
2025-03-21 16:29:47 +08:00
caiyiling 52ac12d6b6 阅片页面显示检查名称
continuous-integration/drone/push Build is passing
2025-03-21 15:36:23 +08:00
caiyiling 272c28a988 自定义阅片更改及非dicom阅片添加个性化配置
continuous-integration/drone/push Build is passing
2025-03-21 15:03:21 +08:00
caiyiling 6b10d07e2a 自定义阅片预览paf更改
continuous-integration/drone/push Build is passing
2025-03-21 14:03:53 +08:00
caiyiling 032e710890 阅片工具及报告页查看pdf更改
continuous-integration/drone/push Build is passing
2025-03-21 13:09:36 +08:00
caiyiling 032150904e 非dicom阅片更改
continuous-integration/drone/push Build is passing
2025-03-20 19:23:20 +08:00
wangxiaoshuang d91161a139 网速监控改为三位小数
continuous-integration/drone/push Build is passing
2025-03-19 15:53:41 +08:00
wangxiaoshuang bba2237337 文件大小改为保留3位小数
continuous-integration/drone/push Build is passing
2025-03-19 15:36:53 +08:00
wangxiaoshuang 707ca5602c Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-18 17:59:20 +08:00
wangxiaoshuang 3b03d6ba76 项目文档搜索栏样式问题 2025-03-18 17:59:10 +08:00
caiyiling 9277d48c85 1
continuous-integration/drone/push Build is passing
2025-03-18 17:55:22 +08:00
caiyiling d753fbc2ab 非dicom阅片测量工具更改
continuous-integration/drone/push Build is passing
2025-03-18 16:53:03 +08:00
caiyiling 5678e3302b 国际化补充
continuous-integration/drone/push Build is passing
2025-03-18 15:34:12 +08:00
caiyiling c25cb097ab 1
continuous-integration/drone/push Build is passing
2025-03-18 15:28:13 +08:00
caiyiling 070db5158d Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is running
2025-03-18 15:27:16 +08:00
caiyiling 121bf497bb 非dicom阅片更改 2025-03-18 15:26:51 +08:00
wangxiaoshuang e2ffd76504 阅片人筛选机构城市国家中英文显示
continuous-integration/drone/push Build is passing
2025-03-18 15:18:26 +08:00
wangxiaoshuang cfbe3b4839 项目文档培训记录培训人数校验修改
continuous-integration/drone/push Build is running
2025-03-18 15:16:31 +08:00
wangxiaoshuang 81bef8abe0 项目文档培训记录培训人数添加校验
continuous-integration/drone/push Build is passing
2025-03-18 14:15:31 +08:00
wangxiaoshuang 84b1263340 浏览器页签标题修改
continuous-integration/drone/push Build is passing
2025-03-18 13:57:07 +08:00
wangxiaoshuang 4016e71c37 项目文档阅片人问题修复
continuous-integration/drone/push Build is passing
2025-03-18 13:51:25 +08:00
wangxiaoshuang 3b0afd3913 1
continuous-integration/drone/push Build is passing
2025-03-18 13:45:13 +08:00
wangxiaoshuang 3672892451 项目文档阅片人问题修复
continuous-integration/drone/push Build is passing
2025-03-18 09:54:33 +08:00
wangxiaoshuang c46ca18a42 项目文档菜单与列表是否适用字段联动
continuous-integration/drone/push Build is passing
2025-03-17 16:38:14 +08:00
wangxiaoshuang 0e0b5c2c4c 项目文档同意入项记录上传方式修改
continuous-integration/drone/push Build is passing
2025-03-17 14:34:24 +08:00
wangxiaoshuang 5339e2df63 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-17 13:23:25 +08:00
wangxiaoshuang 66d5591d50 项目文档同意入项记录上传更改为弹框 2025-03-17 13:23:21 +08:00
52 changed files with 2255 additions and 1571 deletions
+3
View File
@@ -2,6 +2,9 @@
ENV = 'prop' ENV = 'prop'
NODE_ENV = 'prop' NODE_ENV = 'prop'
# base public path
VUE_APP_BASE_PATH = '/'
# 是否开启登陆限制 true:是 false:否 # 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true VUE_APP_LOGIN_FOR_PERMISSION = true
+197
View File
File diff suppressed because one or more lines are too long
+8
View File
@@ -1265,6 +1265,14 @@ export function getTrialFileTypeFile(data) {
data data
}) })
} }
// 项目文档-删除上传同意入项记录
export function deleteTrialTypeFile(params) {
return request({
url: `/TrialFileType/deleteTrialTypeFile`,
method: 'post',
params
})
}
// 项目文档-获取资质材料列表 // 项目文档-获取资质材料列表
export function getTrialAttachments(data) { export function getTrialAttachments(data) {
return request({ return request({
@@ -316,9 +316,9 @@
scope.row.dicomInfo.fileCount scope.row.dicomInfo.fileCount
}} }}
({{ ({{
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(2) (scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(3)
}}MB/{{ }}MB/{{
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(2) (scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(3)
}}MB) }}MB)
</span> </span>
</template> </template>
@@ -66,7 +66,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.FileSize && scope.row.FileSize > 0 scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -138,7 +138,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.FileSize && scope.row.FileSize > 0 scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -320,7 +320,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.size && scope.row.size > 0 scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
+1 -1
View File
@@ -1,7 +1,7 @@
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
module.exports = { module.exports = {
title: 'IRCIS', title: 'IRC Imaging System',
/** /**
* @type {boolean} true | false * @type {boolean} true | false
+1
View File
@@ -862,6 +862,7 @@ const actions = {
const data = {} const data = {}
data.StudyId = study.StudyId data.StudyId = study.StudyId
data.StudyCode = study.StudyCode data.StudyCode = study.StudyCode
data.StudyName = study.StudyName
data.Modalities = study.Modalities data.Modalities = study.Modalities
data.SeriesCount = study.SeriesCount data.SeriesCount = study.SeriesCount
data.InstanceCount = study.InstanceCount data.InstanceCount = study.InstanceCount
+1 -1
View File
@@ -1,6 +1,6 @@
import defaultSettings from '@/settings' import defaultSettings from '@/settings'
const title = defaultSettings.title || 'IRCIS' const title = defaultSettings.title || 'IRC Imaging System'
export default function getPageTitle(pageTitle) { export default function getPageTitle(pageTitle) {
if (pageTitle) { if (pageTitle) {
+149
View File
@@ -39,6 +39,108 @@ function getNumberValues(dataSet, tag, minimumLength) {
return values; return values;
} }
function getLutDescriptor(dataSet, tag) {
if (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) {
return;
}
return [
dataSet.uint16(tag, 0),
dataSet.uint16(tag, 1),
dataSet.uint16(tag, 2),
];
}
function getLutData(lutDataSet, tag, lutDescriptor) {
const lut = [];
const lutData = lutDataSet.elements[tag];
for (let i = 0; i < lutDescriptor[0]; i++) {
// Output range is always unsigned
if (lutDescriptor[2] === 16) {
lut[i] = lutDataSet.uint16(tag, i);
} else {
lut[i] = lutDataSet.byteArray[i + lutData.dataOffset];
}
}
return lut;
}
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
const pixelRepresentation = dataSet.uint16('x00280103');
if (pixelRepresentation === 0) {
imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
} else {
imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
}
imagePixelModule.largestPixelValue = imagePixelModule.largestPixelValue === 0 ? undefined : imagePixelModule.largestPixelValue;
}
function populatePaletteColorLut(dataSet, imagePixelModule) {
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281101'
);
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281102'
);
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281103'
);
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
// When the number of table entries is equal to 2ˆ16 then this value shall be 0.
// See http://dicom.nema.org/MEDICAL/DICOM/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5
if (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) {
imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65536;
}
// The third Palette Color Lookup Table Descriptor value specifies the number of bits for each entry in the Lookup Table Data.
// It shall take the value of 8 or 16.
// The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1.
// The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors.
//
// Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits;
// this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry.
// The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16.
const numLutEntries =
imagePixelModule.redPaletteColorLookupTableDescriptor[0];
const lutData = dataSet.elements.x00281201;
const lutBitsAllocated = lutData.length === numLutEntries ? 8 : 16;
// If the descriptors do not appear to have the correct values, correct them
if (
imagePixelModule.redPaletteColorLookupTableDescriptor[2] !==
lutBitsAllocated
) {
imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated;
imagePixelModule.greenPaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
imagePixelModule.bluePaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
}
imagePixelModule.redPaletteColorLookupTableData = getLutData(
dataSet,
'x00281201',
imagePixelModule.redPaletteColorLookupTableDescriptor
);
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
dataSet,
'x00281202',
imagePixelModule.greenPaletteColorLookupTableDescriptor
);
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
dataSet,
'x00281203',
imagePixelModule.bluePaletteColorLookupTableDescriptor
);
}
function metaDataProvider(type, imageId) { function metaDataProvider(type, imageId) {
const parsedImageId = parseImageId(imageId); const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url); const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
@@ -99,5 +201,52 @@ function metaDataProvider(type, imageId) {
columnPixelSpacing, columnPixelSpacing,
}; };
} }
if (type === 'imagePixelModule') {
const imagePixelModule = {
samplesPerPixel: dataSet.uint16('x00280002'),
photometricInterpretation: dataSet.string('x00280004'),
rows: dataSet.uint16('x00280010'),
columns: dataSet.uint16('x00280011'),
bitsAllocated: dataSet.uint16('x00280100'),
bitsStored: dataSet.uint16('x00280101'),
highBit: dataSet.uint16('x00280102'),
pixelRepresentation: dataSet.uint16('x00280103'),
planarConfiguration: dataSet.uint16('x00280006'),
pixelAspectRatio: dataSet.string('x00280034'),
};
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
if (
imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
dataSet.elements.x00281101
) {
populatePaletteColorLut(dataSet, imagePixelModule);
}
return imagePixelModule;
}
// if (type === 'imagePixelModule') {
// return {
// samplesPerPixel: dataSet.uint16('x00280002'),
// photometricInterpretation: dataSet.string('x00280004'),
// rows: dataSet.uint16('x00280010'),
// columns: dataSet.uint16('x00280011'),
// bitsAllocated: dataSet.uint16('x00280100'),
// bitsStored: dataSet.uint16('x00280101'),
// highBit: dataSet.uint16('x00280102'),
// pixelRepresentation: dataSet.uint16('x00280103'),
// planarConfiguration: dataSet.uint16('x00280006'),
// pixelAspectRatio: dataSet.uint16('x00280034'),
// smallestPixelValue: null,
// largestPixelValue: null,
// // smallestPixelValue: dataSet.uint16('x00280106'),
// // largestPixelValue: dataSet.uint16('x00280107'),
// redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
// greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
// bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
// redPaletteColorLookupTableData: dataSet.string('x00281201'),
// greenPaletteColorLookupTableData: dataSet.string('x00281202'),
// bluePaletteColorLookupTableData: dataSet.string('x00281203')
// }
// }
} }
export default metaDataProvider; export default metaDataProvider;
+1 -1
View File
@@ -445,7 +445,7 @@ function setTimer() {
totalBytes = totalBytes / 1024; totalBytes = totalBytes / 1024;
unit = "MB/s"; unit = "MB/s";
} }
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit; store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
} }
if (timeList.length >= 5) { if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]] delete bytesReceivedPerSecond[timeList[0]]
+1 -1
View File
@@ -150,7 +150,7 @@ function setTimer() {
totalBytes = totalBytes / 1024; totalBytes = totalBytes / 1024;
unit = "MB/s"; unit = "MB/s";
} }
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit; store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
} }
if (timeList.length >= 5) { if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]] delete bytesReceivedPerSecond[timeList[0]]
+1
View File
@@ -9,6 +9,7 @@ const ROUTER = require('@/router');
axios.defaults.withCredentials = false axios.defaults.withCredentials = false
const service = axios.create({ const service = axios.create({
baseURL: '/api', baseURL: '/api',
// baseURL: process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api',
timeout: 2 * 360000, // request timeout timeout: 2 * 360000, // request timeout
withCredentials: false withCredentials: false
}) })
+1 -1
View File
@@ -241,7 +241,7 @@ const searchDataDefault = () => {
PageIndex: 1, PageIndex: 1,
PageSize: 20, PageSize: 20,
asc: false, asc: false,
sortField: 'CreateTime', sortField: '',
} }
} }
export default { export default {
@@ -291,21 +291,33 @@
:label="$t('trials:seletctedReviews:table:institution')" :label="$t('trials:seletctedReviews:table:institution')"
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
/> >
<template slot-scope="scope">
<span>{{ isEN?scope.row.HospitalName:scope.row.HospitalNameCN }}</span>
</template>
</el-table-column>
<!-- City --> <!-- City -->
<el-table-column <el-table-column
prop="City" prop="City"
:label="$t('trials:seletctedReviews:table:city')" :label="$t('trials:seletctedReviews:table:city')"
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
/> >
<template slot-scope="scope">
<span>{{ isEN?scope.row.City:scope.row.CityCN }}</span>
</template>
</el-table-column>
<!-- Country --> <!-- Country -->
<el-table-column <el-table-column
prop="Country" prop="Country"
:label="$t('trials:seletctedReviews:table:country')" :label="$t('trials:seletctedReviews:table:country')"
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
/> >
<template slot-scope="scope">
<span>{{ isEN?scope.row.Country:scope.row.CountryCN }}</span>
</template>
</el-table-column>
<!-- Selector --> <!-- Selector -->
<el-table-column <el-table-column
prop="OptUserName" prop="OptUserName"
@@ -18,7 +18,6 @@
</div> </div>
</div> </div>
<el-form-item <el-form-item
v-for="qs in questions" v-for="qs in questions"
v-show="qs.ShowQuestion!==2" v-show="qs.ShowQuestion!==2"
@@ -51,35 +50,35 @@
type="text" type="text"
@click="addAnnotation(qs)" @click="addAnnotation(qs)"
> >
{{$t('trials:MRIPDFF:button:measure')}} {{ $t('trials:MRIPDFF:button:measure') }}
</el-button> </el-button>
<!-- 清除标记 --> <!-- 清除标记 -->
<el-button <el-button
v-if="getAnnotationStatus(qs) && readingTaskState!== 2" v-if="getAnnotationStatus(qs) && readingTaskState!== 2"
size="mini" size="mini"
type="text" type="text"
@click="removeAnnotation(qs)"
style="margin-left: 0px" style="margin-left: 0px"
@click="removeAnnotation(qs)"
> >
{{$t('trials:MRIPDFF:button:clear')}} {{ $t('trials:MRIPDFF:button:clear') }}
</el-button> </el-button>
<!-- 返回 --> <!-- 返回 -->
<el-button <el-button
v-if="questionForm[qs.Id]" v-if="questionForm[qs.Id]"
size="mini" size="mini"
type="text" type="text"
@click="locateAnnotation(qs)"
style="margin-left: 0px" style="margin-left: 0px"
@click="locateAnnotation(qs)"
> >
{{$t('trials:MRIPDFF:button:return')}} {{ $t('trials:MRIPDFF:button:return') }}
</el-button> </el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button <el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2" v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2"
size="mini" size="mini"
type="text" type="text"
@click="saveAnnotation(qs)"
style="margin-left: 0px" style="margin-left: 0px"
@click="saveAnnotation(qs)"
> >
<!-- 未保存 --> <!-- 未保存 -->
<el-tooltip v-if="getAnnotationSaveEnum(qs) === 0" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom"> <el-tooltip v-if="getAnnotationSaveEnum(qs) === 0" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
@@ -279,7 +278,7 @@ export default {
}, },
mounted() { mounted() {
this.trialId = this.$route.query.trialId this.trialId = this.$route.query.trialId
let digitPlaces = Number(localStorage.getItem('digitPlaces')) const digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.initForm() this.initForm()
DicomEvent.$on('handleImageQualityAbnormal', () => { DicomEvent.$on('handleImageQualityAbnormal', () => {
@@ -295,26 +294,29 @@ export default {
this.isMeasurableId = this.getQuestionId(1105) this.isMeasurableId = this.getQuestionId(1105)
// const loading = this.$loading({ fullscreen: true }) // const loading = this.$loading({ fullscreen: true })
this.questions.forEach(item => { this.questions.forEach(item => {
var val = this.answers[item.Id] if (this.answers.hasOwnProperty(item.Id)) {
let val = this.answers[item.Id]
if (item.DictionaryCode) { if (item.DictionaryCode) {
val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id]) val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id])
} }
this.$set(this.questionForm, item.Id, val) this.$set(this.questionForm, item.Id, val)
} else {
this.$set(this.questionForm, item.Id, '')
}
}) })
this.$set(this.questionForm, 'MeasureData', this.answers.MeasureData ? JSON.parse(this.answers.MeasureData) : '') this.$set(this.questionForm, 'MeasureData', this.answers.MeasureData ? JSON.parse(this.answers.MeasureData) : '')
this.$set(this.questionForm, 'RowIndex', this.answers.RowIndex ? this.answers.RowIndex : '') this.$set(this.questionForm, 'RowIndex', this.answers.RowIndex ? this.answers.RowIndex : '')
this.$set(this.questionForm, 'RowId', this.answers.RowId ? this.answers.RowId : '') this.$set(this.questionForm, 'RowId', this.answers.RowId ? this.answers.RowId : '')
// 如果存在标记且是否可测量为否,则将是否可测量更改为是 // 如果存在标记且是否可测量为否,则将是否可测量更改为是
if (this.isCurrentTask && this.readingTaskState < 2) { if (this.isCurrentTask && this.readingTaskState < 2) {
let arr = JSON.parse(this.answers.TableQuestionMarkList) const arr = JSON.parse(this.answers.TableQuestionMarkList)
let isExitsMarks = arr.findIndex(i=>i.MeasureData) > -1 const isExitsMarks = arr.findIndex(i => i.MeasureData) > -1
if (isExitsMarks && parseInt(this.questionForm[this.isMeasurableId]) === 0) { if (isExitsMarks && parseInt(this.questionForm[this.isMeasurableId]) === 0) {
this.$set(this.questionForm, this.isMeasurableId, 1) this.$set(this.questionForm, this.isMeasurableId, 1)
} }
} }
// saveTypeEnum 0:未保存过(新建病灶);1:已保存,信息不完整(随访初始化病灶/分裂病灶,通过状态判断);2:已保存,信息完整 // saveTypeEnum 0:未保存过(新建病灶);1:已保存,信息不完整(随访初始化病灶/分裂病灶,通过状态判断);2:已保存,信息完整
let isMeasurable = this.getQuestionVal(1105) const isMeasurable = this.getQuestionVal(1105)
const mean = this.getQuestionVal(1104) const mean = this.getQuestionVal(1104)
if (this.questionForm.saveTypeEnum !== 1 && this.isCurrentTask && this.readingTaskState < 2) { if (this.questionForm.saveTypeEnum !== 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.$set(this.questionForm, 'saveTypeEnum', parseInt(isMeasurable) === 1 && isNaN(parseFloat(mean)) ? 1 : 2) this.$set(this.questionForm, 'saveTypeEnum', parseInt(isMeasurable) === 1 && isNaN(parseFloat(mean)) ? 1 : 2)
@@ -325,11 +327,11 @@ export default {
this.markList = [] this.markList = []
this.isExitsMarks = false this.isExitsMarks = false
this.isDisabledMeasurableRadio = false this.isDisabledMeasurableRadio = false
let seg = this.getQuestionVal(1106) const seg = this.getQuestionVal(1106)
this.liverSeg = this.$fd('LiverSegmentation', seg) this.liverSeg = this.$fd('LiverSegmentation', seg)
if (this.answers.TableQuestionMarkList) { if (this.answers.TableQuestionMarkList) {
let arr = JSON.parse(this.answers.TableQuestionMarkList) const arr = JSON.parse(this.answers.TableQuestionMarkList)
arr.map(i=>{ arr.map(i => {
if (i.MeasureData) { if (i.MeasureData) {
this.isExitsMarks = true this.isExitsMarks = true
if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1 && this.isCurrentTask && this.readingTaskState < 2) { if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1 && this.isCurrentTask && this.readingTaskState < 2) {
@@ -337,14 +339,14 @@ export default {
} }
i.MeasureData = JSON.parse(i.MeasureData) i.MeasureData = JSON.parse(i.MeasureData)
} }
this.markList.push({tableQuestionId: i.TableQuestionId, measureData: i, saveEnum: 1}) this.markList.push({ tableQuestionId: i.TableQuestionId, measureData: i, saveEnum: 1 })
}) })
} }
let newMean = this.getMean() const newMean = this.getMean()
if (newMean !== mean) { if (newMean !== mean) {
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '') this.$set(this.questionForm, meanId, newMean || '')
} }
if (this.questionForm.saveTypeEnum === 1 && this.isCurrentTask && this.readingTaskState < 2) { if (this.questionForm.saveTypeEnum === 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.setQuestions() this.setQuestions()
@@ -357,13 +359,13 @@ export default {
// I II III IV V VI VII VIII // I II III IV V VI VII VIII
// L-I-01 L-I-02 L-I-03 // L-I-01 L-I-02 L-I-03
// L-II-01 L-II-02 L-II-03 // L-II-01 L-II-02 L-II-03
let segArr = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII'] const segArr = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII']
let lessionName = '' let lessionName = ''
let segmentId = this.getQuestionId(1106) const segmentId = this.getQuestionId(1106)
let segmentVal = this.answers[segmentId] let segmentVal = this.answers[segmentId]
segmentVal = segmentVal ? parseInt(segmentVal) : null segmentVal = segmentVal ? parseInt(segmentVal) : null
if (segmentVal) { if (segmentVal) {
let i = questionMark === 1101 ? '01' : questionMark === 1102 ? '02' : questionMark === 1103 ? '03' : '' const i = questionMark === 1101 ? '01' : questionMark === 1102 ? '02' : questionMark === 1103 ? '03' : ''
lessionName = `${orderMark}-${segArr[segmentVal - 1]}-${i}` lessionName = `${orderMark}-${segArr[segmentVal - 1]}-${i}`
} }
return lessionName return lessionName
@@ -397,18 +399,18 @@ export default {
this.$set(this.questionForm, 'saveTypeEnum', 1) this.$set(this.questionForm, 'saveTypeEnum', 1)
const mean = this.getQuestionVal(1104) const mean = this.getQuestionVal(1104)
if (qs.QuestionMark === 1101 || qs.QuestionMark === 1102 || qs.QuestionMark === 1103) { if (qs.QuestionMark === 1101 || qs.QuestionMark === 1102 || qs.QuestionMark === 1103) {
let newMean = this.getMean() const newMean = this.getMean()
if (newMean !== mean) { if (newMean !== mean) {
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '') this.$set(this.questionForm, meanId, newMean || '')
} }
} else if (qs.QuestionMark === 1105) { } else if (qs.QuestionMark === 1105) {
if (!v) { if (!v) {
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE') this.$set(this.questionForm, meanId, 'NE')
} else { } else {
let mean = this.getMean() const mean = this.getMean()
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, mean) this.$set(this.questionForm, meanId, mean)
} }
} }
@@ -418,10 +420,10 @@ export default {
let mean = null let mean = null
let isMeasurable = this.getQuestionVal(1105) let isMeasurable = this.getQuestionVal(1105)
isMeasurable = !isNaN(parseInt(isMeasurable)) ? parseInt(isMeasurable) : null isMeasurable = !isNaN(parseInt(isMeasurable)) ? parseInt(isMeasurable) : null
let l1 = this.getQuestionVal(1101) const l1 = this.getQuestionVal(1101)
let l2 = this.getQuestionVal(1102) const l2 = this.getQuestionVal(1102)
let l3 = this.getQuestionVal(1103) const l3 = this.getQuestionVal(1103)
if ( isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) { if (isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) {
const sum = l1 + l2 + l3 const sum = l1 + l2 + l3
mean = sum / 3 mean = sum / 3
return parseFloat(mean.toFixed(this.digitPlaces)) return parseFloat(mean.toFixed(this.digitPlaces))
@@ -442,7 +444,7 @@ export default {
// 维护标记信息 // 维护标记信息
measureData.data.remark = this.getLesionName(this.orderMark, this.activeQuestionMark) measureData.data.remark = this.getLesionName(this.orderMark, this.activeQuestionMark)
} }
let val = measureData.data.cachedStats.mean / 10 const val = measureData.data.cachedStats.mean / 10
this.$set(this.questionForm, measureData.tableQuestionId, val.toFixed(this.digitPlaces)) this.$set(this.questionForm, measureData.tableQuestionId, val.toFixed(this.digitPlaces))
data = { data = {
Id: '', Id: '',
@@ -461,17 +463,17 @@ export default {
} }
store.dispatch('reading/addMeasuredData', { visitTaskId: this.visitTaskId, data: data }) store.dispatch('reading/addMeasuredData', { visitTaskId: this.visitTaskId, data: data })
let mean = this.getQuestionVal(1104) let mean = this.getQuestionVal(1104)
let newMean = this.getMean() const newMean = this.getMean()
if (newMean !== mean) { if (newMean !== mean) {
mean = newMean mean = newMean
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '') this.$set(this.questionForm, meanId, newMean || '')
} }
const isMeasurable = this.getQuestionVal(1105) const isMeasurable = this.getQuestionVal(1105)
DicomEvent.$emit('refreshStudyListMeasureData') DicomEvent.$emit('refreshStudyListMeasureData')
let i = this.markList.findIndex(i=>i.tableQuestionId === measureData.tableQuestionId) const i = this.markList.findIndex(i => i.tableQuestionId === measureData.tableQuestionId)
if (i === -1) { if (i === -1) {
this.markList.push({tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0}) this.markList.push({ tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0 })
} else { } else {
this.markList[i].saveEnum = 0 this.markList[i].saveEnum = 0
this.markList[i].measureData = data this.markList[i].measureData = data
@@ -486,19 +488,19 @@ export default {
}, },
addAnnotation(qs) { addAnnotation(qs) {
// 判断是否有测量数据未保存 // 判断是否有测量数据未保存
let i = this.markList.findIndex(i=>i.saveEnum === 0) const i = this.markList.findIndex(i => i.saveEnum === 0)
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) { if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
this.$alert(this.$t('trials:MRIPDFF:message:message3')) this.$alert(this.$t('trials:MRIPDFF:message:message3'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message3')) // this.$message.warning(this.$t('trials:MRIPDFF:message:message3'))
return return
} }
let orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark) const orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark)
this.activeQuestionId = qs.Id this.activeQuestionId = qs.Id
this.activeQuestionMark= qs.QuestionMark this.activeQuestionMark = qs.QuestionMark
DicomEvent.$emit('addAnnotation', {question: qs, locateInfo: { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: orderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true }}) DicomEvent.$emit('addAnnotation', { question: qs, locateInfo: { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: orderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true }})
}, },
getAnnotationSaveEnum(qs) { getAnnotationSaveEnum(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
if (i > -1) { if (i > -1) {
return this.markList[i].saveEnum return this.markList[i].saveEnum
} else { } else {
@@ -506,7 +508,7 @@ export default {
} }
}, },
getAnnotationStatus(qs) { getAnnotationStatus(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) { if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
return true return true
} else { } else {
@@ -516,14 +518,13 @@ export default {
getIsExitsMarks() { getIsExitsMarks() {
const isMeasurable = this.getQuestionVal(1105) const isMeasurable = this.getQuestionVal(1105)
if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1) { if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1) {
return this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false return this.markList.findIndex(i => i.measureData && i.measureData.MeasureData) > -1
} else { } else {
return false return false
} }
}, },
async removeAnnotation(qs) { async removeAnnotation(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
DicomEvent.$emit('imageLocation', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.markList[i].measureData.OrderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true }) DicomEvent.$emit('imageLocation', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.markList[i].measureData.OrderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true })
// 是否确认清除标记? // 是否确认清除标记?
const confirm = await this.$confirm( const confirm = await this.$confirm(
@@ -535,26 +536,26 @@ export default {
) )
if (confirm !== 'confirm') return if (confirm !== 'confirm') return
let measureData = Object.assign({}, this.markList[i].measureData) const measureData = Object.assign({}, this.markList[i].measureData)
if (measureData.Id) { if (measureData.Id) {
await deleteSingleTableQuestionMark({Id: measureData.Id}, 11) await deleteSingleTableQuestionMark({ Id: measureData.Id }, 11)
} }
// 移除缓存中的measureData // 移除缓存中的measureData
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: measureData.OrderMarkName}) await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: measureData.OrderMarkName })
DicomEvent.$emit('getMeasureData') DicomEvent.$emit('getMeasureData')
this.markList[i].measureData = null this.markList[i].measureData = null
this.markList[i].saveEnum = 0 this.markList[i].saveEnum = 0
// 清除测量值、清除平均值 // 清除测量值、清除平均值
this.$set(this.questionForm, this.markList[i].tableQuestionId, '') this.$set(this.questionForm, this.markList[i].tableQuestionId, '')
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, '') this.$set(this.questionForm, meanId, '')
this.isDisabledMeasurableRadio = this.getIsExitsMarks() this.isDisabledMeasurableRadio = this.getIsExitsMarks()
this.$set(this.questionForm, 'saveTypeEnum', 1) this.$set(this.questionForm, 'saveTypeEnum', 1)
this.setQuestions() this.setQuestions()
}, },
locateAnnotation(qs) { locateAnnotation(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
let measureData = this.markList[i].measureData const measureData = this.markList[i].measureData
// 定位 // 定位
var markTool = 'Probe' var markTool = 'Probe'
var readingTaskState = this.readingTaskState var readingTaskState = this.readingTaskState
@@ -569,18 +570,18 @@ export default {
async saveAnnotation(qs) { async saveAnnotation(qs) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
try { try {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
let params = {} let params = {}
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) { if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
let measureData = this.markList[i].measureData.MeasureData const measureData = this.markList[i].measureData.MeasureData
// 上传截图 // 上传截图
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: measureData.OrderMarkName, lesionType: null, isMarked: !!measureData }, async val => { DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: measureData.OrderMarkName, lesionType: null, isMarked: !!measureData }, async val => {
params = Object.assign({}, this.markList[i].measureData) params = Object.assign({}, this.markList[i].measureData)
if (val) { if (val) {
let pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val) const pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
params.PicturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : '' params.PicturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
} }
let tableQuestionId = this.markList[i].tableQuestionId const tableQuestionId = this.markList[i].tableQuestionId
params.Answer = this.questionForm[tableQuestionId] params.Answer = this.questionForm[tableQuestionId]
params.MeasureData = JSON.stringify(this.markList[i].measureData.MeasureData) params.MeasureData = JSON.stringify(this.markList[i].measureData.MeasureData)
loading.close() loading.close()
@@ -588,13 +589,13 @@ export default {
}) })
} else { } else {
params = { params = {
Answer: "", Answer: '',
VisitTaskId: this.visitTaskId, VisitTaskId: this.visitTaskId,
QuestionId: this.parentQsId, QuestionId: this.parentQsId,
InstanceId: '', InstanceId: '',
SeriesId: '', SeriesId: '',
StudyId: '', StudyId: '',
MarkTool:'', MarkTool: '',
PicturePath: '', PicturePath: '',
NumberOfFrames: 0, NumberOfFrames: 0,
MeasureData: '', MeasureData: '',
@@ -607,9 +608,7 @@ export default {
loading.close() loading.close()
this.saveTableQuestionInfo(params, qs) this.saveTableQuestionInfo(params, qs)
} }
} catch (e) {
} catch(e) {
console.log(e) console.log(e)
loading.close() loading.close()
} }
@@ -617,16 +616,16 @@ export default {
async saveTableQuestionInfo(params, qs) { async saveTableQuestionInfo(params, qs) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
try { try {
let res = await saveTableQuestionMark(params, 11) const res = await saveTableQuestionMark(params, 11)
if (res.IsSuccess) { if (res.IsSuccess) {
// 保存后设置保存状态 // 保存后设置保存状态
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id) const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
this.markList[i].saveEnum = 1 this.markList[i].saveEnum = 1
// 保存病灶 // 保存病灶
let j = this.markList.findIndex(i=>!(i.saveEnum === 1 && i.measureData && i.measureData.MeasureData)) const j = this.markList.findIndex(i => !(i.saveEnum === 1 && i.measureData && i.measureData.MeasureData))
if (j === -1) { if (j === -1) {
let answers = [] const answers = []
let reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/) const reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
for (const k in this.questionForm) { for (const k in this.questionForm) {
if (reg.test(k)) { if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) { if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
@@ -634,7 +633,7 @@ export default {
} }
} }
} }
let params = { const params = {
questionId: this.parentQsId, questionId: this.parentQsId,
rowId: this.questionForm.RowId, rowId: this.questionForm.RowId,
rowIndex: this.answers.RowIndex, rowIndex: this.answers.RowIndex,
@@ -659,7 +658,7 @@ export default {
DicomEvent.$emit('setMeasuredToolsPassive') DicomEvent.$emit('setMeasuredToolsPassive')
loading.close() loading.close()
} }
} catch(e) { } catch (e) {
console.log(e) console.log(e)
loading.close() loading.close()
} }
@@ -738,7 +737,7 @@ export default {
if (!valid) return if (!valid) return
if (parseInt(this.questionForm[this.isMeasurableId]) === 1) { if (parseInt(this.questionForm[this.isMeasurableId]) === 1) {
// 检验是否有标记为保存 // 检验是否有标记为保存
let i = this.markList.findIndex(i=>i.saveEnum === 0) const i = this.markList.findIndex(i => i.saveEnum === 0)
if (i > -1) { if (i > -1) {
// 请先保存标注信息! // 请先保存标注信息!
this.$alert(this.$t('trials:MRIPDFF:message:message1')) this.$alert(this.$t('trials:MRIPDFF:message:message1'))
@@ -756,13 +755,13 @@ export default {
} }
) )
if (confirm !== 'confirm') return if (confirm !== 'confirm') return
let l1Id = this.getQuestionId(1101) const l1Id = this.getQuestionId(1101)
this.$set(this.questionForm, l1Id, '') this.$set(this.questionForm, l1Id, '')
let l2Id = this.getQuestionId(1102) const l2Id = this.getQuestionId(1102)
this.$set(this.questionForm, l2Id, '') this.$set(this.questionForm, l2Id, '')
let l3Id = this.getQuestionId(1103) const l3Id = this.getQuestionId(1103)
this.$set(this.questionForm, l3Id, '') this.$set(this.questionForm, l3Id, '')
let meanId = this.getQuestionId(1104) const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE') this.$set(this.questionForm, meanId, 'NE')
} }
@@ -771,7 +770,7 @@ export default {
try { try {
// let isResetMarks = this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false // let isResetMarks = this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false
if (parseInt(this.questionForm[this.isMeasurableId]) === 0 && this.isExitsMarks) { if (parseInt(this.questionForm[this.isMeasurableId]) === 0 && this.isExitsMarks) {
await deleteTableQuestionMark({rowId: this.questionForm.RowId}, 11) await deleteTableQuestionMark({ rowId: this.questionForm.RowId }, 11)
this.markList.forEach(i => { this.markList.forEach(i => {
if (i.measureData && i.measureData.MeasureData) { if (i.measureData && i.measureData.MeasureData) {
i.measureData = '' i.measureData = ''
@@ -19,12 +19,21 @@
class="dicom-desc" class="dicom-desc"
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;" style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
> >
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
<div> <div>
<span>{{ study.StudyCode }} {{ study.Description }}</span> <div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span> <span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span style="margin-left: 5px;">{{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" v-else>
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName" style="margin: 0 5px">
{{study.StudyName}}
</span>
<div>{{ study.Modalities }} ({{ study.SeriesCount }})</div>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" :title="study.Description">{{ study.Description }}</div>
</div> </div>
</el-tooltip>
</div> </div>
</template> </template>
@@ -205,7 +214,8 @@ export default {
srDialogVisible: false, srDialogVisible: false,
srInfo: {}, srInfo: {},
digitPlaces: 2, digitPlaces: 2,
visitTaskIdx: -1 visitTaskIdx: -1,
taskInfo: null
} }
}, },
@@ -243,6 +253,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode') this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => { DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
@@ -76,7 +76,7 @@
<el-input <el-input
v-if="question.Type==='input'" v-if="question.Type==='input'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2" :disabled="question.TableQuestionType === 2 || readingTaskState === 2"
/> />
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input <el-input
@@ -84,13 +84,14 @@
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
type="textarea" type="textarea"
:autosize="{ minRows: 2, maxRows: 4}" :autosize="{ minRows: 2, maxRows: 4}"
:disabled="readingTaskState === 2"
/> />
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select <el-select
v-if="question.Type==='select'" v-if="question.Type==='select'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
clearable clearable
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode" :disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode || readingTaskState === 2"
@change="((val)=>{formItemChange(val, question)})" @change="((val)=>{formItemChange(val, question)})"
> >
<template v-if="question.TableQuestionType === 1"> <template v-if="question.TableQuestionType === 1">
@@ -132,6 +133,7 @@
v-if="question.Type==='radio'" v-if="question.Type==='radio'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
@change="((val)=>{formItemChange(val, question)})" @change="((val)=>{formItemChange(val, question)})"
:disabled="readingTaskState === 2"
> >
<el-radio <el-radio
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
@@ -145,6 +147,7 @@
<el-checkbox-group <el-checkbox-group
v-if="question.Type==='checkbox'" v-if="question.Type==='checkbox'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState === 2"
> >
<el-checkbox <el-checkbox
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
@@ -158,12 +161,12 @@
<el-input <el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1" v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType" :disabled="!question.ClassifyEditType || readingTaskState === 2"
/> />
<el-select <el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2" v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType" :disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }" @change="(val) => { formItemChange(val, question) }"
> >
<el-option <el-option
@@ -176,7 +179,7 @@
<el-radio-group <el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3" v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType" :disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }" @change="(val) => { formItemChange(val, question) }"
> >
<el-radio <el-radio
@@ -190,7 +193,7 @@
<el-input <el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 4" v-if="question.Type === 'class' && question.ClassifyShowType === 4"
type="number" type="number"
:disabled="!question.ClassifyEditType" :disabled="!question.ClassifyEditType || readingTaskState === 2"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
@change="(val) => { formItemNumberChange(val, question) }" @change="(val) => { formItemNumberChange(val, question) }"
/> />
@@ -215,6 +218,7 @@
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
clearable clearable
@change="(val) => { formItemNumberChange(val, question) }" @change="(val) => { formItemNumberChange(val, question) }"
:disabled="readingTaskState === 2"
> >
<el-option <el-option
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
@@ -229,6 +233,7 @@
@change="(val) => { formItemNumberChange(val, question) }" @change="(val) => { formItemNumberChange(val, question) }"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)" @blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState === 2"
> >
<!-- <template slot="append">1</template> --> <!-- <template slot="append">1</template> -->
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template> <template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
@@ -238,7 +243,7 @@
type="number" type="number"
v-if="question.Type === 'number' && !question.TypeValue && question.DataSource === 1" v-if="question.Type === 'number' && !question.TypeValue && question.DataSource === 1"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)" @blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
:disabled="question.DataSource === 1" :disabled="question.DataSource === 1 || readingTaskState === 2"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
> >
<!-- <template slot="append">2</template> --> <!-- <template slot="append">2</template> -->
@@ -248,6 +253,7 @@
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
:disabled="readingTaskState === 2"
action action
:accept="question.FileType" :accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount" :limit="question.ImageCount === 0 ? 100 : question.ImageCount"
@@ -258,7 +264,7 @@
:file-list="fileList" :file-list="fileList"
:class="{disabled:question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}" :class="{disabled:question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
> >
<el-button slot="default" class="el-icon-plus"> <el-button slot="default" class="el-icon-plus" v-if="readingTaskState < 2">
{{this.$t('common:button:upload')}} {{this.$t('common:button:upload')}}
</el-button> </el-button>
</el-upload> </el-upload>
@@ -337,16 +343,37 @@
</el-button> </el-button>
</template> </template>
</base-model> </base-model>
<!-- 预览文件 -->
<el-dialog
v-if="previewVisible"
:visible.sync="previewVisible"
:title="$t('common:button:preview')"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<div
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<PreviewFile
v-if="previewVisible"
:file-path="currentPath"
:file-type="currentType"
/>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { uploadReadingAnswerImage, getTrialOrganList, deleteReadingRowAnswer, getCustomTableQuestionPreview, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials' import { uploadReadingAnswerImage, getTrialOrganList, deleteReadingRowAnswer, getCustomTableQuestionPreview, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials'
import QuestionTableFormItem from './CustomizeQuestionTableFormItem' import QuestionTableFormItem from './CustomizeQuestionTableFormItem'
import BaseModel from '@/components/BaseModel' import BaseModel from '@/components/BaseModel'
import PreviewFile from '@/components/PreviewFile/index'
import DicomEvent from './../components/DicomEvent' import DicomEvent from './../components/DicomEvent'
export default { export default {
name: 'CustomizeQuestionFormItem', name: 'CustomizeQuestionFormItem',
components: { QuestionTableFormItem, BaseModel }, components: { QuestionTableFormItem, BaseModel, PreviewFile },
props: { props: {
IsBaseline: { IsBaseline: {
type: Boolean, type: Boolean,
@@ -398,7 +425,10 @@ export default {
RowId: null, RowId: null,
digitPlaces: 2, digitPlaces: 2,
CalculationTabelList: [], CalculationTabelList: [],
classArr: [] classArr: [],
previewVisible: false,
currentPath: '',
currentType: ''
} }
}, },
watch: { watch: {
@@ -422,6 +452,13 @@ export default {
this.formItemNumberChange(this.question.Id, false) this.formItemNumberChange(this.question.Id, false)
} }
}, },
readingTaskState: {
deep: true,
immediate: true,
handler(v, oldv) {
console.log(v)
}
}
}, },
mounted() { mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
@@ -547,6 +584,7 @@ export default {
this.$set(this.QuestionsForm, obj.key, null) this.$set(this.QuestionsForm, obj.key, null)
}, },
handleSave() { handleSave() {
console.log('tableQsForm')
this.$refs.tableQsForm.validate(valid => { this.$refs.tableQsForm.validate(valid => {
if (!valid) return if (!valid) return
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
@@ -612,6 +650,7 @@ export default {
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId) var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
this.AnswersList.splice(index, 1, this.QuestionsForm) this.AnswersList.splice(index, 1, this.QuestionsForm)
} }
console.log({key: this.question.Id, val: this.AnswersList, question: this.question})
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question}) this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
this.formItemNumberChange(this.question.Id, true) this.formItemNumberChange(this.question.Id, true)
this.addOrEdit.visible = false this.addOrEdit.visible = false
@@ -935,7 +974,8 @@ export default {
let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file) let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) }) this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) })
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question }) this.$emit("setFormItemData", { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '')
loading.close() loading.close()
// uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => { // uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// if (res.IsSuccess) { // if (res.IsSuccess) {
@@ -972,7 +1012,10 @@ export default {
var suffix = file.url.substring(file.url.lastIndexOf(".")+1) var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
suffix = suffix ? suffix.toLowerCase() : '' suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){ if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank') // window.open(this.OSSclientConfig.basePath + file.url,'_blank')
this.currentPath = file.url
this.currentType = suffix
this.previewVisible = true
}else{ }else{
this.imageUrl = this.OSSclientConfig.basePath + file.url this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true this.imgVisible = true
@@ -986,8 +1029,12 @@ export default {
if (file && file.status === "success") { if (file && file.status === "success") {
this.imageUrl = '' this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1) this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.fileList.forEach((i,index)=>{
i.name = `${this.$t('trials:emailManageCfg:title:fileName')}${index+ 1}`
})
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1) this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '')
} }
} }
} }
@@ -77,6 +77,7 @@ export default {
methods: { methods: {
handleSave(isMsg) { handleSave(isMsg) {
return new Promise(resolve => { return new Promise(resolve => {
console.log('handleSave')
this.$refs['questions'].validate((valid) => { this.$refs['questions'].validate((valid) => {
if (!valid) { if (!valid) {
resolve(false) resolve(false)
@@ -232,7 +233,9 @@ export default {
this.questionForm[v] = '' this.questionForm[v] = ''
}, },
setFormItemData(obj) { setFormItemData(obj) {
console.log('setFormItemData', obj)
this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val))) this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
console.log(this.questionForm)
this.classArr.map(i=>{ this.classArr.map(i=>{
if (i.triggerId === obj.key) { if (i.triggerId === obj.key) {
let answer = null let answer = null
@@ -194,7 +194,7 @@
</template> </template>
</template> </template>
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'"> <template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'">
<CustomizeReportPageUpload <customize-report-page-upload
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)" v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visitTaskId="visitTaskId" :visitTaskId="visitTaskId"
:question="scope.row" :question="scope.row"
@@ -202,8 +202,8 @@
:readingTaskState="readingTaskState" :readingTaskState="readingTaskState"
:initUrl="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]" :initUrl="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}" @setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
></CustomizeReportPageUpload> ></customize-report-page-upload>
<CustomizeReportPageUpload <customize-report-page-upload
v-else-if="scope.row.Type==='upload'" v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId" :visitTaskId="visitTaskId"
:question="scope.row" :question="scope.row"
@@ -211,25 +211,25 @@
:readingTaskState="readingTaskState" :readingTaskState="readingTaskState"
:initUrl="questionForm[scope.row.QuestionId]" :initUrl="questionForm[scope.row.QuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}" @setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
></CustomizeReportPageUpload> ></customize-report-page-upload>
</template> </template>
<template v-else-if="scope.row.Type === 'upload'"> <template v-else-if="scope.row.Type === 'upload'">
<CustomizeReportPageUpload <customize-report-page-upload
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)" v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visitTaskId="visitTaskId" :visitTaskId="visitTaskId"
:question="scope.row" :question="scope.row"
:task="task" :task="task"
:readingTaskState="readingTaskState" :readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]" :initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload> ></customize-report-page-upload>
<CustomizeReportPageUpload <customize-report-page-upload
v-else-if="scope.row.Type==='upload'" v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId" :visitTaskId="visitTaskId"
:question="scope.row" :question="scope.row"
:task="task" :task="task"
:readingTaskState="readingTaskState" :readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]" :initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload> ></customize-report-page-upload>
</template> </template>
<template v-else-if="scope.row.QuestionType=== 22"> <template v-else-if="scope.row.QuestionType=== 22">
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }} {{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
@@ -276,6 +276,7 @@
<script> <script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials' import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading' import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './../components/DicomEvent' import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload' import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
@@ -736,15 +737,16 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
try {
var params = { var params = {
data: { data: {
visitTaskId: this.visitTaskId visitTaskId: this.visitTaskId
}, },
signInfo: signInfo signInfo: signInfo
} }
submitDicomVisitTask(params).then(res => { let res = await submitDicomVisitTask(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) { if (this.$refs['signForm']) {
@@ -752,41 +754,36 @@ export default {
} }
this.signVisible = false this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
// //
this.readingTaskState = 2 this.readingTaskState = 2
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 }) store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
DicomEvent.$emit('setReadingState', 2) DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location) window.opener.postMessage('refreshTaskList', window.location)
const res = await getAutoCutNextTask()
let isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), { this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning', type: 'warning',
distinguishCancelAndClose: true distinguishCancelAndClose: true
}) })
.then(() => { .then(() => {
// var token = getToken()
// var subjectCode = this.$router.currentRoute.query.subjectCode
// var subjectId = this.$router.currentRoute.query.subjectId
// var trialId = this.$router.currentRoute.query.trialId
// this.$router.push({
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
// })
// DicomEvent.$emit('getNextTask')
window.location.reload() window.location.reload()
}) })
.catch(action => { .catch(action => {
}) })
} }
}
this.loading = false this.loading = false
}).catch(() => { } catch(e) {
this.loading = false this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) { if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
} }
}) }
}, },
previewDicoms(task) { previewDicoms(task) {
var token = getToken() var token = getToken()
@@ -19,12 +19,20 @@
class="dicom-desc" class="dicom-desc"
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;" style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
> >
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
<div> <div>
<span>{{ study.StudyCode }} {{ study.Description }}</span> <div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span> <span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span>{{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" v-else>
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName">
{{study.StudyName}}
</span>
<div>{{ study.Modalities }} ({{ study.SeriesCount }})</div>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" :title="study.Description">{{ study.Description }}</div>
</div> </div>
</el-tooltip>
</div> </div>
</template> </template>
@@ -212,7 +220,8 @@ export default {
srDialogVisible: false, srDialogVisible: false,
srInfo: {}, srInfo: {},
digitPlaces: 2, digitPlaces: 2,
visitTaskIdx: -1 visitTaskIdx: -1,
taskInfo: null
} }
}, },
@@ -250,6 +259,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode') this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => { DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
@@ -339,6 +339,7 @@ export default {
localStorage.setItem('CriterionType', res.Result.CriterionType) localStorage.setItem('CriterionType', res.Result.CriterionType)
localStorage.setItem('digitPlaces', res.Result.DigitPlaces) localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback) localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
this.readingCategory = res.Result.ReadingCategory this.readingCategory = res.Result.ReadingCategory
this.questionFormChangeState = false this.questionFormChangeState = false
this.questionFormChangeNum = 0 this.questionFormChangeNum = 0
@@ -66,7 +66,8 @@ export default function(evt) {
draw(context, context => { draw(context, context => {
// Configurable shadow // Configurable shadow
setShadow(context, this.configuration) setShadow(context, this.configuration)
// Draw perpendicular line
const strokeWidth = lineWidth
const { const {
start, start,
end, end,
@@ -86,9 +87,6 @@ export default function(evt) {
// Draw the measurement line // Draw the measurement line
drawLine(context, element, start, end, lineOptions) drawLine(context, element, start, end, lineOptions)
// Draw perpendicular line
const strokeWidth = lineWidth
updatePerpendicularLineHandles(eventData, data) updatePerpendicularLineHandles(eventData, data)
drawLine( drawLine(
@@ -10,9 +10,13 @@ const getNewContext = cornerstoneTools.import('drawing/getNewContext')
const draw = cornerstoneTools.import('drawing/draw') const draw = cornerstoneTools.import('drawing/draw')
const drawHandles = cornerstoneTools.import('drawing/drawHandles') const drawHandles = cornerstoneTools.import('drawing/drawHandles')
const drawTextBox = cornerstoneTools.import('drawing/drawTextBox') const drawTextBox = cornerstoneTools.import('drawing/drawTextBox')
const drawLink = cornerstoneTools.import('drawing/drawLink')
const drawLinkedTextBox = cornerstoneTools.import('drawing/drawLinkedTextBox')
// Utilities // Utilities
const getRGBPixels = cornerstoneTools.import('util/getRGBPixels') const getRGBPixels = cornerstoneTools.import('util/getRGBPixels')
const calculateSUV = cornerstoneTools.import('util/calculateSUV') const calculateSUV = cornerstoneTools.import('util/calculateSUV')
const getROITextBoxCoords = cornerstoneTools.import('util/getROITextBoxCoords')
// import { probeCursor } from '../cursors/index.js'; // import { probeCursor } from '../cursors/index.js';
// import { getLogger } from '../../util/logger.js'; // import { getLogger } from '../../util/logger.js';
const throttle = cornerstoneTools.import('util/throttle') const throttle = cornerstoneTools.import('util/throttle')
@@ -20,6 +24,8 @@ const getModule = cornerstoneTools.getModule
const getPixelSpacing = cornerstoneTools.import('util/getPixelSpacing') const getPixelSpacing = cornerstoneTools.import('util/getPixelSpacing')
// import numbersWithCommas from './../../util/numbersWithCommas.js'; // import numbersWithCommas from './../../util/numbersWithCommas.js';
const numbersWithCommas = cornerstoneTools.import('util/numbersWithCommas') const numbersWithCommas = cornerstoneTools.import('util/numbersWithCommas')
const clipBoxToDisplayedArea = cornerstoneTools.import('util/clip')
// const logger = getLogger('tools:annotation:ProbeTool'); // const logger = getLogger('tools:annotation:ProbeTool');
import calculateEllipseStatistics from './calculateEllipseStatistics' import calculateEllipseStatistics from './calculateEllipseStatistics'
import getCircleCoords from './getCircleCoords' import getCircleCoords from './getCircleCoords'
@@ -31,6 +37,19 @@ import getCircleCoords from './getCircleCoords'
* desired position. * desired position.
* @extends Tools.Base.BaseAnnotationTool * @extends Tools.Base.BaseAnnotationTool
*/ */
const getHandle = (x, y, index, extraAttributes = {}) =>
Object.assign(
{
x,
y,
index,
drawnIndependently: false,
allowedOutsideImage: false,
highlight: true,
active: false
},
extraAttributes
)
export default class ProbeTool extends cornerstoneTools.ProbeTool { export default class ProbeTool extends cornerstoneTools.ProbeTool {
constructor(props = {}) { constructor(props = {}) {
const defaultProps = { const defaultProps = {
@@ -64,6 +83,7 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
return; return;
} }
const { x, y } = eventData.currentPoints.image
return { return {
visible: true, visible: true,
@@ -84,6 +104,23 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
active: true, active: true,
radius: 0 radius: 0
}, },
// textBox: {
// active: false,
// hasMoved: false,
// movesIndependently: false,
// drawnIndependently: true,
// allowedOutsideImage: true,
// hasBoundingBox: true,
// }
textBox: getHandle(x, y - 30, null, {
highlight: false,
hasMoved: true,
active: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
})
}, },
}; };
} }
@@ -226,7 +263,7 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
draw(context, context => { draw(context, context => {
const color = toolColors.getColorIfActive(data); const color = toolColors.getColorIfActive(data);
const lineWidth = toolStyle.getToolWidth()
if (this.configuration.drawHandles) { if (this.configuration.drawHandles) {
// Draw the handles // Draw the handles
let radius = getCanvasRadius(data.handles, fixedRadius, element, pixelSpacing) let radius = getCanvasRadius(data.handles, fixedRadius, element, pixelSpacing)
@@ -273,6 +310,8 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
} }
let r = getPixelRadius(fixedRadius, pixelSpacing) let r = getPixelRadius(fixedRadius, pixelSpacing)
// Coords for text // Coords for text
if (!data.handles.hasOwnProperty('textBox')) {
const coords = { const coords = {
// Translate the x/y away from the cursor // Translate the x/y away from the cursor
x: data.handles.end.x + r, x: data.handles.end.x + r,
@@ -289,12 +328,115 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
textCoords.y , textCoords.y ,
color color
); );
// drawTextBox(context, '', textCoords.x, textCoords.y, color); return
}
// const handles = {
// start: {
// x: data.handles.end.x,
// y: data.handles.end.y
// },
// end: {
// x: data.handles.end.x + r,
// y: data.handles.end.y
// }
// }
let xOffset = 0
if (data.remark && !isNaN(parseInt(data.remark.slice(-1)))) {
let i = parseInt(data.remark.slice(-1))
if (i === 1) {
xOffset = -60
} else if (i === 2) {
xOffset = 0
} else if (i=== 3) {
xOffset = 0
}
}
// const xOffset = -30
const textBoxAnchorPoints = handles => [
handles.end
]
_drawLinkedTextBox(
context,
element,
data.handles.textBox,
textLines,
data.handles,
color,
lineWidth,
xOffset,
false
)
} }
}); });
} }
} }
} }
function _drawLinkedTextBox(
context,
element,
textBox,
text,
handles,
color,
lineWidth,
xOffset,
yCenter) {
const { pixelToCanvas } = external.cornerstone;
// Convert the textbox Image coordinates into Canvas coordinates
const textCoords = pixelToCanvas(element, textBox);
if (xOffset) {
textCoords.x += xOffset;
}
const options = {
centering: {
x: false,
y: yCenter,
},
};
options.displacer = box => clipBoxToDisplayedArea(element, box);
// Draw the text box
textBox.boundingBox = drawTextBox(
context,
text,
textCoords.x,
textCoords.y,
color,
options
);
if (textBox.hasMoved) {
// Identify the possible anchor points for the tool -> text line
let arr = [
{
x: handles.end.x,
y: handles.end.y
},
{
x: handles.end.x,
y: handles.end.y
}
]
const linkAnchorPoints = arr.map(h =>
pixelToCanvas(element, h)
);
// Draw dashed link line between tool and text
drawLink(
linkAnchorPoints,
textCoords,
textBox.boundingBox,
context,
color,
lineWidth
);
}
}
function _getUnit(modality, showHounsfieldUnits) { function _getUnit(modality, showHounsfieldUnits) {
return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : ''; return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';
} }
@@ -5,28 +5,28 @@
<!-- 全局阅片 --> <!-- 全局阅片 -->
<global-review <global-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 2" v-else-if="taskInfo && taskInfo.ReadingCategory=== 2"
:trialId="trialId" :trial-id="trialId"
:subjectId="taskInfo.SubjectId" :subject-id="taskInfo.SubjectId"
:visitTaskId="taskInfo.VisitTaskId" :visit-task-id="taskInfo.VisitTaskId"
:readingCategory="taskInfo.ReadingCategory" :reading-category="taskInfo.ReadingCategory"
:subjectCode="taskInfo.SubjectCode" :subject-code="taskInfo.SubjectCode"
:taskBlindName="taskInfo.TaskBlindName" :task-blind-name="taskInfo.TaskBlindName"
:isReadingShowSubjectInfo="taskInfo.IsReadingShowSubjectInfo" :is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:isReadingShowPreviousResults="taskInfo.IsReadingShowPreviousResults" :is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:isExistsClinicalData="taskInfo.IsExistsClinicalData" :is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/> />
<!-- 裁判阅片 --> <!-- 裁判阅片 -->
<ad-review <ad-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 4" v-else-if="taskInfo && taskInfo.ReadingCategory=== 4"
:trialId="trialId" :trial-id="trialId"
:subjectId="taskInfo.SubjectId" :subject-id="taskInfo.SubjectId"
:visitTaskId="taskInfo.VisitTaskId" :visit-task-id="taskInfo.VisitTaskId"
:readingCategory="taskInfo.ReadingCategory" :reading-category="taskInfo.ReadingCategory"
:subjectCode="taskInfo.SubjectCode" :subject-code="taskInfo.SubjectCode"
:taskBlindName="taskInfo.TaskBlindName" :task-blind-name="taskInfo.TaskBlindName"
:isReadingShowSubjectInfo="taskInfo.IsReadingShowSubjectInfo" :is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:isReadingShowPreviousResults="taskInfo.IsReadingShowPreviousResults" :is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:isExistsClinicalData="taskInfo.IsExistsClinicalData" :is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/> />
<!-- 肿瘤学阅片 --> <!-- 肿瘤学阅片 -->
<!-- <oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" /> --> <!-- <oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" /> -->
@@ -134,7 +134,7 @@ export default {
} catch (e) { } catch (e) {
this.loading = false this.loading = false
} }
}, }
} }
} }
</script> </script>
@@ -148,7 +148,7 @@ export default {
height:80%; height:80%;
} }
::v-deep .el-dialog__body{ ::v-deep .el-dialog__body{
padding: 20px 20px 0 20px; padding: 10px;
height: calc(100% - 70px); height: calc(100% - 70px);
} }
.el-dialog__header{ .el-dialog__header{
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,173 @@
<template>
<div>
<el-upload
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
:http-request="uploadScreenshot"
list-type="picture-card"
:on-remove="handleRemove"
:file-list="fileList"
:class="{disabled:readingTaskState >= 2 || (question.ImageCount === 0 ? false : fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}"
:disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))"
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
>
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
crossOrigin="anonymous"
alt=""
style="max-width: 100%; max-height: 100%"
/>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload>
</div>
</template>
<script>
import { uploadReadingAnswerImage, getTrialOrganList, getCustomTableQuestionPreview } from '@/api/trials'
export default {
name: "CustomizeReportPageUpload",
props: {
task: {
Type: Object,
required: true
},
question: {
Type: Object,
required: true
},
visitTaskId: {
type: String,
required: true
},
readingTaskState: {
type: Number,
required: true
},
initUrl: {
type: String,
default: ''
}
},
data () {
return {
imgVisible: false,
imageUrl: null,
accept: '.png,.jpg,.jpeg',
fileList: [],
}
},
mounted() {
this.urls = this.initUrl === '' ? [] : this.initUrl.split('|')
console.log(this.visitTaskId, this.urls)
this.fileList = []
this.urls.map(url => {
this.fileList.push({ name: '', url: `${url}` })
})
// console.log(this.fileList)
},
methods: {
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
}
},
async uploadScreenshot(param) {
if (!this.visitTaskId) return
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
fullscreen: false,
lock: true,
text: 'Loading',
spinner: 'el-icon-loading'
})
var trialId = this.$route.query.trialId
var subjectId = this.$route.query.trialId
var file = await this.fileToBlob(param.file)
const res = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${param.file.name}`, file)
console.log(res)
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)})
this.urls.push(this.$getObjectName(res.url))
this.$emit('setImageUrl', this.urls.length > 0 ? this.urls.join('|') : '')
loading.close()
},
handleBeforeUpload(file) {
//
if (this.checkFileSuffix(file.name)) {
// this.fileList = []
return true
} else {
// this.$alert(` ${this.accept} `)
let msg = this.$t(
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg)
return false
}
},
//
handlePictureCardPreview(file) {
var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true
this.$refs[file.url].$viewer.show()
}
},
//
handleRemove(file, fileList) {
this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
},
}
}
</script>
<style lang="scss" scoped>
.disabled{
::v-deep .el-upload--picture-card {
display: none;
}
}
</style>
@@ -1,12 +1,13 @@
<template> <template>
<div v-loading="loading" class="ecrf-list-container"> <div v-loading="loading" class="ecrf-list-container">
<el-form <el-form
v-if="taskInfo"
ref="questions" ref="questions"
size="small" size="small"
:model="questionForm" :model="questionForm"
class="ecrf-form" class="ecrf-form"
> >
<FormItem <!-- <FormItem
v-for="question of questions" v-for="question of questions"
:key="question.Id" :key="question.Id"
:question="question" :question="question"
@@ -16,6 +17,19 @@
:calculation-list="calculationList" :calculation-list="calculationList"
@setFormItemData="setFormItemData" @setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData" @resetFormItemData="resetFormItemData"
/> -->
<QuestionFormItem
v-for="question of questions"
:key="question.Id"
:visit-task-id="visitTaskId"
:question="question"
:question-form="questionForm"
:reading-task-state="readingTaskState"
:criterion-id="criterionId"
:calculation-list="calculationList"
:is-baseline="isBaseline"
@resetFormItemData="resetFormItemData"
@setFormItemData="setFormItemData"
/> />
<el-form-item v-if="readingTaskState < 2"> <el-form-item v-if="readingTaskState < 2">
@@ -53,17 +67,18 @@
<script> <script>
import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials' import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading' import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import store from '@/store' import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import FormItem from './FormItem' // import FormItem from './FormItem'
import QuestionFormItem from '@/views/trials/trials-panel/reading/dicoms/customize/CustomizeQuestionFormItem'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
export default { export default {
name: 'EcrfList', name: 'EcrfList',
components: { components: {
FormItem, QuestionFormItem,
SignForm SignForm
}, },
props: { props: {
@@ -88,7 +103,8 @@ export default {
activeName: 0, activeName: 0,
classArr: [], classArr: [],
calculationList: [], calculationList: [],
taskInfo: null taskInfo: null,
isBaseline: false
} }
}, },
computed: { computed: {
@@ -109,6 +125,7 @@ export default {
currentTaskState: { currentTaskState: {
immediate: true, immediate: true,
handler(state) { handler(state) {
console.log(state)
if (state === 2) { if (state === 2) {
this.readingTaskState = 2 this.readingTaskState = 2
} }
@@ -117,45 +134,65 @@ export default {
}, },
mounted() { mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo')) this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.isBaseline = this.taskInfo.IsBaseLine
}, },
methods: { methods: {
async getQuestions() { async getQuestions(visitTaskId) {
this.loading = true this.loading = true
try { try {
const param = { const param = {
readingQuestionCriterionTrialId: this.criterionId,
visitTaskId: this.visitTaskId visitTaskId: this.visitTaskId
} }
const res = await getTrialReadingQuestion(param) const res = await getCustomTableQuestionAnswer(param)
if (res.IsSuccess) { if (res.IsSuccess) {
this.readingTaskState = res.OtherInfo.readingTaskState this.readingTaskState = res.OtherInfo.ReadingTaskState
res.Result.SinglePage.map((v) => { res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null) this.$set(this.questionForm, v.Id, v.Answer)
}
if (v.Type === 'table' || v.Type === 'basicTable') {
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
} }
if (v.Type === 'class') { if (v.Type === 'class') {
this.classArr.push({ triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType }) this.classArr.push({ triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType })
} }
if (v.Type === 'number') {
this.$set(this.questionForm, v.Id, v.Answer === '' ? '' : parseFloat(v.Answer).toFixed(this.digitPlaces))
}
if (v.Childrens.length > 0) { if (v.Childrens.length > 0) {
this.setChild(v.Childrens) this.setChild(v.Childrens)
} }
}) })
this.questions = res.Result.SinglePage this.questions = res.Result.SinglePage
}
this.loading = false this.loading = false
}
} catch (e) { } catch (e) {
console.log(e)
this.loading = false this.loading = false
} }
}, },
setChild(obj) { setChild(obj) {
obj.forEach(i => { obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null) this.$set(this.questionForm, i.Id, i.Answer)
}
if (i.Type === 'table' || i.Type === 'basicTable') {
i.TableQuestions.Questions.forEach(o => {
if (o.Type === 'number') {
i.TableQuestions.Answers.forEach((ite, index) => {
this.$set(i.TableQuestions.Answers[index], o.Id, i.TableQuestions.Answers[index][o.Id] ? parseFloat(i.TableQuestions.Answers[index][o.Id]).toFixed(this.digitPlaces) : null)
})
}
})
this.$set(this.questionForm, i.Id, i.TableQuestions.Answers)
} }
if (i.Type === 'class') { if (i.Type === 'class') {
this.classArr.push({ triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType }) this.classArr.push({ triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType })
} }
if (i.Type === 'number') {
this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(this.digitPlaces))
}
if (i.Childrens && i.Childrens.length > 0) { if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens) this.setChild(i.Childrens)
} }
@@ -169,26 +206,28 @@ export default {
console.log(e) console.log(e)
} }
}, },
async handleSave() { async handleSave(isMsg) {
const valid = await this.$refs['questions'].validate() const valid = await this.$refs['questions'].validate()
if (!valid) return if (!valid) return
this.loading = true this.loading = true
const answers = []
for (const k in this.questionForm) {
answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] })
}
const params = {
trialId: this.trialId,
visitTaskId: this.visitTaskId,
readingQuestionCriterionTrialId: this.criterionId,
answerList: answers
}
try { try {
const res = await saveVisitTaskQuestions(params) var answers = []
for (const k in this.questionForm) {
if (this.questionForm[k] instanceof Array) {} else {
answers.push({ id: k, answer: this.questionForm[k] })
}
}
var params = {
visitTaskId: this.visitTaskId,
answers: answers
}
const res = await changeDicomReadingQuestionAnswer(params)
if (res.IsSuccess) { if (res.IsSuccess) {
if (isMsg) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
} }
this.loading = false this.loading = false
}
} catch (e) { } catch (e) {
this.loading = false this.loading = false
} }
@@ -314,5 +353,50 @@ export default {
} }
} }
::v-deep .el-table,
.el-table__expanded-cell {
background-color: #000;
color: #fff;
border-color: #444444;
}
::v-deep .el-table th,
.el-table tr {
background-color: #000;
color: #fff;
border-color: #444444;
}
::v-deep .el-table__body tr > td {
background-color: #000 !important;
color: #fff;
border-color: #444444;
}
::v-deep .el-table__body tr:hover > td {
background-color: #858282 !important;
color: #fff;
border-color: #444444;
}
::v-deep .el-table--border th.gutter:last-of-type {
border: none;
}
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
} }
</style> </style>
@@ -2,6 +2,7 @@
<div class="none-dicom-viewer"> <div class="none-dicom-viewer">
<!-- tools --> <!-- tools -->
<div class="tools-wrapper"> <div class="tools-wrapper">
<div class="tools-left">
<!-- 布局 --> <!-- 布局 -->
<div class="tool-item" :title="$t('trials:reading:button:layout')"> <div class="tool-item" :title="$t('trials:reading:button:layout')">
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand">
@@ -63,6 +64,14 @@
> >
<svg-icon icon-class="polygon" class="svg-icon" /> <svg-icon icon-class="polygon" class="svg-icon" />
</div> </div>
<!-- <div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'SplineROITool' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:SplineROITool')"
@click.prevent="setAnnotateToolActive('SplineROITool')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div> -->
<div <div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']" :class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:Eraser')" :title="$t('trials:dicom-show:Eraser')"
@@ -70,13 +79,13 @@
> >
<svg-icon icon-class="clear" class="svg-icon" /> <svg-icon icon-class="clear" class="svg-icon" />
</div> </div>
<!-- <div <div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Length' ? 'tool-item-active' : '']" :class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Length' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:length')" :title="$t('trials:nondicom-show:scale')"
@click.prevent="setAnnotateToolActive('Length')" @click.prevent="setAnnotateToolActive('Length')"
> >
<svg-icon icon-class="length" class="svg-icon" /> <svg-icon icon-class="length" class="svg-icon" />
</div> --> </div>
<!-- 截图 --> <!-- 截图 -->
<!-- <div <!-- <div
class="tool-item" class="tool-item"
@@ -94,6 +103,11 @@
<svg-icon icon-class="refresh" class="svg-icon" /> <svg-icon icon-class="refresh" class="svg-icon" />
</div> </div>
</div> </div>
<div>
<el-button type="text" @click="previewConfig">{{ $t('trials:reading:button:customCfg') }}</el-button>
</div>
</div>
<!-- viewports --> <!-- viewports -->
<div class="viewports-wrapper"> <div class="viewports-wrapper">
<div class="grid-container" :style="gridStyle"> <div class="grid-container" :style="gridStyle">
@@ -153,7 +167,7 @@
</div> </div>
</div> </div>
<div :ref="`sliderBox-${index}`" class="right-slider-box" @click.stop="clickSlider($event, index)"> <div :ref="`sliderBox-${index}`" class="right-slider-box" @click.stop="clickSlider($event, index)">
<div :style="{top: v.height + '%'}" class="slider" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event, index)"/> <div :style="{top: v.height + '%'}" class="slider" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event, index)" />
</div> </div>
</div> </div>
<div v-show="v.fileType === 'application/pdf' && fullScreenIndex === null " class="content flex_col"> <div v-show="v.fileType === 'application/pdf' && fullScreenIndex === null " class="content flex_col">
@@ -209,6 +223,36 @@
</div> </div>
</div> </div>
</div> </div>
<el-dialog
:title="$t('trials:noneDicom:message:msg2')"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
width="400px"
>
<el-form ref="lengthForm" :model="form" :rules="rules">
<el-form-item label="" prop="length">
<el-input v-model="form.length" type="number">
<template slot="append">mm</template>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="saveForm">{{ $t('common:button:save') }}</el-button>
</span>
</el-dialog>
<el-dialog
v-if="personalConfigDialog.visible"
:visible.sync="personalConfigDialog.visible"
:close-on-click-modal="false"
:title="personalConfigDialog.title"
width="600px"
>
<Others />
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
@@ -230,6 +274,7 @@ import hardcodedMetaDataProvider from './../js/hardcodedMetaDataProvider'
import registerWebImageLoader from './../js/registerWebImageLoader' import registerWebImageLoader from './../js/registerWebImageLoader'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import store from '@/store' import store from '@/store'
import Others from '@/views/trials/trials-panel/reading/dicoms/components/Others'
const { ViewportType } = Enums const { ViewportType } = Enums
const renderingEngineId = 'myRenderingEngine' const renderingEngineId = 'myRenderingEngine'
const { const {
@@ -242,6 +287,7 @@ const {
ArrowAnnotateTool, ArrowAnnotateTool,
RectangleROITool, RectangleROITool,
PlanarFreehandROITool, PlanarFreehandROITool,
SplineROITool,
EraserTool, EraserTool,
LengthTool LengthTool
// cursors // cursors
@@ -249,12 +295,19 @@ const {
const { MouseBindings, Events: toolsEvents } = csToolsEnums const { MouseBindings, Events: toolsEvents } = csToolsEnums
export default { export default {
name: 'ImageViewer', name: 'ImageViewer',
components: { Others },
props: { props: {
relatedStudyInfo: { relatedStudyInfo: {
type: Object, type: Object,
default() { default() {
return {} return {}
} }
},
psArr: {
type: Array,
default() {
return []
}
} }
}, },
data() { data() {
@@ -272,7 +325,20 @@ export default {
activeTool: '', activeTool: '',
readingTaskState: 2, readingTaskState: 2,
renderHistoryAnnotationTaskIds: [], renderHistoryAnnotationTaskIds: [],
imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'] imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'],
digitPlaces: 2,
dialogVisible: false,
personalConfigDialog: { visible: false, title: this.$t('trials:reading:button:customCfg') }, //
form: {
length: null,
annotationObj: {}
},
rules: {
length: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
{ pattern: /^\d+$/, message: this.$t('trials:noneDicom:message:msg3'), trigger: ['blur', 'change'] }
]
}
} }
}, },
computed: { computed: {
@@ -344,6 +410,8 @@ export default {
isMove: false, isMove: false,
height: 0 height: 0
})) }))
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.initLoader() this.initLoader()
window.addEventListener('message', this.handleIframeMessage) window.addEventListener('message', this.handleIframeMessage)
}, },
@@ -413,10 +481,10 @@ export default {
cornerstoneTools.addTool(ArrowAnnotateTool) cornerstoneTools.addTool(ArrowAnnotateTool)
cornerstoneTools.addTool(RectangleROITool) cornerstoneTools.addTool(RectangleROITool)
cornerstoneTools.addTool(PlanarFreehandROITool) cornerstoneTools.addTool(PlanarFreehandROITool)
cornerstoneTools.addTool(SplineROITool)
cornerstoneTools.addTool(EraserTool) cornerstoneTools.addTool(EraserTool)
cornerstoneTools.addTool(LengthTool) cornerstoneTools.addTool(LengthTool)
viewportIds.forEach((viewportId, i) => { viewportIds.forEach((viewportId, i) => {
const toolGroupId = `canvas-${i}` const toolGroupId = `canvas-${i}`
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId) const toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
@@ -434,14 +502,25 @@ export default {
return doneChangingTextCallback(await this.customPrompt()) return doneChangingTextCallback(await this.customPrompt())
} }
}) })
toolGroup.addTool(RectangleROITool.toolName) toolGroup.addTool(RectangleROITool.toolName, {
cachedStats: false,
getTextLines: this.getRectangleROIToolTextLines
})
toolGroup.addTool(PlanarFreehandROITool.toolName, { toolGroup.addTool(PlanarFreehandROITool.toolName, {
allowOpenContours: false, allowOpenContours: false,
cachedStats: false cachedStats: false,
getTextLines: this.getPlanarFreehandROIToolTextLines
}) })
// const splineConfig = toolGroup.getToolConfiguration(
// splineToolName,
// 'spline'
// )
toolGroup.addTool(SplineROITool.toolName)
toolGroup.addTool(EraserTool.toolName) toolGroup.addTool(EraserTool.toolName)
toolGroup.addTool(LengthTool.toolName, { toolGroup.addTool(LengthTool.toolName, {
getTextLines: this.getLengthToolTextLines getTextLines: this.getLengthToolTextLines,
cachedStats: false
}) })
toolGroup.setToolActive(StackScrollTool.toolName, { toolGroup.setToolActive(StackScrollTool.toolName, {
@@ -454,11 +533,13 @@ export default {
toolGroup.setToolPassive(ArrowAnnotateTool.toolName) toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
toolGroup.setToolPassive(RectangleROITool.toolName) toolGroup.setToolPassive(RectangleROITool.toolName)
toolGroup.setToolPassive(PlanarFreehandROITool.toolName) toolGroup.setToolPassive(PlanarFreehandROITool.toolName)
toolGroup.setToolPassive(SplineROITool.toolName)
toolGroup.setToolPassive(LengthTool.toolName) toolGroup.setToolPassive(LengthTool.toolName)
} else { } else {
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName) toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
toolGroup.setToolEnabled(RectangleROITool.toolName) toolGroup.setToolEnabled(RectangleROITool.toolName)
toolGroup.setToolEnabled(PlanarFreehandROITool.toolName) toolGroup.setToolEnabled(PlanarFreehandROITool.toolName)
toolGroup.setToolEnabled(SplineROITool.toolName)
toolGroup.setToolEnabled(LengthTool.toolName) toolGroup.setToolEnabled(LengthTool.toolName)
} }
toolGroup.setToolPassive(EraserTool.toolName) toolGroup.setToolPassive(EraserTool.toolName)
@@ -482,17 +563,14 @@ export default {
renderHistoryAnnotations(obj) { renderHistoryAnnotations(obj) {
if (this.renderHistoryAnnotationTaskIds.includes(obj.VisitTaskId)) return if (this.renderHistoryAnnotationTaskIds.includes(obj.VisitTaskId)) return
this.renderHistoryAnnotationTaskIds.push(obj.VisitTaskId) this.renderHistoryAnnotationTaskIds.push(obj.VisitTaskId)
const arr = [] // let arr = []
obj.Annotations.map(i => { obj.Annotations.map(i => {
if (typeof i.MeasureData === 'string') { const annotation = i.MeasureData
const annotation = JSON.parse(i.MeasureData)
annotation.annotationId = i.Id annotation.annotationId = i.Id
arr.push(annotation)
cornerstoneTools.annotation.state.addAnnotation(annotation) cornerstoneTools.annotation.state.addAnnotation(annotation)
if (obj.ReadingTaskState === 2) { if (obj.ReadingTaskState === 2) {
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID) cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
} }
}
}) })
}, },
// //
@@ -588,7 +666,7 @@ export default {
this.rows = parseInt(command.split('*')[0]) this.rows = parseInt(command.split('*')[0])
this.cols = parseInt(command.split('*')[1]) this.cols = parseInt(command.split('*')[1])
if (this.rows === 1 && this.cols === 1) { if (this.rows === 1 && this.cols === 1) {
this.$nextTick(()=>{ this.$nextTick(() => {
this.activeCanvas(0) this.activeCanvas(0)
}) })
} }
@@ -726,6 +804,19 @@ export default {
if (this.activeTool) { if (this.activeTool) {
toolGroup.setToolPassive(this.activeTool) toolGroup.setToolPassive(this.activeTool)
} }
if (toolName === 'Length') {
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
const imageId = viewport.csImage.imageId
const annotations = cornerstoneTools.annotation.state.getAllAnnotations()
const idx = annotations.findIndex(i => i.metadata.referencedImageId === imageId && i.metadata.toolName === 'Length')
if (idx > -1) {
this.activeTool = ''
//
this.$message.warning(this.$t('trials:noneDicom:message:msg4'))
return
}
}
toolGroup.setToolActive(toolName, { toolGroup.setToolActive(toolName, {
bindings: [{ mouseButton: MouseBindings.Primary }] bindings: [{ mouseButton: MouseBindings.Primary }]
}) })
@@ -772,11 +863,20 @@ export default {
if (!annotation) return if (!annotation) return
if (annotation.annotationId) { if (annotation.annotationId) {
await deleteTrialFileType(annotation.annotationId) await deleteTrialFileType(annotation.annotationId)
} else {
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
} }
const renderingEngine = getRenderingEngine(renderingEngineId) const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`) const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
viewport.render() viewport.render()
// const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
const imageId = annotation.metadata.referencedImageId
const path = imageId.split(`web:${this.OSSclientConfig.basePath}`)[1]
const fileList = this.viewportInfos[i].fileList
const fileIndex = fileList.findIndex(f => f.Path === path)
if (annotation.metadata.toolName === 'Length') {
this.$emit('setPS', { NoneDicomFileId: fileList[fileIndex].Id, Path: fileList[fileIndex].Path, PS: null })
}
}, },
async annotationModifiedListener(e) { async annotationModifiedListener(e) {
console.log('Modified') console.log('Modified')
@@ -793,6 +893,16 @@ export default {
const fileList = this.viewportInfos[i].fileList const fileList = this.viewportInfos[i].fileList
const fileIndex = fileList.findIndex(f => f.Path === path) const fileIndex = fileList.findIndex(f => f.Path === path)
if (fileIndex === -1) return if (fileIndex === -1) return
if (annotation.metadata.toolName === 'Length') {
const value = annotation.data.l
if (value) {
const cachedStats = Object.keys(annotation.data.cachedStats)
const ps = value / annotation.data.cachedStats[cachedStats[0]].length
annotation.data.ps = ps
this.$emit('setPS', { NoneDicomFileId: fileList[fileIndex].Id, Path: fileList[fileIndex].Path, PS: ps })
}
this.setToolsPassive()
}
const params = { const params = {
id: annotation.annotationId, id: annotation.annotationId,
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId, visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
@@ -820,16 +930,22 @@ export default {
const fileIndex = fileList.findIndex(f => f.Path === path) const fileIndex = fileList.findIndex(f => f.Path === path)
if (fileIndex === -1) return if (fileIndex === -1) return
if (annotation.metadata.toolName === 'Length') { if (annotation.metadata.toolName === 'Length') {
const { value } = await this.$prompt('请录入录入物理长度(mm)!') this.form.annotationObj = {
annotation.data.handles.scale = value id: '',
if (!value) { visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
// studyId: this.viewportInfos[i].studyId,
cornerstoneTools.annotation.state.addAnnotation(annotation.annotationUID) noneDicomFileId: fileList[fileIndex].Id,
const renderingEngine = getRenderingEngine(renderingEngineId) path: fileList[fileIndex].Path,
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`) annotation,
viewport.render() fileList,
fileIndex
} }
this.form.length = null
this.dialogVisible = true
this.setToolsPassive()
return
} }
const params = { const params = {
id: '', id: '',
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId, visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
@@ -841,23 +957,143 @@ export default {
const res = await addNoneDicomMark(params) const res = await addNoneDicomMark(params)
annotation.annotationId = res.Result annotation.annotationId = res.Result
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
viewport.render()
// //
// this.$message.success(this.$t('common:message:savedSuccessfully')) // this.$message.success(this.$t('common:message:savedSuccessfully'))
}, },
async saveForm() {
const validate = await this.$refs.lengthForm.validate()
if (!validate) return
const value = this.form.length
const annotation = this.form.annotationObj.annotation
const fileList = this.form.annotationObj.fileList
const fileIndex = this.form.annotationObj.fileIndex
if (value) {
annotation.data.l = parseFloat(value)
const cachedStats = Object.keys(annotation.data.cachedStats)
const ps = parseFloat(value) / annotation.data.cachedStats[cachedStats[0]].length
annotation.data.ps = ps
this.$emit('setPS', { NoneDicomFileId: fileList[fileIndex].Id, Path: fileList[fileIndex].Path, PS: ps })
} else {
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
return
}
const params = {
id: '',
visitTaskId: this.form.annotationObj.visitTaskId,
studyId: this.form.annotationObj.studyId,
noneDicomFileId: this.form.annotationObj.noneDicomFileId,
path: this.form.annotationObj.path,
measureData: JSON.stringify(annotation)
}
const res = await addNoneDicomMark(params)
annotation.annotationId = res.Result
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
viewport.render()
this.dialogVisible = false
},
getLengthToolTextLines(data, targetId) { getLengthToolTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId] const cachedVolumeStats = data.cachedStats[targetId]
const { length, unit } = cachedVolumeStats const { length, unit } = cachedVolumeStats
if (length === undefined || length === null || isNaN(length)) { if (length === undefined || length === null || isNaN(length)) {
return return
} }
if (data.handles.scale === undefined || data.handles.scale === null || isNaN(data.handles.scale)) { if (data.l === undefined || data.l === null || isNaN(data.l)) {
return return
} }
const textLines = [] const textLines = []
textLines.push(`${csUtils.roundNumber(length)} ${unit}`) textLines.push(`P: ${parseFloat(length).toFixed(this.digitPlaces)} ${unit}`)
textLines.push(`${csUtils.roundNumber(data.handles.scale)} mm`) if (data.l) {
textLines.push(`L: ${parseFloat(data.l).toFixed(this.digitPlaces)} mm`)
textLines.push(`PS: ${parseFloat(data.l / length).toFixed(3)} mm/px`)
}
return textLines
},
getPlanarFreehandROIToolTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId]
const {
area,
mean,
stdDev,
// length,
perimeter,
max,
isEmptyArea,
unit,
areaUnit,
modalityUnit
} = cachedVolumeStats || {}
return textLines; const textLines = []
let ps = null
const path = targetId.split(`web:${this.OSSclientConfig.basePath}`)[1]
const i = this.psArr.findIndex(i => i.Path === path)
if (i > -1 && this.psArr[i].PS) {
ps = parseFloat(this.psArr[i].PS).toFixed(3)
}
if (area) {
const areaLine = isEmptyArea
? `Area: Oblique not supported`
: `Area: ${ps ? parseFloat(area * ps * ps).toFixed(this.digitPlaces) : parseFloat(area).toFixed(this.digitPlaces)} ${ps ? 'mm' + '\xb2' : areaUnit}`
textLines.push(areaLine)
}
if (mean) {
textLines.push(`Mean: ${parseFloat(mean).toFixed(this.digitPlaces)} ${modalityUnit}`)
}
if (Number.isFinite(max)) {
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`)
}
if (stdDev) {
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`)
}
if (perimeter) {
if (ps) {
textLines.push(`Perimeter: ${parseFloat(perimeter * ps).toFixed(this.digitPlaces)} mm`)
} else {
textLines.push(`Perimeter: ${parseFloat(perimeter).toFixed(this.digitPlaces)} ${unit}`)
}
}
// if (length) {
// // No need to show length prefix as there is just the single value
// textLines.push(`${csUtils.roundNumber(length)} ${unit}`);
// }
return textLines
},
getRectangleROIToolTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId]
const { area, mean, max, stdDev, areaUnit, modalityUnit } = cachedVolumeStats
if (mean === undefined) {
return
}
const textLines = []
let ps = null
const path = targetId.split(`web:${this.OSSclientConfig.basePath}`)[1]
const i = this.psArr.findIndex(i => i.Path === path)
if (i > -1 && this.psArr[i].PS) {
ps = parseFloat(this.psArr[i].PS).toFixed(3)
}
if (ps) {
textLines.push(`Area: ${parseFloat(area * ps * ps).toFixed(this.digitPlaces)} ${'mm' + '\xb2'}`)
} else {
textLines.push(`Area: ${parseFloat(area).toFixed(this.digitPlaces)} ${areaUnit}`)
}
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`)
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`)
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`)
return textLines
}, },
debounce(callback, delay) { debounce(callback, delay) {
let timerId let timerId
@@ -929,7 +1165,6 @@ export default {
viewport.render() viewport.render()
// } // }
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx }) // this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
}, },
sliderMouseleave(e, index) { sliderMouseleave(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index) const i = this.viewportInfos.findIndex(i => i.index === index)
@@ -964,6 +1199,9 @@ export default {
// //
viewCD(id) { viewCD(id) {
this.$emit('previewCD', id) this.$emit('previewCD', id)
},
previewConfig() {
this.personalConfigDialog.visible = true
} }
} }
} }
@@ -978,11 +1216,17 @@ export default {
.tools-wrapper { .tools-wrapper {
height: 50px; height: 50px;
display: flex; display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center; align-items: center;
border-bottom: 1px solid #727272; border-bottom: 1px solid #727272;
color: #ddd; color: #ddd;
padding: 0 5px;
.tools-left {
flex: 1;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.tool-item { .tool-item {
padding: 5px; padding: 5px;
margin: 0 5px; margin: 0 5px;
@@ -1101,5 +1345,24 @@ export default {
} }
} }
} }
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
} }
</style> </style>
@@ -305,7 +305,7 @@ export default {
imgVisible: false, imgVisible: false,
imageUrl: '', imageUrl: '',
urls: [], urls: [],
digitPlaces: null digitPlaces: 2
} }
}, },
watch: { watch: {
@@ -51,10 +51,12 @@
<file-viewer <file-viewer
ref="fileViewer" ref="fileViewer"
:related-study-info="relatedStudyInfo" :related-study-info="relatedStudyInfo"
:ps-arr="psArr"
@toggleTaskByViewer="toggleTaskByViewer" @toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask" @toggleTask="toggleTask"
@toggleImage="toggleImage" @toggleImage="toggleImage"
@previewCD="previewCD" @previewCD="previewCD"
@setPS="setPS"
/> />
</div> </div>
<!-- 表单 --> <!-- 表单 -->
@@ -152,7 +154,8 @@ export default {
clinicalDataVisible: false, clinicalDataVisible: false,
isClinicalDataFullscreen: false, isClinicalDataFullscreen: false,
trialId: '', trialId: '',
cdVisitTaskId: '' cdVisitTaskId: '',
psArr: []
} }
}, },
computed: { computed: {
@@ -175,7 +178,6 @@ export default {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo')) this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.trialId = this.$route.query.trialId this.trialId = this.$route.query.trialId
this.getRelatedTask() this.getRelatedTask()
}, },
methods: { methods: {
// //
@@ -249,7 +251,16 @@ export default {
visitTaskId: visitTaskId visitTaskId: visitTaskId
} }
const res = await getNoneDicomMarkListOutDto(params) const res = await getNoneDicomMarkListOutDto(params)
this.$set(this.visitTaskList[visitTaskIdx], 'Annotations', res.Result.NoneDicomMarkList) const arr = res.Result.NoneDicomMarkList.map(i => {
if (typeof i.MeasureData === 'string') {
i.MeasureData = JSON.parse(i.MeasureData)
}
if (i.MeasureData.metadata.toolName === 'Length' && this.psArr.findIndex(p => p.NoneDicomFileId === i.NoneDicomFileId) === -1) {
this.psArr.push({ NoneDicomFileId: i.NoneDicomFileId, Path: i.Path, PS: i.MeasureData.data.ps })
}
return i
})
this.$set(this.visitTaskList[visitTaskIdx], 'Annotations', arr)
this.loading = false this.loading = false
resolve() resolve()
} catch (e) { } catch (e) {
@@ -259,6 +270,14 @@ export default {
} }
}) })
}, },
setPS(obj) {
const i = this.psArr.findIndex(p => p.NoneDicomFileId === obj.NoneDicomFileId)
if (i > -1) {
this.psArr[i].PS = obj.PS
} else {
this.psArr.push(obj)
}
},
// //
toggleTask(taskInfo) { toggleTask(taskInfo) {
this.setActiveTaskVisitId(taskInfo.VisitTaskId) this.setActiveTaskVisitId(taskInfo.VisitTaskId)
@@ -170,6 +170,13 @@
</span> </span>
</div> </div>
</template> </template>
<template v-else-if="scope.row.Type==='upload' && scope.row.Answers[task.VisitTaskId]">
<span v-for="(url,index) in scope.row.Answers[task.VisitTaskId].split('|')" :key="url" style="margin-left: 5px;">
<el-button v-if="scope.row.Answers[task.VisitTaskId]" type="text" @click="preview(url)">
{{ `${$t('trials:noneDicom:title:attachment')}${index + 1}` }}
</el-button>
</span>
</template>
<template v-else-if="scope.row.DictionaryCode"> <template v-else-if="scope.row.DictionaryCode">
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }} {{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
</template> </template>
@@ -206,19 +213,41 @@
</div> </div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" /> <SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog> </el-dialog>
<!-- 预览文件 -->
<el-dialog
v-if="previewVisible"
:visible.sync="previewVisible"
:title="$t('common:button:preview')"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<div
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<PreviewFile
v-if="previewVisible"
:file-path="currentPath"
:file-type="currentType"
/>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials' import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading' import { setSkipReadingCache } from '@/api/reading'
// import UploadFile from './UploadFile' import { getAutoCutNextTask } from '@/api/user'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
import PreviewFile from '@/components/PreviewFile/index'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import store from '@/store' import store from '@/store'
export default { export default {
name: 'ReportPage', name: 'CustomizeReportPage',
components: { SignForm }, components: { SignForm, PreviewFile },
data() { data() {
return { return {
trialId: '', trialId: '',
@@ -242,7 +271,10 @@ export default {
tableAnswers: {}, tableAnswers: {},
questionForm: {}, questionForm: {},
questionId: null, questionId: null,
taskInfo: null taskInfo: null,
previewVisible: false,
currentPath: '',
currentType: ''
} }
}, },
watch: { watch: {
@@ -264,7 +296,8 @@ export default {
this.visitTaskId = this.taskInfo.VisitTaskId this.visitTaskId = this.taskInfo.VisitTaskId
this.subjectId = this.taskInfo.SubjectId this.subjectId = this.taskInfo.SubjectId
this.criterionType = this.taskInfo.CriterionType this.criterionType = this.taskInfo.CriterionType
this.digitPlaces = this.taskInfo.DigitPlaces var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.TrialReadingCriterionId = this.taskInfo.TrialReadingCriterionId this.TrialReadingCriterionId = this.taskInfo.TrialReadingCriterionId
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
this.handleResize() this.handleResize()
@@ -351,11 +384,11 @@ export default {
}, },
InitVisitTaskQuestionForm() { InitVisitTaskQuestionForm() {
this.taskQuestions.map((v, i) => { this.taskQuestions.map((v, i) => {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table' && v.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId]) this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
} }
if (v.Type === 'table') { if (v.Type === 'table' || v.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i) var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i)
this.$set(this.questionForm, v.QuestionId, tableAnswers) this.$set(this.questionForm, v.QuestionId, tableAnswers)
// this.$set(v, 'xfIndex', i) // this.$set(v, 'xfIndex', i)
@@ -379,10 +412,10 @@ export default {
}, },
setChild(obj) { setChild(obj) {
obj.forEach((i, index) => { obj.forEach((i, index) => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId]) this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
} }
if (i.Type === 'table') { if (i.Type === 'table' || i.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index) var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
this.$set(this.questionForm, i.QuestionId, tableAnswers) this.$set(this.questionForm, i.QuestionId, tableAnswers)
} }
@@ -397,7 +430,7 @@ export default {
} }
this.$set(this.questionForm, i.QuestionId, val) this.$set(this.questionForm, i.QuestionId, val)
} }
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') { if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table' && i.Type !== 'basicTable') {
this.setChild(i.Childrens) this.setChild(i.Childrens)
} }
}) })
@@ -450,19 +483,18 @@ export default {
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
break break
case 8: case 8:
var arr = [] const arr = []
this.questionForm[o.QuestionId].forEach(q => { this.questionForm[o.QuestionId].forEach(q => {
arr.push(q[o.TableQuestionId]) arr.push(q[o.TableQuestionId])
}) })
num = arr.length === 0 ? 0 : Math.max(...arr) num = arr.length === 0 ? 0 : Math.max(...arr)
break break
case 9: case 9:
// eslint-disable-next-line no-redeclare const arr1 = []
var arr = []
this.questionForm[o.QuestionId].forEach(q => { this.questionForm[o.QuestionId].forEach(q => {
arr.push(q[o.TableQuestionId]) arr1.push(q[o.TableQuestionId])
}) })
num = arr.length === 0 ? 0 : Math.min(...arr) num = arr1.length === 0 ? 0 : Math.min(...arr1)
break break
} }
} else { } else {
@@ -489,11 +521,10 @@ export default {
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
if (rules.ValueType === 2) { if (rules.ValueType === 2) {
num = num * 100 num = num * 100
} }
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(digitPlaces) : '∞' return isNaN(num) ? '' : isFinite(num) ? num.toFixed(this.digitPlaces) : '∞'
}, },
getReportInfo() { getReportInfo() {
this.loading = true this.loading = true
@@ -522,8 +553,6 @@ export default {
questions.forEach((item) => { questions.forEach((item) => {
const obj = item const obj = item
this.$set(obj, 'Answers', {}) this.$set(obj, 'Answers', {})
var digitPlaces = parseInt(localStorage.getItem('digitPlaces')) || 0
item.Answer.forEach(i => { item.Answer.forEach(i => {
if (item.DictionaryCode) { if (item.DictionaryCode) {
this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null) this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null)
@@ -536,7 +565,7 @@ export default {
} else if (item.ValueType === 3) { } else if (item.ValueType === 3) {
val = i.Answer val = i.Answer
} else { } else {
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces) val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(this.digitPlaces)
} }
this.$set(obj.Answers, i.VisitTaskId, val) this.$set(obj.Answers, i.VisitTaskId, val)
} else { } else {
@@ -590,15 +619,16 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
try {
var params = { var params = {
data: { data: {
visitTaskId: this.visitTaskId visitTaskId: this.visitTaskId
}, },
signInfo: signInfo signInfo: signInfo
} }
submitDicomVisitTask(params).then(res => { const res = await submitDicomVisitTask(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) { if (this.$refs['signForm']) {
@@ -606,43 +636,39 @@ export default {
} }
this.signVisible = false this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
// //
this.readingTaskState = 2 this.readingTaskState = 2
this.taskInfo.ReadingTaskState = 2 this.taskInfo.ReadingTaskState = 2
localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo)) localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo))
store.dispatch('noneDicomReview/setCurrentTaskState', 2) store.dispatch('noneDicomReview/setCurrentTaskState', 2)
// DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location) window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), { const res = await getAutoCutNextTask()
const isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
// ''
this.$confirm(this.$t('trials:readingReport:message:msg4'), {
type: 'warning', type: 'warning',
distinguishCancelAndClose: true distinguishCancelAndClose: true
}) })
.then(() => { .then(() => {
// var token = getToken()
// var subjectCode = this.$router.currentRoute.query.subjectCode
// var subjectId = this.$router.currentRoute.query.subjectId
// var trialId = this.$router.currentRoute.query.trialId
// this.$router.push({
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
// })
// DicomEvent.$emit('getNextTask')
window.location.reload() window.location.reload()
}) })
.catch(action => { .catch(action => {
// changeURLStatic('visitTaskId', this.visitTaskId)
}) })
} }
}
this.loading = false this.loading = false
}).catch(() => { } catch (e) {
console.log(e)
this.loading = false this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) { if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
} }
}) }
}, },
previewDicoms(task) { previewDicoms(task) {
var token = getToken() var token = getToken()
@@ -721,6 +747,13 @@ export default {
this.loading = false this.loading = false
console.log(e) console.log(e)
} }
},
//
preview(path) {
this.currentPath = path
const arr = path.split('.')
this.currentType = arr[arr.length - 1]
this.previewVisible = true
} }
} }
} }
@@ -787,6 +820,28 @@ export default {
height: 30px; height: 30px;
line-height: 40px; line-height: 40px;
} }
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
}
::v-deep .el-switch__label{
color:#fff;
} }
::v-deep .el-switch__label.is-active{ ::v-deep .el-switch__label.is-active{
color: #428bca; color: #428bca;
@@ -22,8 +22,12 @@
v-if="!study.IsCriticalSequence" v-if="!study.IsCriticalSequence"
class="dicom-desc" class="dicom-desc"
> >
<div>{{ study.CodeView }}</div> <!-- <div v-if="taskInfo && taskInfo.IsShowStudyName">{{ study.StudyName }}</div> -->
<div> <div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.CodeView">{{ study.CodeView }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.BodyPart">{{ study.BodyPart }}</span> <span :title="study.BodyPart">{{ study.BodyPart }}</span>
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span> <span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
</div> </div>
@@ -164,6 +168,9 @@ export default {
text-align: left; text-align: left;
color: #d0d0d0; color: #d0d0d0;
padding: 2px; padding: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.ps { .ps {
@@ -99,9 +99,9 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.size && scope.row.size > 0 scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: scope.row.Size && scope.row.Size > 0 : scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -324,7 +324,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
handleReset() { handleReset() {
this.searchData = searchDataDefault() this.searchData = searchDataDefault()
@@ -164,7 +164,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.FileSize && scope.row.FileSize > 0 scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -278,6 +278,7 @@
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
:disabled="!scope.row.TrialFileRecord"
v-if="isManage && !viewStatus && hasEdit" v-if="isManage && !viewStatus && hasEdit"
v-model="scope.row.IsAuthorizedView" v-model="scope.row.IsAuthorizedView"
@change="(val) => auth(false, scope.row, val)" @change="(val) => auth(false, scope.row, val)"
@@ -747,7 +748,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
openFile(isFolder = false) { openFile(isFolder = false) {
this.selectData = {} this.selectData = {}
@@ -769,11 +770,12 @@ export default {
}, },
immediate: true, immediate: true,
}, },
rowData: { 'rowData': {
handler() { handler() {
this.DATA = Object.assign({}, this.rowData) this.DATA = Object.assign({}, this.rowData)
}, },
immediate: true, immediate: true,
deep:true
}, },
}, },
created() { created() {
@@ -273,6 +273,12 @@ export default {
this.loading = true this.loading = true
let res = await setAuthorizedView(data) let res = await setAuthorizedView(data)
this.loading = false this.loading = false
if (res.IsSuccess) {
this.$emit('update:rowData', {})
this.$nextTick(() => {
this.$emit('update:rowData', item)
})
}
} catch (err) { } catch (err) {
this.loading = false this.loading = false
item.IsEnable = !item.IsEnable item.IsEnable = !item.IsEnable
@@ -766,11 +766,12 @@ export default {
}, },
immediate: true, immediate: true,
}, },
rowData: { 'rowData': {
handler() { handler() {
this.DATA = Object.assign({}, this.rowData) this.DATA = Object.assign({}, this.rowData)
}, },
immediate: true, immediate: true,
deep:true
}, },
}, },
computed: { computed: {
@@ -690,7 +690,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
openFile(isFolder = false) { openFile(isFolder = false) {
this.selectData = {} this.selectData = {}
@@ -722,11 +722,12 @@ export default {
}, },
immediate: true, immediate: true,
}, },
rowData: { 'rowData': {
handler() { handler() {
this.DATA = Object.assign({}, this.rowData) this.DATA = Object.assign({}, this.rowData)
}, },
immediate: true, immediate: true,
deep:true
}, },
}, },
created() { created() {
@@ -1,101 +1,45 @@
<template> <template>
<base-model :config="config"> <base-model :config="config">
<div slot="dialog-body"> <div slot="dialog-body">
<el-form <el-form ref="trainRecordForm" :model="form" label-width="140px" size="small" :rules="rules">
ref="trainRecordForm"
:model="form"
label-width="140px"
size="small"
:rules="rules"
>
<div class="base-dialog-body"> <div class="base-dialog-body">
<el-form-item <el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingDate')"
v-if="!config.upload" prop="TrianingDate">
:label="$t('trials:trialDocument:trainRecord:form:TrianingDate')" <el-date-picker v-model="form.TrianingDate" type="date" placeholder="" format="yyyy-MM-dd"
prop="TrianingDate" value-format="yyyy-MM-dd" style="width: 100%">
>
<el-date-picker
v-model="form.TrianingDate"
type="date"
placeholder=""
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"
>
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
<el-form-item <el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingCount')"
v-if="!config.upload" prop="TrianingCount">
:label="$t('trials:trialDocument:trainRecord:form:TrianingCount')" <el-input v-model.number="form.TrianingCount" type="number" />
prop="TrianingCount"
>
<el-input v-model="form.TrianingCount" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingState')"
v-if="!config.upload" prop="TrianingState">
:label="$t('trials:trialDocument:trainRecord:form:TrianingState')"
prop="TrianingState"
>
<el-input v-model="form.TrianingState" /> <el-input v-model="form.TrianingState" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:Note')" prop="Note">
v-if="!config.upload"
:label="$t('trials:trialDocument:trainRecord:form:Note')"
prop="Note"
>
<el-input v-model="form.Note" /> <el-input v-model="form.Note" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item v-if="!config.upload || config.upload === 'Trial'"
v-if="!config.upload || config.upload === 'Trial'" :label="$t('trials:trialDocument:trainRecord:form:TrialFileRecord')" prop="TrialFileRecord">
:label="$t('trials:trialDocument:trainRecord:form:TrialFileRecord')" <el-upload class="upload-demo" action :before-upload="(param) => beforeUpload(param, 'Trial', '.pdf')"
prop="TrialFileRecord" :http-request="(param) => handleUploadFile(param, 'Trial')" :on-remove="() => handleRemoveFile('Trial')"
> :limit="1" accept=".pdf" :file-list="TrialFile">
<el-upload <el-button size="small" type="primary" :disabled="!!form.TrialFileRecord && !!form.TrialFileRecord.FilePath
class="upload-demo" ">{{ $t('common:button:upload') }}
action
:before-upload="(param) => beforeUpload(param, 'Trial', '.pdf')"
:http-request="(param) => handleUploadFile(param, 'Trial')"
:on-remove="() => handleRemoveFile('Trial')"
:limit="1"
accept=".pdf"
:file-list="TrialFile"
>
<el-button
size="small"
type="primary"
:disabled="
!!form.TrialFileRecord && !!form.TrialFileRecord.FilePath
"
>{{ $t('common:button:upload') }}
</el-button> </el-button>
<span slot="tip" class="el-upload__tip"> <span slot="tip" class="el-upload__tip">
{{ $t('trials:trialDocument:trainRecord:rule:mustPDF') }} {{ $t('trials:trialDocument:trainRecord:rule:mustPDF') }}
</span> </span>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item <el-form-item v-if="!config.upload || config.upload === 'History'" :label="$t('trials:trialDocument:trainRecord:form:historyFileRecord')
v-if="!config.upload || config.upload === 'History'" ">
:label=" <el-upload class="upload-demo" action :before-upload="(param) => beforeUpload(param, 'History', '.zip')"
$t('trials:trialDocument:trainRecord:form:historyFileRecord')
"
>
<el-upload
class="upload-demo"
action
:before-upload="(param) => beforeUpload(param, 'History', '.zip')"
:http-request="(param) => handleUploadFile(param, 'History')" :http-request="(param) => handleUploadFile(param, 'History')"
:on-remove="() => handleRemoveFile('History')" :on-remove="() => handleRemoveFile('History')" :limit="1" accept=".zip" :file-list="HistoryFile">
:limit="1" <el-button size="small" type="primary" :disabled="!!form.HistoryFileRecord && !!form.HistoryFileRecord.FilePath
accept=".zip" ">{{ $t('common:button:upload') }}
:file-list="HistoryFile"
>
<el-button
size="small"
type="primary"
:disabled="
!!form.HistoryFileRecord && !!form.HistoryFileRecord.FilePath
"
>{{ $t('common:button:upload') }}
</el-button> </el-button>
<span slot="tip" class="el-upload__tip"> <span slot="tip" class="el-upload__tip">
{{ $t('trials:trialDocument:trainRecord:rule:mustZIP') }} {{ $t('trials:trialDocument:trainRecord:rule:mustZIP') }}
@@ -115,7 +59,7 @@
</div> </div>
</base-model> </base-model>
</template> </template>
<script> <script>
import baseModel from '@/components/BaseModel' import baseModel from '@/components/BaseModel'
import { addOrUpdateTrialTrianingRecord } from '@/api/dictionary' import { addOrUpdateTrialTrianingRecord } from '@/api/dictionary'
export default { export default {
@@ -165,6 +109,36 @@ export default {
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, },
], ],
TrianingCount: [
{
type: 'number',
min: 0,
message: this.$t(
'trials:trialDocument:trainRecord:ruleMessage:TrianingCountPattern'
),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (
value &&
(String(value).includes('.') ||
new RegExp(/\D/g).test(String(value)))
) {
callback(
new Error(
this.$t(
'trials:trialDocument:trainRecord:ruleMessage:TrianingCountPattern'
)
)
)
} else {
callback()
}
},
trigger: 'blur',
},
]
}, },
loading: false, loading: false,
TrialFile: [], TrialFile: [],
@@ -843,7 +843,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
openFile(isFolder = false) { openFile(isFolder = false) {
this.selectData = {} this.selectData = {}
@@ -865,11 +865,12 @@ export default {
}, },
immediate: true, immediate: true,
}, },
rowData: { 'rowData': {
handler() { handler() {
this.DATA = Object.assign({}, this.rowData) this.DATA = Object.assign({}, this.rowData)
}, },
immediate: true, immediate: true,
deep:true
}, },
}, },
created() { created() {
@@ -81,7 +81,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.size && scope.row.size > 0 scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -359,7 +359,6 @@ export default {
status: 'add', status: 'add',
upload: null, upload: null,
}, },
DATA: {},
doctorList: [], doctorList: [],
} }
}, },
@@ -612,7 +611,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
openFile(isFolder = false) { openFile(isFolder = false) {
this.selectData = {} this.selectData = {}
@@ -632,12 +631,6 @@ export default {
}, },
immediate: true, immediate: true,
}, },
rowData: {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
},
}, },
created() { created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template'] let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
@@ -7,112 +7,53 @@
<div class="search" style="position: relative"> <div class="search" style="position: relative">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<!--专业--> <!--专业-->
<el-form-item <el-form-item :label="$t('trials:trialDocument:curriculumVitae:search:Speciality')">
:label="$t('trials:trialDocument:curriculumVitae:search:Speciality')" <el-select v-model="searchData.SpecialityId" style="width: 200px" placeholder="" clearable>
> <el-option v-for="item in $d.Department" :key="item.id" :label="item.label" :value="item.id">
<el-select
v-model="searchData.SpecialityId"
style="width: 200px"
placeholder=""
clearable
>
<el-option
v-for="item in $d.Department"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!--亚专业--> <!--亚专业-->
<el-form-item <el-form-item :label="$t('trials:trialDocument:curriculumVitae:search:Subspeciality')
:label=" ">
$t('trials:trialDocument:curriculumVitae:search:Subspeciality') <el-select v-model="searchData.SubspecialityId" style="width: 200px" placeholder="" clearable>
" <el-option v-for="item in $d.Subspeciality" :key="item.id" :label="item.label" :value="item.id">
>
<el-select
v-model="searchData.SubspecialityId"
style="width: 200px"
placeholder=""
clearable
>
<el-option
v-for="item in $d.Subspeciality"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!--机构--> <!--机构-->
<el-form-item <el-form-item :label="$t('trials:trialDocument:curriculumVitae:search:HospitalName')
:label=" ">
$t('trials:trialDocument:curriculumVitae:search:HospitalName') <el-select v-model="searchData.HospitalId" style="width: 200px" placeholder="" clearable>
" <el-option v-for="(item, index) in hospitalList" :key="index"
> :label="isEN ? item.HospitalName : item.HospitalNameCN" :value="item.Id" />
<el-select
v-model="searchData.HospitalId"
style="width: 200px"
placeholder=""
clearable
>
<el-option
v-for="(item, index) in hospitalList"
:key="index"
:label="isEN ? item.HospitalName : item.HospitalNameCN"
:value="item.Id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"> <el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }} {{ $t('common:button:search') }}
</el-button> </el-button>
<el-button <el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }} {{ $t('common:button:reset') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<el-table <el-table v-loading="loading" v-adaptive="{ bottomOffset: 75 }" :data="list" stripe height="100"
v-loading="loading" style="width: 100%">
v-adaptive="{ bottomOffset: 75 }"
:data="list"
stripe
height="100"
style="width: 100%"
>
<el-table-column type="index" /> <el-table-column type="index" />
<!--姓名--> <!--姓名-->
<el-table-column <el-table-column prop="BlindName" :label="$t('trials:trialDocument:curriculumVitae:table:name')"
prop="BlindName" show-overflow-tooltip sortable="custom">
:label="$t('trials:trialDocument:curriculumVitae:table:name')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ isEN ? scope.row.BlindName : scope.row.BlindNameCN }}</span> <span>{{ isEN ? scope.row.BlindName : scope.row.BlindNameCN }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column prop="Code" :label="$t('trials:trialDocument:curriculumVitae:table:UserName')"
prop="Code" show-overflow-tooltip sortable="custom" />
:label="$t('trials:trialDocument:curriculumVitae:table:UserName')" <el-table-column prop="Speciality" :label="$t('trials:trialDocument:curriculumVitae:table:Speciality')"
show-overflow-tooltip show-overflow-tooltip sortable="custom">
sortable="custom"
/>
<el-table-column
prop="Speciality"
:label="$t('trials:trialDocument:curriculumVitae:table:Speciality')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span> <span>
{{ {{
@@ -125,11 +66,8 @@
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column prop="Subspeciality" :label="$t('trials:trialDocument:curriculumVitae:table:Subspeciality')"
prop="Subspeciality" show-overflow-tooltip>
:label="$t('trials:trialDocument:curriculumVitae:table:Subspeciality')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="isEN"> <span v-if="isEN">
{{ {{
@@ -147,62 +85,41 @@
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column prop="HospitalName" :label="$t('trials:trialDocument:curriculumVitae:table:HospitalName')"
prop="HospitalName" show-overflow-tooltip sortable="custom">
:label="$t('trials:trialDocument:curriculumVitae:table:HospitalName')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span> <span>
{{ isEN ? scope.row.HospitalName : scope.row.HospitalNameCN }} {{ isEN ? scope.row.HospitalName : scope.row.HospitalNameCN }}
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column prop="OptTimeStr" :label="$t('trials:trialDocument:curriculumVitae:table:submmitTime')"
prop="OptTimeStr" show-overflow-tooltip sortable="custom" />
:label="$t('trials:trialDocument:curriculumVitae:table:submmitTime')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column :label="$t('common:action:action')" width="200"> <el-table-column :label="$t('common:action:action')" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button icon="el-icon-view" :title="$t('common:button:view')" circle @click.stop="preview(scope.row)" />
icon="el-icon-view"
:title="$t('common:button:view')"
circle
@click.stop="preview(scope.row)"
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页组件 --> <!-- 分页组件 -->
<pagination <pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
class="page" @pagination="getList" />
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<el-dialog :visible.sync="preview_visible" fullscreen> <el-dialog :visible.sync="preview_visible" fullscreen>
<div style="height: 100%; overflow: auto"> <div style="height: 100%; overflow: auto">
<preview <preview :isEN="isEN" :isAll="isAll" :reviewerId.sync="reviewerId" v-if="preview_visible" />
:isEN="isEN"
:isAll="isAll"
:reviewerId.sync="reviewerId"
v-if="preview_visible"
/>
</div> </div>
</el-dialog> </el-dialog>
</box-content> </box-content>
</template> </template>
<script> <script>
const otherId = 'ef84e9cb-f1a6-49d7-b6da-34be2c12abd5'
import { getTrialDoctorList } from '@/api/dictionary' import { getTrialDoctorList } from '@/api/dictionary'
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
import BoxContent from '@/components/BoxContent' import BoxContent from '@/components/BoxContent'
import preview from '@/views/reviewers/curriculumVitae/preview.vue' import preview from '@/views/reviewers/curriculumVitae/preview.vue'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import store from '@/store'
const searchDataDefault = () => { const searchDataDefault = () => {
return { return {
SubspecialityId: null, SubspecialityId: null,
@@ -238,6 +155,7 @@ export default {
reviewerId: null, reviewerId: null,
isAll: false, isAll: false,
preview_visible: false, preview_visible: false,
otherId,
} }
}, },
methods: { methods: {
@@ -293,6 +211,9 @@ export default {
immediate: true, immediate: true,
}, },
}, },
mounted() {
store.dispatch('global/getHospital')
},
computed: { computed: {
...mapGetters(['hospitalList']), ...mapGetters(['hospitalList']),
isEN() { isEN() {
@@ -334,38 +255,44 @@ export default {
]) ])
}, },
TITLE() { TITLE() {
return `${this.$fd('ArchiveType', this.ArchiveTypeEnum)}${ return `${this.$fd('ArchiveType', this.ArchiveTypeEnum)}${this.isEN ? this.rowData.Name : this.rowData.NameCN
this.isEN ? this.rowData.Name : this.rowData.NameCN
}` }`
}, },
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.title { .title {
line-height: 40px; line-height: 40px;
font-weight: bold; font-weight: bold;
margin-bottom: 10px; margin-bottom: 10px;
} }
.fileName { .fileName {
display: inline-block; display: inline-block;
max-width: 100%; max-width: 100%;
white-space: nowrap; /* 文本不换行 */ white-space: nowrap;
overflow: hidden; /* 超出部分隐藏 */ /* 文本不换行 */
overflow: hidden;
/* 超出部分隐藏 */
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.fileBtnBox { .fileBtnBox {
display: inline-block; display: inline-block;
width: 50px; width: 50px;
i { i {
cursor: pointer; cursor: pointer;
color: #409eff; color: #409eff;
margin-right: 3px; margin-right: 3px;
&:last-child { &:last-child {
margin: 0; margin: 0;
} }
} }
} }
.topForm { .topForm {
.el-form-item { .el-form-item {
margin-right: 30px; margin-right: 30px;
@@ -71,23 +71,9 @@
</el-button> </el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button type="primary" @click.stop="openUpload">
type="primary" {{ $t('trials:trialDocument:entryRecord:title:uploadFile') }}
v-if="hasEdit && isManage && !viewStatus"
@click.stop="openFile(false)"
>
{{ $t('trials:trialDocument:entryRecord:button:uploadFile') }}
</el-button> </el-button>
<el-button
v-if="hasDownLoad && (isManage || isInspect)"
icon="el-icon-download"
type="primary"
:disabled="!file || !file.FilePath"
@click.stop="downLoad(file)"
>{{
$t('trials:trialDocument:entryRecord:button:downLoadFile')
}}</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@@ -188,7 +174,7 @@
/> />
</div> </div>
</el-dialog> </el-dialog>
<upload-files <!-- <upload-files
:config="config" :config="config"
:faccept="faccept" :faccept="faccept"
:uploadPath="uploadPath" :uploadPath="uploadPath"
@@ -196,17 +182,67 @@
v-if="config.visible" v-if="config.visible"
@close="close" @close="close"
@uplaodFile="uplaodFile" @uplaodFile="uplaodFile"
/> -->
<base-model :config="upload_config">
<div slot="dialog-body">
<div class="file_title">
{{ $t('trials:trialDocument:entryRecord:title:uploadFile') }}
</div>
<div class="file" v-if="file.FileName">
<div class="name">{{ file.FileName }}</div>
<i
v-if="hasDownLoad && (isManage || isInspect)"
class="el-icon-download"
:title="$t('common:button:download')"
@click.stop="downLoad(file)"
/> />
<i
v-if="hasDel && isManage && !viewStatus"
class="el-icon-delete"
:title="$t('common:button:delete')"
@click.stop="handleRemoveFile"
/>
</div>
<div class="btnBox">
<!-- <el-button
type="primary"
v-if="hasEdit && isManage && !viewStatus"
@click.stop="openFile(false)"
>
{{ $t('trials:trialDocument:entryRecord:button:uploadFile') }}
</el-button> -->
<el-upload
v-if="hasEdit && isManage && !viewStatus"
class="upload-demo"
action
:before-upload="(param) => beforeUpload(param, '.zip')"
:show-file-list="false"
:http-request="handleUploadFile"
:limit="1"
accept=".zip"
>
<el-button size="small" type="primary" :disabled="!!file.FileName">
{{ $t('trials:trialDocument:entryRecord:button:uploadFile') }}
</el-button>
</el-upload>
</div>
</div>
</base-model>
</box-content> </box-content>
</template> </template>
<script> <script>
import { getConfirmationReviewerList } from '@/api/trials' import { getConfirmationReviewerList } from '@/api/trials'
import { uploadTrialFileTypeFile, getTrialFileTypeFile } from '@/api/dictionary' import {
uploadTrialFileTypeFile,
getTrialFileTypeFile,
deleteTrialTypeFile,
} from '@/api/dictionary'
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
import BoxContent from '@/components/BoxContent' import BoxContent from '@/components/BoxContent'
import preview from '@/views/reviewers/curriculumVitae/preview.vue' import preview from '@/views/reviewers/curriculumVitae/preview.vue'
import baseModel from '@/components/BaseModel'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import uploadFiles from '../../uploadFiles.vue' // import uploadFiles from '../../uploadFiles.vue'
import { downLoadFile } from '@/utils/stream.js' import { downLoadFile } from '@/utils/stream.js'
const searchDataDefault = () => { const searchDataDefault = () => {
return { return {
@@ -223,7 +259,13 @@ const searchDataDefault = () => {
} }
export default { export default {
name: 'entryRecord', name: 'entryRecord',
components: { BoxContent, Pagination, preview, uploadFiles }, components: {
BoxContent,
Pagination,
preview,
// uploadFiles,
baseModel,
},
props: { props: {
ArchiveTypeEnum: { ArchiveTypeEnum: {
type: Number, type: Number,
@@ -254,7 +296,6 @@ export default {
isAll: false, isAll: false,
preview_visible: false, preview_visible: false,
timeList: [], timeList: [],
config: { config: {
visible: false, visible: false,
showClose: true, showClose: true,
@@ -263,6 +304,14 @@ export default {
appendToBody: false, appendToBody: false,
isFolder: false, isFolder: false,
}, },
upload_config: {
visible: false,
showClose: true,
width: '800px',
title: '',
appendToBody: false,
isFolder: false,
},
faccept: ['.zip'], faccept: ['.zip'],
limitLength: 1, limitLength: 1,
uploadPath: null, uploadPath: null,
@@ -270,6 +319,88 @@ export default {
} }
}, },
methods: { methods: {
handleRemoveFile() {
this.$confirm(
this.$t('trials:trialDocument:entryRecord:message:deleteMes'),
{
type: 'warning',
distinguishCancelAndClose: true,
}
)
.then(() => {
deleteTrialTypeFile({
TrialFileTypeId: this.file.TrialFileTypeId,
}).then((res) => {
if (res.IsSuccess) {
this.getFile()
this.$message({
message: this.$t('common:message:deletedSuccessfully'),
type: 'success',
})
}
})
})
.catch((action) => {})
},
async handleUploadFile(param) {
try {
console.log(param)
let trialId = this.$route.query.trialId
let extendName = param.file.name
.substring(param.file.name.lastIndexOf('.'))
.toLocaleLowerCase()
if (!trialId)
return this.$alert(
this.$t('trials:trialDocument:entryRecord:msg:noTrialId')
).catch()
this.loading = true
var file = await this.fileToBlob(param.file)
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
let types = typeArr[this.ArchiveTypeEnum]
// let fileNameNoType = param.file.name
// .substring(0, param.file.name.lastIndexOf('.'))
// .toLocaleLowerCase()
const res = await this.OSSclient.put(
`/${trialId}/Document/${types}/${this.$guid()}${extendName}`,
file
)
this.file = {
FileName: param.file.name,
FilePath: this.$getObjectName(res.url),
FileSize: param.file.size,
FileFormat: extendName,
}
this.loading = false
this.uplaodFile([this.file])
} catch (err) {
console.log(err)
}
},
beforeUpload(param, accept) {
if (this.file && !!this.file.FileName) {
this.$alert(
this.$t('trials:trialDocument:entryRecord:msg:hasFile')
).catch()
return
}
let extendName = param.name
.substring(param.name.lastIndexOf('.'))
.toLocaleLowerCase()
if (accept !== extendName) {
this.$alert(
this.$t('trials:trialDocument:entryRecord:msg:typeErr')
).catch()
return
}
},
openUpload() {
this.upload_config.title = `${this.$t(
'trials:trialDocument:entryRecord:title:uploadFile'
)}
-
${this.isEN ? this.rowData.Name : this.rowData.NameCN}`
this.upload_config.visible = true
},
// //
async downLoad(row) { async downLoad(row) {
try { try {
@@ -467,4 +598,34 @@ export default {
margin-right: 30px; margin-right: 30px;
} }
} }
.file_title {
line-height: 40px;
font-weight: bold;
}
.file {
width: 100%;
display: flex;
margin-bottom: 10px;
.name {
max-width: 90%;
white-space: nowrap; /* 文本不会换行,会在同一行内继续,直到遇到<br>标签为止 */
text-overflow: ellipsis; /* 当文本溢出包含它的容器时,显示省略号(...)来表示被截断的文本 */
overflow: hidden; /* 隐藏溢出容器的文本 */
}
i {
cursor: pointer;
margin: 3px;
color: #409eff;
}
.disable {
cursor: not-allowed;
color: #909399;
}
}
.btnBox {
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-end;
}
</style> </style>
@@ -155,6 +155,9 @@ export default {
} }
}, },
computed: { computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
isInspect() { isInspect() {
return this.hasPermi([ return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:inspect', 'trials:trials-panel:trial-summary:trial-document:inspect',
@@ -247,4 +250,7 @@ export default {
margin: 0 0 12px 0; margin: 0 0 12px 0;
border-top: 1px solid #ebeef5; border-top: 1px solid #ebeef5;
} }
::v-deep .box-body .search .base-search-form .el-form-item {
margin-bottom: 15px;
}
</style> </style>
@@ -15,7 +15,7 @@
v-for="(item, index) of siteOptions" v-for="(item, index) of siteOptions"
:key="index" :key="index"
:label="item.TrialSiteCode" :label="item.TrialSiteCode"
:value="item.SiteId" :value="item.TrialSiteId"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -459,7 +459,7 @@ export default {
}, },
fileSizeFormatter(size) { fileSizeFormatter(size) {
if (!size) return if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M' return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
}, },
handleReset() { handleReset() {
this.searchData = searchDataDefault() this.searchData = searchDataDefault()
@@ -323,7 +323,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.Size && scope.row.Size > 0 scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -434,9 +434,9 @@
scope.row.dicomInfo.fileCount scope.row.dicomInfo.fileCount
}} }}
({{ ({{
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(2) (scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(3)
}}MB/{{ }}MB/{{
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(2) (scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(3)
}}MB) }}MB)
</span> </span>
</template> </template>
@@ -92,7 +92,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.FileSize && scope.row.FileSize > 0 scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -462,7 +462,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.size && scope.row.size > 0 scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
@@ -328,7 +328,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ <span>{{
scope.row.Size && scope.row.Size > 0 scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB` ? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: '' : ''
}}</span> }}</span>
</template> </template>
+4 -4
View File
@@ -11,13 +11,13 @@ const webpack = require('webpack')
const defaultSettings = require('./src/settings.js') const defaultSettings = require('./src/settings.js')
const moment = require('moment') const moment = require('moment')
var distDate = moment(new Date()).format('YYYY-MM-DD') var distDate = moment(new Date()).format('YYYY-MM-DD')
const name = process.env.NODE_ENV === 'usa' ? 'LILI' : defaultSettings.title || 'IRCIS' // page title const name = process.env.NODE_ENV === 'usa' ? 'Imaging Trial Management System' : defaultSettings.title || 'IRC Imaging System' // page title
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
module.exports = defineConfig({ module.exports = defineConfig({
// lintOnSave: false, // lintOnSave: false,
transpileDependencies: false, transpileDependencies: false,
publicPath: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? process.env.VUE_APP_BASE_PATH : `${process.env.VUE_FILE_PATH}${process.env.VUE_APP_OSS_PATH}${distDate}/`, publicPath: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? process.env.VUE_APP_BASE_PATH : `${process.env.VUE_FILE_PATH}${process.env.VUE_APP_OSS_PATH}${distDate}/`,
// publicPath: '/', // publicPath: '/',
outputDir: 'dist', outputDir: 'dist',
assetsDir: 'static', assetsDir: 'static',
@@ -97,7 +97,7 @@ module.exports = defineConfig({
] ]
}), }),
// new BundleAnalyzerPlugin(), // new BundleAnalyzerPlugin(),
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function() { } process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
: new WebpackAliyunOss({ : new WebpackAliyunOss({
from: ['./dist/**'], from: ['./dist/**'],
dist: process.env.VUE_APP_OSS_PATH + distDate, dist: process.env.VUE_APP_OSS_PATH + distDate,
@@ -184,7 +184,7 @@ module.exports = defineConfig({
// 生成文件的最大体积 // 生成文件的最大体积
maxAssetSize: 3000000000, maxAssetSize: 3000000000,
// 只给出js的性能提示 // 只给出js的性能提示
assetFilter: function(assetFileName) { assetFilter: function (assetFileName) {
return assetFileName.endsWith('.js') return assetFileName.endsWith('.js')
} }
} }