72 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
caiyiling bfe2f1dbfb Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-17 11:37:30 +08:00
caiyiling 24806f57ed 自定义阅片bug修复 2025-03-17 11:37:09 +08:00
wangxiaoshuang b0ff8e7163 项目文档培训记录效果改为可输入所有字符
continuous-integration/drone/push Build is passing
2025-03-17 11:34:03 +08:00
caiyiling c9ef6cd19f Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-17 11:24:01 +08:00
caiyiling 00cc5d5d27 非dicom阅片ecrf更改 2025-03-17 11:23:24 +08:00
wangxiaoshuang 25ddd422a3 1
continuous-integration/drone/push Build is passing
2025-03-17 09:29:56 +08:00
wangxiaoshuang a060c1745d 项目文档资质材料
continuous-integration/drone/push Build is passing
2025-03-14 17:09:38 +08:00
wangxiaoshuang 1a4bfe64f9 项目文档上传文件路径更改
continuous-integration/drone/push Build is passing
2025-03-14 13:15:44 +08:00
caiyiling 2fd6e1893b Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-14 10:35:46 +08:00
caiyiling dc0229810d 国际化补充 2025-03-14 10:35:20 +08:00
wangxiaoshuang 08c911d4a0 项目文档申报方同意入项记录审核人角色字段更改
continuous-integration/drone/push Build is passing
2025-03-14 10:25:35 +08:00
wangxiaoshuang 08cdcffd82 项目文档申报方同意入项记录
continuous-integration/drone/push Build is passing
2025-03-13 17:10:42 +08:00
wangxiaoshuang a5f16c866d 检查名称配置更改
continuous-integration/drone/push Build is passing
2025-03-13 16:37:08 +08:00
caiyiling 3167c2bea7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-13 15:01:16 +08:00
caiyiling 26cca57f75 系统标准国际化补充 2025-03-13 15:00:50 +08:00
wangxiaoshuang ff88cbd6e2 1
continuous-integration/drone/push Build is passing
2025-03-13 13:23:56 +08:00
wangxiaoshuang c4a498d953 检查被IQC标记删除:在crc查看时,该行记录增加删除线
continuous-integration/drone/push Build is passing
2025-03-13 11:14:34 +08:00
wangxiaoshuang f58e2ff82f 影像重传,确认完成时,签名中XXX未替换 2025-03-13 11:14:00 +08:00
wangxiaoshuang 1696fb6294 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-12 17:33:10 +08:00
wangxiaoshuang 3c81a8a678 1 2025-03-12 17:32:58 +08:00
caiyiling afcd1b82c0 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main 2025-03-12 17:22:44 +08:00
caiyiling 96864b808c 配置文件更改 2025-03-12 17:22:18 +08:00
wangxiaoshuang 5ba2abb8f5 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is failing
2025-03-12 17:11:15 +08:00
wangxiaoshuang dc0329032e 项目文档菜单添加滚动条 2025-03-12 17:11:05 +08:00
caiyiling 4097389447 图片渲染窗口滚动条优化
continuous-integration/drone/push Build is passing
2025-03-12 16:11:16 +08:00
caiyiling cf39a84370 全局和裁判阅片签名更改
continuous-integration/drone/push Build is passing
2025-03-12 15:42:56 +08:00
caiyiling aae2d6a1c5 非dicom全局和裁判阅片更改
continuous-integration/drone/push Build is passing
2025-03-12 15:18:23 +08:00
caiyiling 10f4bf7480 pdf文件替换
continuous-integration/drone/push Build is passing
2025-03-12 14:56:17 +08:00
caiyiling 57f0938efc 非dicom文件交互更改
continuous-integration/drone/push Build is passing
2025-03-12 14:50:55 +08:00
caiyiling 615580331b 后台管理页面调整
continuous-integration/drone/push Build is passing
2025-03-12 14:42:05 +08:00
caiyiling 4b4058b0da 文件渲染视口样式更改
continuous-integration/drone/push Build is passing
2025-03-12 13:16:47 +08:00
caiyiling f77820df79 临床数据查看更改
continuous-integration/drone/push Build is running
2025-03-12 13:14:31 +08:00
caiyiling 398bc21666 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-12 13:10:53 +08:00
caiyiling 7db8e231b6 切换pdf时取消取消全屏 2025-03-12 13:10:26 +08:00
wangxiaoshuang 581e2c3879 培训记录备注可输入值变更
continuous-integration/drone/push Build is passing
2025-03-12 11:47:27 +08:00
caiyiling ce030d23cd Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-12 11:35:06 +08:00
caiyiling f3c073286b 非dicom表单更改及渲染视口双击事件优化 2025-03-12 11:34:18 +08:00
wangxiaoshuang d5b342ddc6 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-12 11:22:32 +08:00
wangxiaoshuang d616512a72 项目文档按钮权限更改 2025-03-12 11:22:20 +08:00
110 changed files with 4329 additions and 2007 deletions
+3
View File
@@ -2,6 +2,9 @@
ENV = 'prop'
NODE_ENV = 'prop'
# base public path
VUE_APP_BASE_PATH = '/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true
+197
View File
File diff suppressed because one or more lines are too long
+72
View File
@@ -1249,3 +1249,75 @@ export function getTrialDoctorList(data) {
data
})
}
// 项目文档-上传同意入项记录
export function uploadTrialFileTypeFile(data) {
return request({
url: `/TrialFileType/uploadTrialFileTypeFile`,
method: 'post',
data
})
}
// 项目文档-获取上传同意入项记录
export function getTrialFileTypeFile(data) {
return request({
url: `/TrialFileType/getTrialFileTypeFile`,
method: 'post',
data
})
}
// 项目文档-删除上传同意入项记录
export function deleteTrialTypeFile(params) {
return request({
url: `/TrialFileType/deleteTrialTypeFile`,
method: 'post',
params
})
}
// 项目文档-获取资质材料列表
export function getTrialAttachments(data) {
return request({
url: `/Attachment/getTrialAttachments`,
method: 'post',
data
})
}
// 项目文档-修改资质材料稽查状态
export function setAuthorizedViewC(data) {
return request({
url: `/Attachment/setAuthorizedView`,
method: 'post',
data
})
}
// 项目文档-上传资质材料
export function saveTrialAttachments(data) {
return request({
url: `/Attachment/saveTrialAttachments`,
method: 'post',
data
})
}
// 项目文档-资质材料(获取医生列表)
export function getTrialDoctorListC(data) {
return request({
url: `/Attachment/getTrialDoctorList`,
method: 'post',
data
})
}
// 项目文档-修改资质材料
export function updateTrialAttachments(data) {
return request({
url: `/Attachment/updateTrialAttachments`,
method: 'post',
data
})
}
// 项目文档-删除资质材料
export function deleteAttachment(data) {
return request({
url: `/Attachment/deleteAttachment`,
method: 'post',
data
})
}
+8
View File
@@ -110,4 +110,12 @@ export function addOrUpdateTrialBodyPart(data) {
data
})
}
// 修改检查名称列表
export function updateTrialStudyNameList(data) {
return request({
url: `/TrialConfig/updateTrialStudyNameList`,
method: 'post',
data
})
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

+1 -2
View File
@@ -1,7 +1,7 @@
<!-- 搜索表单 -->
<template>
<div class="base-search-form">
<el-form :size="size" :inline="true" :label-width="labelWidth">
<el-form :inline="true" :label-width="labelWidth">
<el-form-item
v-for="item in searchForm"
:key="item.prop"
@@ -152,7 +152,6 @@
<el-button
v-else
:type="item.type"
:size="item.size || size"
:icon="item.icon || ''"
@click="handleClick(item.emitKey)"
>{{ item.label }}</el-button
-1
View File
@@ -62,7 +62,6 @@
</a> -->
<span v-for="(operate, i) in column.operates" :key="i">
<el-button
:size="operate.size || 'mini'"
:type="operate.type || 'primary'"
v-if="
(operate.show && scope.row[operate.show]) ||
@@ -316,9 +316,9 @@
scope.row.dicomInfo.fileCount
}}
({{
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(3)
}}MB/{{
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(3)
}}MB)
</span>
</template>
@@ -66,7 +66,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -138,7 +138,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -320,7 +320,7 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
+1 -1
View File
@@ -1,7 +1,7 @@
// eslint-disable-next-line no-undef
module.exports = {
title: 'IRCIS',
title: 'IRC Imaging System',
/**
* @type {boolean} true | false
+1
View File
@@ -862,6 +862,7 @@ const actions = {
const data = {}
data.StudyId = study.StudyId
data.StudyCode = study.StudyCode
data.StudyName = study.StudyName
data.Modalities = study.Modalities
data.SeriesCount = study.SeriesCount
data.InstanceCount = study.InstanceCount
+1 -1
View File
@@ -1,6 +1,6 @@
import defaultSettings from '@/settings'
const title = defaultSettings.title || 'IRCIS'
const title = defaultSettings.title || 'IRC Imaging System'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
+149
View File
@@ -39,6 +39,108 @@ function getNumberValues(dataSet, tag, minimumLength) {
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) {
const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
@@ -99,5 +201,52 @@ function metaDataProvider(type, imageId) {
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;
+1 -1
View File
@@ -445,7 +445,7 @@ function setTimer() {
totalBytes = totalBytes / 1024;
unit = "MB/s";
}
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
}
if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]]
+1 -1
View File
@@ -150,7 +150,7 @@ function setTimer() {
totalBytes = totalBytes / 1024;
unit = "MB/s";
}
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
}
if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]]
+1
View File
@@ -9,6 +9,7 @@ const ROUTER = require('@/router');
axios.defaults.withCredentials = false
const service = axios.create({
baseURL: '/api',
// baseURL: process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api',
timeout: 2 * 360000, // request timeout
withCredentials: false
})
@@ -39,7 +39,6 @@
</el-form>
<el-button
type="primary"
icon="el-icon-plus"
style="margin-left:auto;"
size="small"
@click="handleAdd"
@@ -105,7 +104,7 @@
sortable="custom"
/>
<el-table-column label="Action">
<el-table-column label="Action" width="300">
<template slot-scope="scope">
<el-button
type="text"
@@ -39,7 +39,6 @@
</el-form-item>
<el-button
type="primary"
icon="el-icon-plus"
style="float: right"
size="small"
@click="handleAdd"
@@ -120,7 +119,7 @@
sortable="custom"
/>
<el-table-column :label="$t('common:action:action')">
<el-table-column :label="$t('common:action:action')" width="300">
<template slot-scope="scope">
<el-button type="text" @click="PreviewFile(scope.row)">
{{ $t('common:button:preview') }}
@@ -33,7 +33,6 @@
</el-form>
<el-button
type="primary"
icon="el-icon-plus"
style="margin-left: auto; margin-bottom: 10px"
size="small"
@click="handleAdd"
@@ -117,7 +116,7 @@
sortable="custom"
/>
<el-table-column :label="$t('common:action:action')" min-width="100">
<el-table-column :label="$t('common:action:action')" min-width="120">
<template slot-scope="scope">
<el-button type="text" @click="handlePreview(scope.row)">
{{ $t('common:button:preview') }}
@@ -37,7 +37,6 @@
</el-form-item>
<el-button
type="primary"
icon="el-icon-plus"
style="float: right"
size="small"
@click="handleAdd"
@@ -121,7 +120,7 @@
sortable="custom"
/>
<el-table-column :label="$t('common:action:action')">
<el-table-column :label="$t('common:action:action')" width="300">
<template slot-scope="scope">
<el-button type="text" @click="PreviewFile(scope.row)">
{{ $t('common:button:preview') }}
+3 -15
View File
@@ -2,13 +2,13 @@
<div class="app-container my_menu" >
<el-form :inline="true">
<el-form-item label="模块">
<el-select v-model="queryParams.ModuleTypeId" placeholder="模块" clearable size="small">
<el-select v-model="queryParams.ModuleTypeId" placeholder="模块" clearable >
<el-option v-for="item of dict.type.ModuleType" :key="`ModuleTypeId${item.value}`" :value="item.value" :label="item.raw.ValueCN" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
<div>
@@ -66,42 +66,30 @@
<template slot-scope="scope">
<el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN "
size="mini"
type="text"
icon="el-icon-top"
@click="handleUpMove(scope.row)"
>上移</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
v-if="!(scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN)"
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
>新增</el-button>
<el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN "
size="mini"
type="text"
icon="el-icon-plus"
@click="handleChildren(scope.row)"
>Children</el-button>
<el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN "
size="mini"
type="text"
icon="el-icon-plus"
@click="handleCopy(scope.row)"
>复制到</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
@@ -1,7 +1,7 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- CRO Name -->
<el-form-item :label="$t('institutions:cros:label:croName')">
<el-input v-model="searchData.CROName" style="width: 100px" />
@@ -21,10 +21,7 @@
</el-form>
<span style="margin-left: auto">
<el-button
size="small"
type="primary"
style="margin-left: auto"
icon="el-icon-plus"
@click="handleAddCro"
>{{ $t('common:button:new') }}</el-button
>
@@ -77,17 +74,17 @@
<el-table-column :label="$t('common:action:action')" min-width="200">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
type="text"
@click="handleEdit(scope.row)"
/>
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
circle
icon="el-icon-delete"
:title="$t('common:button:delete')"
type="text"
@click="handleDelete(scope.row)"
/>
>
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@@ -1,7 +1,7 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Hospital -->
<el-form-item :label="$t('institutions:hospitals:label:hospital')">
<el-input v-model="searchData.HospitalName" style="width:100px;" />
@@ -29,10 +29,7 @@
</el-form>
<span style="margin-left:auto;">
<el-button
size="small"
type="primary"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddHospital"
>{{ $t('common:button:new') }}</el-button>
</span>
@@ -132,17 +129,17 @@
<el-table-column :label="$t('common:action:action')" width="150">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
type="text"
@click="handleEdit(scope.row)"
/>
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
circle
icon="el-icon-delete"
:title="$t('common:button:delete')"
type="text"
@click="handleDelete(scope.row)"
/>
>
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@@ -1,7 +1,7 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Site Name -->
<el-form-item :label="$t('institutions:sites:label:siteName')">
<el-input v-model="searchData.SiteName" style="width: 120px" />
@@ -34,16 +34,13 @@
<div style="margin-left: auto">
<el-button
type="primary"
size="small"
icon="el-icon-plus"
@click="handleAddSystemSite"
>{{ $t("trial:dictionary:institutions:site:addSystemSite") }}
</el-button>
<el-button
type="primary"
size="small"
style="margin-left: 10px"
icon="el-icon-plus"
@click="handleAddSite"
>
{{ $t('common:button:new') }}
@@ -173,17 +170,17 @@
<el-table-column :label="$t('common:action:action')" fixed="right" width="150">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
type="text"
@click="handleEdit(scope.row)"
/>
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
circle
icon="el-icon-delete"
:title="$t('common:button:delete')"
type="text"
@click="handleDelete(scope.row)"
/>
>
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@@ -1,7 +1,7 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Sponsor Name -->
<el-form-item :label="$t('institutions:sponsors:label:sponsorName')">
<el-input v-model="searchData.SponsorName" style="width: 100px" />
@@ -21,10 +21,8 @@
</el-form>
<span style="margin-left: auto">
<el-button
size="small"
type="primary"
style="margin-left: auto"
icon="el-icon-plus"
@click="handleAddSponsor"
>{{ $t('common:button:new') }}</el-button
>
@@ -77,17 +75,17 @@
<el-table-column :label="$t('common:action:action')" min-width="150">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
type="text"
@click="handleEdit(scope.row)"
/>
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
circle
icon="el-icon-delete"
:title="$t('common:button:delete')"
type="text"
@click="handleDelete(scope.row)"
/>
>
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item>
@@ -12,12 +12,24 @@
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">新建</el-button>
<el-button type="primary" @click="handleAdd">新建</el-button>
</span>
</div>
<el-table
@@ -68,25 +80,22 @@
/>
</template>
</el-table-column>
<el-table-column label="操作" width="300" fixed="right">
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="success"
size="mini"
type="text"
@click="handleChild(scope.row)"
>
子项
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -63,18 +63,16 @@
/>
</template>
</el-table-column>
<el-table-column label="操作" width="300" fixed="right">
<el-table-column label="操作" width="150" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item>
@@ -12,12 +12,24 @@
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">新建</el-button>
<el-button type="primary" @click="handleAdd">新建</el-button>
</span>
</div>
<el-table
@@ -68,25 +80,22 @@
/>
</template>
</el-table-column>
<el-table-column label="操作" width="300" fixed="right">
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="success"
size="mini"
type="text"
@click="handleChild(scope.row)"
>
子项
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -183,16 +183,13 @@
<el-button
size="small"
type="primary"
icon="el-icon-plus"
@click="handleAdd"
>{{ $t('common:button:new') }}</el-button>
</template>
<template slot-scope="scope">
<!-- 删除 -->
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.$index)"
>{{ $t('common:button:delete') }}</el-button>
</template>
@@ -65,15 +65,13 @@
<el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item>
@@ -15,13 +15,25 @@
<el-input v-model="searchData.KeyInfo" clearable style="width:120px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">新建</el-button>
<el-button type="primary" size="mini" @click="handleBatchAdd">批量新建</el-button>
<el-button type="primary" @click="handleAdd">新建</el-button>
<el-button type="primary" @click="handleBatchAdd">批量新建</el-button>
</span>
</div>
<el-table
@@ -86,22 +98,19 @@
<el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="success"
size="mini"
type="text"
@click="handleChild(scope.row)"
>
子项
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item>
@@ -12,13 +12,25 @@
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleSetting">配置字典分组</el-button>
<el-button type="primary" size="mini" @click="handleAdd">新建</el-button>
<el-button type="primary" @click="handleSetting">配置字典分组</el-button>
<el-button type="primary" @click="handleAdd">新建</el-button>
</span>
</div>
<el-table
@@ -72,22 +84,19 @@
<el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="success"
size="mini"
type="text"
@click="handleChild(scope.row)"
>
子项
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
删除
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item label="Code:">
<el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item>
@@ -10,12 +10,24 @@
<el-input v-model="searchData.KeyName" clearable style="width:120px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">New</el-button>
<el-button type="primary" @click="handleAdd">New</el-button>
</span>
</div>
<el-table
@@ -50,18 +62,16 @@
<el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
Edit
编辑
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
Delete
删除
</el-button>
</template>
</el-table-column>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dictionary:browser:search:title')">
<el-input v-model="searchData.Title" style="width: 100px" />
</el-form-item>
@@ -23,7 +23,7 @@
</el-form-item>
</el-form>
<span style="margin-left: auto">
<el-button type="primary" size="mini" @click="handleAdd">
<el-button type="primary" @click="handleAdd">
{{ $t("dictionary:browser:button:add") }}
</el-button>
</span>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Group -->
<el-form-item :label="$t('template:anonymization:label:group')">
<el-input v-model="searchData.Group" clearable style="width:120px;" />
@@ -33,7 +33,7 @@
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
<el-button type="primary" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
</span>
</div>
@@ -107,15 +107,13 @@
<el-table-column :label="$t('common:action:action')" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- 临床数据名称 -->
<el-form-item :label="$t('trials:processCfg:title:clinicalDataCfg')">
<el-input v-model="searchData.ClinicalDataSetName" />
@@ -44,7 +44,7 @@
</el-form>
<span style="margin-left:auto">
<!-- 新增 -->
<el-button type="primary" size="mini" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
<el-button type="primary" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
</span>
</div>
@@ -158,12 +158,11 @@
min-width="140"
/>
<el-table-column :label="$t('common:action:action')" min-width="350" fixed="right">
<el-table-column :label="$t('common:action:action')" min-width="250" fixed="right">
<template slot-scope="scope">
<!-- 问题配置 -->
<el-button
type="primary"
size="mini"
type="text"
:disabled="scope.row.ClinicalUploadType !== 2"
@click="handleConfigQuestion(scope.row)"
>
@@ -172,8 +171,7 @@
<!-- 下载 -->
<el-button
v-if="$i18n.locale === 'zh'"
type="primary"
size="mini"
type="text"
:disabled="!scope.row.FileName"
@click="handleDownloadTpl(scope.row.Path)"
>
@@ -182,8 +180,7 @@
<!-- 下载 -->
<el-button
v-else
type="primary"
size="mini"
type="text"
:disabled="!scope.row.EnFileName"
@click="handleDownloadTpl(scope.row.EnPath)"
>
@@ -191,16 +188,14 @@
</el-button>
<!-- 编辑 -->
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:action:edit') }}
</el-button>
<!-- 删除 -->
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -68,13 +68,12 @@
>
<template slot-scope="scope">
<!-- 配置 -->
<el-button size="small" :disabled="isCompleteConfig" type="primary" @click="openChildren(scope.row)">
<el-button :disabled="isCompleteConfig" type="text" @click="openChildren(scope.row)">
{{ $t('dictionary:template:criterionDictionary:button:config') }}
</el-button>
<!-- 删除 -->
<el-button
type="danger"
size="small"
type="text"
:disabled="isCompleteConfig"
@click="handleDelete(scope.row)"
>
@@ -108,7 +107,7 @@
@click="handleSave"
v-loading="loading"
>
保存
{{ $t('common:button:save')}}
</el-button>
</div>
<el-table
@@ -227,7 +226,8 @@ export default {
})
},
handleAdd() {
this.drawer_cfg2 = { drawerChild: true, title: '选择标准字典' }
// 选择标准字典
this.drawer_cfg2 = { drawerChild: true, title: this.$t('template:criterionDictionary:title:selectDictionary') }
this.config.visible = true
this.$nextTick(() => {
var a = this.dicList.filter(v => {
@@ -262,9 +262,10 @@ export default {
},
handleDelete(row) {
this.loading = true
this.$confirm('确定要删除该系统标准字典吗?').then(() => {
// 是否确认删除
this.$confirm(this.$t('template:criterionDictionary:message:msg1')).then(() => {
deleteSystemCriterionDictionary({Id: row.Id}).then(res => {
this.$message.success('删除成功')
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.loading = false
this.getList()
}).catch(() => { this.loading = false })
@@ -10,7 +10,7 @@
@click="handleAdd"
style="margin-right: 10px;"
>
配置
{{ $t('dictionary:template:criterionDictionary:button:config') }}
</el-button>
</div>
</div>
@@ -24,39 +24,44 @@
>
<el-table-column
prop=""
label="序号"
label=""
width="50"
>
<template slot-scope="scope">
{{scope.$index + 1}}
</template>
</el-table-column>
<!-- 键值 -->
<el-table-column
prop="Code"
label="键值"
:label="$t('dictionary:template:criterionDictionary:table:code')"
show-overflow-tooltip
/>
<!-- 中文值 -->
<el-table-column
prop="ValueCN"
label="中文值"
:label="$t('dictionary:template:criterionDictionary:table:valueCN')"
show-overflow-tooltip
>
</el-table-column>
<!-- 英文值 -->
<el-table-column
prop="Value"
label="英文值"
:label="$t('dictionary:template:criterionDictionary:table:value')"
show-overflow-tooltip
>
</el-table-column>
<!-- 描述 -->
<el-table-column
prop="Description"
label="描述"
:label="$t('dictionary:template:criterionDictionary:table:description')"
show-overflow-tooltip
>
</el-table-column>
<!-- 分组 -->
<el-table-column
prop="Description"
label="分组"
:label="$t('dictionary:template:criterionDictionary:table:group')"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -84,7 +89,7 @@
@click="handleSave"
v-loading="loading"
>
保存
{{ $t('common:button:save')}}
</el-button>
</div>
<el-table
@@ -100,27 +105,31 @@
type="selection"
width="55">
</el-table-column>
<!-- 键值 -->
<el-table-column
prop="raw.Code"
label="键值"
:label="$t('dictionary:template:criterionDictionary:table:code')"
show-overflow-tooltip
>
</el-table-column>
<!-- 中文值 -->
<el-table-column
prop="raw.ValueCN"
label="中文值"
:label="$t('dictionary:template:criterionDictionary:table:valueCN')"
show-overflow-tooltip
>
</el-table-column>
<!-- 英文值 -->
<el-table-column
prop="raw.Value"
label="英文值"
:label="$t('dictionary:template:criterionDictionary:table:value')"
show-overflow-tooltip
>
</el-table-column>
<!-- 描述 -->
<el-table-column
prop="raw.Description"
label="描述"
:label="$t('dictionary:template:criterionDictionary:table:description')"
show-overflow-tooltip
>
</el-table-column>
@@ -152,7 +161,7 @@ export default {
activeName: '0',
addOrEdit: { visible: false, title: '' },
preview: { visible: false, title: 'eCRF预览' },
config: { visible: false, title: '标准字典值' },
config: { visible: false, title: this.$t('template:criterionDictionary:message:msg2') }, //标准字典值
selectedList: []
}
},
@@ -167,7 +176,7 @@ export default {
CrterionDictionaryGroup: v
}).then(res => {
this.loading = false
this.$message.success('设置成功')
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.getList()
}).catch(() => {this.loading = false})
},
@@ -206,30 +206,27 @@
<el-table-column
prop=""
:label="$t('common:action:action')"
width="250"
width="200"
show-overflow-tooltip
fixed="right"
>
<template slot-scope="scope">
<el-button
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)"
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('trials:readingUnit:qsList:title:edit') }}
</el-button>
<el-button
v-else
type="primary"
size="mini"
type="text"
@click="handleLook(scope.row)"
>
{{ $t('trials:readingUnit:qsList:title:view') }}
</el-button>
<el-button
type="primary"
size="mini"
type="text"
:disabled="!(scope.row.Type === 'table' || scope.row.Type === 'basicTable')"
@click="handleConfig(scope.row)"
>
@@ -237,8 +234,7 @@
</el-button>
<el-button
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)"
type="danger"
size="mini"
type="text"
:disabled="scope.row.IsEnable"
@click="handleDelete(scope.row)"
>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item
:label="$t('trials:auditRecord:table:criterion')"
>
@@ -75,7 +75,7 @@
</el-form>
<span style="margin-left:auto">
<!-- 添加 -->
<el-button type="primary" size="mini" @click="handleAdd">{{$t('common:button:new')}}</el-button>
<el-button type="primary" @click="handleAdd">{{$t('common:button:new')}}</el-button>
</span>
</div>
@@ -173,36 +173,32 @@
{{ $fd('YesOrNo', scope.row.IseCRFShowInDicomReading) }}
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" min-width="200px">
<el-table-column :label="$t('common:action:action')" min-width="220px">
<template slot-scope="scope">
<!-- 编辑 -->
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<!-- eCRF -->
<el-button
type="primary"
size="mini"
type="text"
@click="handleConfig(scope.row)"
>
{{ $t('dictionary:template:criterionConfig:button:eCRF') }}
</el-button>
<!-- 基础数据 -->
<el-button
type="primary"
size="mini"
type="text"
@click="handleBaseDataConfig(scope.row)"
>
{{ $t('dictionary:template:criterionConfig:button:basicData') }}
</el-button>
<!-- 删除 -->
<el-button
type="danger"
size="mini"
type="text"
:disabled="scope.row.IsCompleteConfig"
@click="handleDelete(scope.row)"
>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Group -->
<el-form-item :label="$t('template:anonymization:label:group')">
<el-input v-model="searchData.Group" clearable style="width:120px;" />
@@ -33,7 +33,7 @@
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
<el-button type="primary" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
</span>
</div>
@@ -107,15 +107,13 @@
<el-table-column :label="$t('common:action:action')" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:action:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- 问题名称 -->
<el-form-item :label="$t('trials:MIMqcCfg:table:questionName')">
<el-input v-model="searchData.QuestionName" clearable style="width:120px;" />
@@ -54,7 +54,7 @@
</el-form-item>
</el-form>
<span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">
<el-button type="primary" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</span>
@@ -190,18 +190,16 @@
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" width="200" fixed="right">
<el-table-column :label="$t('common:action:action')" width="150" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -216,17 +216,17 @@
>
<template slot-scope="scope">
<el-button
circle
:title="$t('common:button:edit')"
icon="el-icon-edit-outline"
type="text"
@click="handleEdit(scope.row)"
/>
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
circle
:title="$t('common:button:delete')"
icon="el-icon-delete"
type="text"
@click="handleDelete(scope.row)"
/>
>
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- 问题名称 -->
<el-form-item :label="$t('trials:qcCfg:table:questionName')">
<el-input v-model="searchData.QuestionName" clearable style="width:120px;" />
@@ -42,13 +42,12 @@
<span style="margin-left:auto">
<el-button
:disabled="list.length === 0"
size="mini"
type="primary"
@click="preview.visible = true"
>
{{$t('common:button:preview')}}
</el-button>
<el-button type="primary" size="mini" @click="handleAdd">{{$t('common:button:new')}}</el-button>
<el-button type="primary" @click="handleAdd">{{$t('common:button:new')}}</el-button>
</span>
</div>
@@ -136,15 +135,13 @@
<el-table-column :label="$t('common:action:action')" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -204,24 +204,21 @@
<template slot-scope="scope">
<el-button
v-if="isCompleteConfig"
type="primary"
size="mini"
type="text"
@click="handleLook(scope.row)"
>
{{ $t('trials:readingPeriod:button:view') }}
</el-button>
<el-button
v-if="!isCompleteConfig"
type="primary"
size="mini"
type="text"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
v-if="!isCompleteConfig"
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
@@ -1,7 +1,7 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- 是否需要回执 -->
<el-form-item :label="$t('trials:emailManageCfg:title:isReturnRequired')" v-if="!systemLevel">
<el-select
@@ -139,7 +139,7 @@
</el-form-item>
</el-form>
<span style="margin-left: auto">
<el-button type="primary" size="mini" @click="handleExport">
<el-button type="primary" @click="handleExport">
{{ $t('common:button:export') }}
</el-button>
<!-- <el-button
@@ -148,7 +148,7 @@
>
场景配置
</el-button> -->
<el-button type="primary" size="mini" @click="handleAdd">
<el-button type="primary" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</span>
+3 -3
View File
@@ -3,7 +3,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dictionary:file:search:Name')">
<el-input v-model="searchData.Name" style="width: 100px" />
</el-form-item>
@@ -95,7 +95,7 @@
</el-form-item>
</el-form>
<span style="margin-left: auto">
<el-button type="primary" size="mini" @click="handleAdd">
<el-button type="primary" @click="handleAdd">
{{ $t('dictionary:browser:button:add') }}
</el-button>
</span>
@@ -241,7 +241,7 @@ const searchDataDefault = () => {
PageIndex: 1,
PageSize: 20,
asc: false,
sortField: 'CreateTime',
sortField: '',
}
}
export default {
+1 -2
View File
@@ -2,7 +2,7 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form :inline="true" class="base-search-form">
<!-- Code -->
<el-form-item :label="$t('dictionary:sign:label:code')">
<el-input v-model="searchData.Code" style="width:100px;" />
@@ -27,7 +27,6 @@
<span style="margin-left:auto;">
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
{{ $t('common:button:new') }}
+3 -6
View File
@@ -111,14 +111,12 @@
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
size="mini"
icon="el-icon-refresh-left"
@click="handleReset"
>
@@ -135,7 +133,6 @@
</el-form-item>
<el-button
type="primary"
size="mini"
@click="resolve"
style="float: right"
v-if="level > 7"
@@ -205,7 +202,7 @@
<el-table-column
:label="$t('feedBack:form:role')"
prop="FeedBackUserName"
min-width="80"
min-width="100"
show-overflow-tooltip
sortable="custom"
v-if="level > 7"
@@ -273,11 +270,11 @@
:label="$t('common:action:action')"
fixed="right"
prop="UserTypeShortName"
width="80"
width="100"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-button size="mini" type="text" @click="getDetail(scope.row)">
<el-button type="text" @click="getDetail(scope.row)">
{{ $t('common:button:view') }}
</el-button>
</template>
+1 -1
View File
@@ -138,7 +138,7 @@
<script>
import { getNoneDicomStudyList, setNodicomStudyState } from '@/api/trials'
import store from '@/store'
import pdf from '@/assets/pdf.jpg'
import pdf from '@/assets/pdf.png'
import zip from '@/assets/zip.jpg'
import { changeURLStatic } from '@/utils/history.js'
import Preview from './components/preview'
+2 -4
View File
@@ -36,13 +36,11 @@
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
{{ $t('common:button:search') }}
</el-button>
<el-button
size="mini"
icon="el-icon-refresh-left"
@click="handleReset"
>
@@ -97,10 +95,10 @@
show-overflow-tooltip
>
<template slot-scope="scope">
<el-button size="mini" type="text" @click="view(scope.row)">
<el-button type="text" @click="view(scope.row)">
{{ $t('common:button:view') }}
</el-button>
<el-button size="mini" type="text" @click="rePublish(scope.row)">
<el-button type="text" @click="rePublish(scope.row)">
{{ $t('system:event:button:rePublish') }}
</el-button>
</template>
@@ -176,7 +176,6 @@
<el-button
size="small"
type="primary"
icon="el-icon-plus"
@click="handleAdd"
>{{ $t('common:button:new') }}</el-button
>
@@ -184,9 +183,7 @@
<template slot-scope="scope">
<!-- 删除 -->
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.$index)"
>{{ $t('common:button:delete') }}</el-button
>
+1 -22
View File
@@ -22,7 +22,6 @@
<el-form-item :label="$t('system:l18n:search:Module')">
<el-input
v-model="searchData.Module"
size="small"
clearable
style="width: 130px"
/>
@@ -30,7 +29,6 @@
<el-form-item :label="$t('system:l18n:search:Code')">
<el-input
v-model="searchData.Code"
size="small"
clearable
style="width: 130px"
/>
@@ -38,7 +36,6 @@
<el-form-item :label="$t('system:l18n:search:ValueCN')">
<el-input
v-model="searchData.ValueCN"
size="small"
clearable
style="width: 130px"
/>
@@ -46,7 +43,6 @@
<el-form-item :label="$t('system:l18n:search:Value')">
<el-input
v-model="searchData.Value"
size="small"
style="width: 130px"
clearable
/>
@@ -69,7 +65,6 @@
<el-form-item :label="$t('system:l18n:search:Description')">
<el-input
v-model="searchData.Description"
size="small"
clearable
style="width: 130px"
/>
@@ -117,14 +112,12 @@
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
size="mini"
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
@@ -133,24 +126,18 @@
</el-button>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>
{{ $t('common:button:new') }}
</el-button>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleBatchAdd"
>
{{ $t('system:l18n:button:batchAdd') }}
</el-button>
<el-button
type="primary"
icon="el-icon-edit-outline"
size="mini"
:disabled="selectTableList.length <= 0"
@click="handleBatchUpdate"
>
@@ -158,17 +145,13 @@
</el-button>
<el-button
type="primary"
icon="el-icon-edit-outline"
size="mini"
:disabled="selectTableList.length <= 0"
@click="handleBatchUpdateToChange"
>
{{ $t('system:l18n:button:batchEdit') }}
</el-button>
<el-button
size="mini"
type="primary"
icon="el-icon-download"
@click="exportTable"
>
{{ $t('common:button:export') }}
@@ -275,7 +258,7 @@
<el-table-column
:label="$t('system:l18n:search:Description')"
prop="Description"
min-width="100"
min-width="110"
show-overflow-tooltip
sortable="custom"
/>
@@ -309,18 +292,14 @@
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
:disabled="scope.row.State === 1"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
+4 -10
View File
@@ -3,22 +3,21 @@
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item :label="$t('system:log:table:version')" prop="Version">
<el-input v-model="searchData.Version" size="small" clearable />
<el-input v-model="searchData.Version" clearable />
</el-form-item>
<el-form-item :label="$t('system:log:table:versionUS')" prop="Version">
<el-input v-model="searchData.Version_US" size="small" clearable />
<el-input v-model="searchData.Version_US" clearable />
</el-form-item>
<el-form-item
:label="$t('system:log:table:UpdateContent')"
prop="UpdateContent"
>
<el-input v-model="searchData.UpdateContent" size="small" clearable />
<el-input v-model="searchData.UpdateContent" clearable />
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
{{ $t('common:button:search') }}
@@ -26,7 +25,6 @@
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>
{{ $t('common:button:new') }}
@@ -102,22 +100,18 @@
:label="$t('common:action:action')"
fixed="right"
prop=""
min-width="200"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>
{{ $t('common:button:edit') }}
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>
{{ $t('common:button:delete') }}
-11
View File
@@ -6,7 +6,6 @@
v-model="queryParams.menuName"
placeholder=""
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
@@ -15,21 +14,18 @@
v-model="queryParams.visible"
placeholder=""
clearable
size="small"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>{{ $t("system:menu:button:search") }}</el-button
>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>{{ $t("system:menu:button:add") }}</el-button
>
@@ -40,7 +36,6 @@
type="info"
plain
icon="el-icon-sort"
size="mini"
@click="toggleExpandAll"
>{{ $t("system:menu:button:foldAndExpand") }}</el-button
>
@@ -154,25 +149,19 @@
<template slot-scope="scope">
<el-button
v-hasPermi="['system:menu:edit']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>{{ $t("system:menu:button:edit") }}</el-button
>
<el-button
v-hasPermi="['system:menu:add']"
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
>{{ $t("system:menu:button:add") }}</el-button
>
<el-button
v-hasPermi="['system:menu:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>{{ $t("system:menu:button:remove") }}</el-button
>
+7 -13
View File
@@ -3,7 +3,7 @@
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item :label="$t('system:notice:label:NoticeLevel')" prop="NoticeLevelEnum">
<el-select v-model="searchData.NoticeLevelEnum" clearable size="small">
<el-select v-model="searchData.NoticeLevelEnum" clearable>
<el-option
v-for="item of $d.NoteLevel"
:key="item.value"
@@ -13,7 +13,7 @@
</el-select>
</el-form-item>
<el-form-item :label="$t('system:notice:label:NoticeType')" prop="NoticeTypeEnum">
<el-select v-model="searchData.NoticeTypeEnum" clearable size="small">
<el-select v-model="searchData.NoticeTypeEnum" clearable>
<el-option
v-for="item of $d.NoteType"
:key="item.value"
@@ -23,7 +23,7 @@
</el-select>
</el-form-item>
<el-form-item :label="$t('system:notice:label:ApplicableProject')" prop="ApplicableProjectEnum">
<el-select v-model="searchData.ApplicableProjectEnum" clearable size="small">
<el-select v-model="searchData.ApplicableProjectEnum" clearable>
<el-option
v-for="item of $d.NoticeApplicableTrial"
:key="item.value"
@@ -33,7 +33,7 @@
</el-select>
</el-form-item>
<el-form-item :label="$t('system:notice:label:NoticeUserTypeIdList')" prop="NoticeUserTypeIdList">
<el-select v-model="searchData.NoticeUserTypeIdList" multiple clearable size="small">
<el-select v-model="searchData.NoticeUserTypeIdList" multiple clearable>
<el-option
v-for="item of roleList"
:key="item.Id"
@@ -43,7 +43,7 @@
</el-select>
</el-form-item>
<el-form-item :label="$t('system:notice:label:NoticeMode')" prop="NoticeModeEnum">
<el-select v-model="searchData.NoticeModeEnum" clearable size="small">
<el-select v-model="searchData.NoticeModeEnum" clearable>
<el-option
v-for="item of $d.NoticeMode"
:key="item.value"
@@ -53,8 +53,8 @@
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">{{ $t('common:button:search') }}</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">{{ $t('common:button:add') }}</el-button>
<el-button type="primary" icon="el-icon-search" @click="getList">{{ $t('common:button:search') }}</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">{{ $t('common:button:add') }}</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" v-adaptive="{bottomOffset:45}" height="100" :data="list" class="table">
@@ -116,23 +116,17 @@
<el-table-column :label="$t('common:action:action')" fixed="right" prop="UserTypeShortName" min-width="200" show-overflow-tooltip>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>{{$t('common:action:edit')}}</el-button>
<el-button
v-if="scope.row.NoticeStateEnum === 0"
size="mini"
type="text"
icon="el-icon-s-promotion"
@click="handlePush(scope.row)"
>{{$t('common:action:push')}}</el-button>
<el-button
v-if="scope.row.NoticeStateEnum === 1"
size="mini"
type="text"
icon="el-icon-s-release"
@click="handleGet(scope.row)"
>{{$t('common:action:pull')}}</el-button>
</template>
+1 -8
View File
@@ -6,12 +6,11 @@
<el-input
v-model="queryParams.SearchFilter"
clearable
size="small"
@keyup.enter.native="getList"
/>
</el-form-item>
<el-form-item :label="$t('system:role:title:Group')">
<el-select v-model="queryParams.GroupId" clearable size="small">
<el-select v-model="queryParams.GroupId" clearable>
<el-option
v-for="item of dict.type.UserTypeGroup"
:key="item.value"
@@ -24,7 +23,6 @@
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>{{ $t('common:button:search') }}</el-button
>
@@ -32,7 +30,6 @@
v-hasPermi="['system:role:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAddRole"
>{{ $t('common:button:add') }}</el-button
>
@@ -111,17 +108,13 @@
<template slot-scope="scope">
<el-button
v-hasPermi="['system:role:edit']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleEditRole(scope.row)"
>{{ $t('common:button:edit') }}</el-button
>
<el-button
v-hasPermi="['system:role:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteRole(scope.row)"
>{{ $t('common:button:delete') }}</el-button
>
@@ -227,7 +227,7 @@
<template slot-scope="scope">
<!-- 详情 -->
<el-button
circle
type="text"
:disabled="
(scope.row.TrialStatusStr === 'Initializing' &&
!hasPermi(['role:pm'])) ||
@@ -240,10 +240,10 @@
hasPermi(['role:pm'])
))
"
icon="el-icon-info"
:title="$t('system:retrospect:table:detail')"
@click.stop="handleDetail(scope.row)"
/>
>
{{ $t('system:retrospect:table:detail') }}
</el-button>
</template>
</el-table-column>
</el-table>
+2 -3
View File
@@ -2,7 +2,6 @@
<box-content>
<div class="search" style="position: relative">
<SearchForm
size="mini"
:that="this"
:search-data="searchData"
:search-form="searchForm"
@@ -249,12 +248,12 @@ export default {
operates: [
{
name: this.$t('common:button:edit'),
type: 'primary',
type: 'text',
emitKey: 'editCb',
},
{
name: this.$t('common:button:email'),
type: 'primary',
type: 'text',
emitKey: 'sendCb',
show: 'IsFirstAdd',
},
+4 -4
View File
@@ -94,8 +94,8 @@ export const columns = [
label: 'Action',
minWidth: 200,
operates: [
{ name: 'Edit', type: 'primary', emitKey: 'editCb' },
{ name: 'Delete', type: 'danger', emitKey: 'deleteCb' }
{ name: 'Edit', type: 'text', emitKey: 'editCb' },
{ name: 'Delete', type: 'text', emitKey: 'deleteCb' }
] }
]
@@ -180,6 +180,6 @@ export const searchForm = [
]
// 用户列表查询表单事件配置信息
export const searchHandle = [
{ label: 'Reset', type: 'primary', emitKey: 'reset' },
{ label: 'Search', type: 'primary', emitKey: 'search' }
{ label: 'Reset', type: 'text', emitKey: 'reset' },
{ label: 'Search', type: 'text', emitKey: 'search' }
]
+12 -1
View File
@@ -620,7 +620,18 @@
]"
circle
icon="el-icon-folder-opened"
:disabled="scope.row.IsDeleted"
:disabled="
(scope.row.TrialStatusStr === 'Initializing' &&
!hasPermi(['role:pm'])) ||
scope.row.IsDeleted ||
((scope.row.TrialStatusStr === 'Completed' ||
scope.row.TrialStatusStr === 'Stopped') &&
!(
hasPermi(['role:qa']) ||
hasPermi(['role:ea']) ||
hasPermi(['role:pm'])
))
"
:title="$t('trials:trials-list:action:trialDocument')"
@click.stop="toTrialDocument(scope.row)"
/>
@@ -425,6 +425,8 @@ export default {
this.loading = true
if (this.viewStatus) {
this.searchData.IsConfirmed = true
}
if (this.isDoc) {
let IR = this.userTypeOptions.find((item) => item.UserTypeEnum == 13)
if (IR) {
this.searchData.UserTypeId = IR.Id
@@ -291,21 +291,33 @@
:label="$t('trials:seletctedReviews:table:institution')"
show-overflow-tooltip
width="150"
/>
>
<template slot-scope="scope">
<span>{{ isEN?scope.row.HospitalName:scope.row.HospitalNameCN }}</span>
</template>
</el-table-column>
<!-- City -->
<el-table-column
prop="City"
:label="$t('trials:seletctedReviews:table:city')"
show-overflow-tooltip
width="150"
/>
>
<template slot-scope="scope">
<span>{{ isEN?scope.row.City:scope.row.CityCN }}</span>
</template>
</el-table-column>
<!-- Country -->
<el-table-column
prop="Country"
:label="$t('trials:seletctedReviews:table:country')"
show-overflow-tooltip
width="150"
/>
>
<template slot-scope="scope">
<span>{{ isEN?scope.row.Country:scope.row.CountryCN }}</span>
</template>
</el-table-column>
<!-- Selector -->
<el-table-column
prop="OptUserName"
@@ -712,7 +712,7 @@ export default {
this.loading = false
} catch (e) {
this.loading = false
this.$refs['signForm'].btnLoading = false
this.$refs['signForm'] ? this.$refs['signForm'].btnLoading = false : ''
}
},
handleViewDetail(visitTaskId) {
@@ -18,7 +18,6 @@
</div>
</div>
<el-form-item
v-for="qs in questions"
v-show="qs.ShowQuestion!==2"
@@ -45,41 +44,41 @@
</template>
</el-input>
<!-- 测量 -->
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && !questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && !questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
@click="addAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:measure')}}
{{ $t('trials:MRIPDFF:button:measure') }}
</el-button>
<!-- 清除标记 -->
<el-button
v-if="getAnnotationStatus(qs) && readingTaskState!== 2"
size="mini"
type="text"
@click="removeAnnotation(qs)"
<el-button
v-if="getAnnotationStatus(qs) && readingTaskState!== 2"
size="mini"
type="text"
style="margin-left: 0px"
@click="removeAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:clear')}}
{{ $t('trials:MRIPDFF:button:clear') }}
</el-button>
<!-- 返回 -->
<el-button
v-if="questionForm[qs.Id]"
size="mini"
type="text"
@click="locateAnnotation(qs)"
<el-button
v-if="questionForm[qs.Id]"
size="mini"
type="text"
style="margin-left: 0px"
@click="locateAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:return')}}
{{ $t('trials:MRIPDFF:button:return') }}
</el-button>
<!-- 保存 -->
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
@click="saveAnnotation(qs)"
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
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">
@@ -279,7 +278,7 @@ export default {
},
mounted() {
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.initForm()
DicomEvent.$on('handleImageQualityAbnormal', () => {
@@ -295,26 +294,29 @@ export default {
this.isMeasurableId = this.getQuestionId(1105)
// const loading = this.$loading({ fullscreen: true })
this.questions.forEach(item => {
var val = this.answers[item.Id]
if (item.DictionaryCode) {
val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id])
if (this.answers.hasOwnProperty(item.Id)) {
let val = this.answers[item.Id]
if (item.DictionaryCode) {
val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id])
}
this.$set(this.questionForm, item.Id, val)
} else {
this.$set(this.questionForm, item.Id, '')
}
this.$set(this.questionForm, item.Id, val)
})
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, 'RowId', this.answers.RowId ? this.answers.RowId : '')
//
if (this.isCurrentTask && this.readingTaskState < 2) {
let arr = JSON.parse(this.answers.TableQuestionMarkList)
let isExitsMarks = arr.findIndex(i=>i.MeasureData) > -1
const arr = JSON.parse(this.answers.TableQuestionMarkList)
const isExitsMarks = arr.findIndex(i => i.MeasureData) > -1
if (isExitsMarks && parseInt(this.questionForm[this.isMeasurableId]) === 0) {
this.$set(this.questionForm, this.isMeasurableId, 1)
}
}
// saveTypeEnum 01访/2
let isMeasurable = this.getQuestionVal(1105)
const isMeasurable = this.getQuestionVal(1105)
const mean = this.getQuestionVal(1104)
if (this.questionForm.saveTypeEnum !== 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.$set(this.questionForm, 'saveTypeEnum', parseInt(isMeasurable) === 1 && isNaN(parseFloat(mean)) ? 1 : 2)
@@ -325,11 +327,11 @@ export default {
this.markList = []
this.isExitsMarks = false
this.isDisabledMeasurableRadio = false
let seg = this.getQuestionVal(1106)
const seg = this.getQuestionVal(1106)
this.liverSeg = this.$fd('LiverSegmentation', seg)
if (this.answers.TableQuestionMarkList) {
let arr = JSON.parse(this.answers.TableQuestionMarkList)
arr.map(i=>{
const arr = JSON.parse(this.answers.TableQuestionMarkList)
arr.map(i => {
if (i.MeasureData) {
this.isExitsMarks = true
if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1 && this.isCurrentTask && this.readingTaskState < 2) {
@@ -337,15 +339,15 @@ export default {
}
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) {
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
}
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
if (this.questionForm.saveTypeEnum === 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.setQuestions()
}
@@ -357,13 +359,13 @@ export default {
// I II III IV V VI VII VIII
// L-I-01 L-I-02 L-I-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 segmentId = this.getQuestionId(1106)
const segmentId = this.getQuestionId(1106)
let segmentVal = this.answers[segmentId]
segmentVal = segmentVal ? parseInt(segmentVal) : null
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}`
}
return lessionName
@@ -397,18 +399,18 @@ export default {
this.$set(this.questionForm, 'saveTypeEnum', 1)
const mean = this.getQuestionVal(1104)
if (qs.QuestionMark === 1101 || qs.QuestionMark === 1102 || qs.QuestionMark === 1103) {
let newMean = this.getMean()
const newMean = this.getMean()
if (newMean !== mean) {
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
}
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
} else if (qs.QuestionMark === 1105) {
if (!v) {
let meanId = this.getQuestionId(1104)
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
} else {
let mean = this.getMean()
let meanId = this.getQuestionId(1104)
const mean = this.getMean()
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, mean)
}
}
@@ -418,10 +420,10 @@ export default {
let mean = null
let isMeasurable = this.getQuestionVal(1105)
isMeasurable = !isNaN(parseInt(isMeasurable)) ? parseInt(isMeasurable) : null
let l1 = this.getQuestionVal(1101)
let l2 = this.getQuestionVal(1102)
let l3 = this.getQuestionVal(1103)
if ( isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) {
const l1 = this.getQuestionVal(1101)
const l2 = this.getQuestionVal(1102)
const l3 = this.getQuestionVal(1103)
if (isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) {
const sum = l1 + l2 + l3
mean = sum / 3
return parseFloat(mean.toFixed(this.digitPlaces))
@@ -442,7 +444,7 @@ export default {
//
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))
data = {
Id: '',
@@ -461,17 +463,17 @@ export default {
}
store.dispatch('reading/addMeasuredData', { visitTaskId: this.visitTaskId, data: data })
let mean = this.getQuestionVal(1104)
let newMean = this.getMean()
const newMean = this.getMean()
if (newMean !== mean) {
mean = newMean
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
const isMeasurable = this.getQuestionVal(1105)
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) {
this.markList.push({tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0})
this.markList.push({ tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0 })
} else {
this.markList[i].saveEnum = 0
this.markList[i].measureData = data
@@ -486,19 +488,19 @@ export default {
},
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) {
this.$alert(this.$t('trials:MRIPDFF:message:message3'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message3'))
return
}
let orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark)
const orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark)
this.activeQuestionId = qs.Id
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 }})
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 }})
},
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) {
return this.markList[i].saveEnum
} else {
@@ -506,7 +508,7 @@ export default {
}
},
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) {
return true
} else {
@@ -516,14 +518,13 @@ export default {
getIsExitsMarks() {
const isMeasurable = this.getQuestionVal(1105)
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 {
return false
}
},
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 })
//
const confirm = await this.$confirm(
@@ -534,27 +535,27 @@ export default {
}
)
if (confirm !== 'confirm') return
let measureData = Object.assign({}, this.markList[i].measureData)
const measureData = Object.assign({}, this.markList[i].measureData)
if (measureData.Id) {
await deleteSingleTableQuestionMark({Id: measureData.Id}, 11)
await deleteSingleTableQuestionMark({ Id: measureData.Id }, 11)
}
// 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')
this.markList[i].measureData = null
this.markList[i].saveEnum = 0
//
this.$set(this.questionForm, this.markList[i].tableQuestionId, '')
let meanId = this.getQuestionId(1104)
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, '')
this.isDisabledMeasurableRadio = this.getIsExitsMarks()
this.$set(this.questionForm, 'saveTypeEnum', 1)
this.setQuestions()
},
locateAnnotation(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
let measureData = this.markList[i].measureData
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
const measureData = this.markList[i].measureData
//
var markTool = 'Probe'
var readingTaskState = this.readingTaskState
@@ -569,18 +570,18 @@ export default {
async saveAnnotation(qs) {
const loading = this.$loading({ fullscreen: true })
try {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
let params = {}
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 => {
params = Object.assign({}, this.markList[i].measureData)
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) : ''
}
let tableQuestionId = this.markList[i].tableQuestionId
const tableQuestionId = this.markList[i].tableQuestionId
params.Answer = this.questionForm[tableQuestionId]
params.MeasureData = JSON.stringify(this.markList[i].measureData.MeasureData)
loading.close()
@@ -588,13 +589,13 @@ export default {
})
} else {
params = {
Answer: "",
Answer: '',
VisitTaskId: this.visitTaskId,
QuestionId: this.parentQsId,
InstanceId: '',
SeriesId: '',
StudyId: '',
MarkTool:'',
MarkTool: '',
PicturePath: '',
NumberOfFrames: 0,
MeasureData: '',
@@ -607,9 +608,7 @@ export default {
loading.close()
this.saveTableQuestionInfo(params, qs)
}
} catch(e) {
} catch (e) {
console.log(e)
loading.close()
}
@@ -617,16 +616,16 @@ export default {
async saveTableQuestionInfo(params, qs) {
const loading = this.$loading({ fullscreen: true })
try {
let res = await saveTableQuestionMark(params, 11)
const res = await saveTableQuestionMark(params, 11)
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
//
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) {
let 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 answers = []
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) {
if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
@@ -634,7 +633,7 @@ export default {
}
}
}
let params = {
const params = {
questionId: this.parentQsId,
rowId: this.questionForm.RowId,
rowIndex: this.answers.RowIndex,
@@ -659,7 +658,7 @@ export default {
DicomEvent.$emit('setMeasuredToolsPassive')
loading.close()
}
} catch(e) {
} catch (e) {
console.log(e)
loading.close()
}
@@ -735,43 +734,43 @@ export default {
async handleSave() {
try {
const valid = await this.$refs.measurementForm.validate()
if (!valid) return
if (parseInt(this.questionForm[this.isMeasurableId]) === 1) {
if (!valid) return
if (parseInt(this.questionForm[this.isMeasurableId]) === 1) {
//
let i = this.markList.findIndex(i=>i.saveEnum === 0)
if (i > -1) {
const i = this.markList.findIndex(i => i.saveEnum === 0)
if (i > -1) {
//
this.$alert(this.$t('trials:MRIPDFF:message:message1'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message1'))
return
}
} else {
this.$alert(this.$t('trials:MRIPDFF:message:message1'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message1'))
return
}
} else {
//
// ''
const confirm = await this.$confirm(
this.$t('trials:MRIPDFF:message:message2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
let l1Id = this.getQuestionId(1101)
this.$set(this.questionForm, l1Id, '')
let l2Id = this.getQuestionId(1102)
this.$set(this.questionForm, l2Id, '')
let l3Id = this.getQuestionId(1103)
this.$set(this.questionForm, l3Id, '')
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
}
const loading = this.$loading({ fullscreen: true })
const confirm = await this.$confirm(
this.$t('trials:MRIPDFF:message:message2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const l1Id = this.getQuestionId(1101)
this.$set(this.questionForm, l1Id, '')
const l2Id = this.getQuestionId(1102)
this.$set(this.questionForm, l2Id, '')
const l3Id = this.getQuestionId(1103)
this.$set(this.questionForm, l3Id, '')
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
}
try {
const loading = this.$loading({ fullscreen: true })
try {
// let isResetMarks = this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false
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 => {
if (i.measureData && i.measureData.MeasureData) {
i.measureData = ''
@@ -19,12 +19,21 @@
class="dicom-desc"
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>
<span>{{ study.StudyCode }} {{ study.Description }}</span>
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<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>
</el-tooltip>
</div>
</template>
@@ -205,7 +214,8 @@ export default {
srDialogVisible: false,
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1
visitTaskIdx: -1,
taskInfo: null
}
},
@@ -243,6 +253,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
@@ -76,7 +76,7 @@
<el-input
v-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2"
:disabled="question.TableQuestionType === 2 || readingTaskState === 2"
/>
<!-- 多行文本输入框 -->
<el-input
@@ -84,13 +84,14 @@
v-model="questionForm[question.Id]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="readingTaskState === 2"
/>
<!-- 下拉框 -->
<el-select
v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
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)})"
>
<template v-if="question.TableQuestionType === 1">
@@ -132,6 +133,7 @@
v-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
@change="((val)=>{formItemChange(val, question)})"
:disabled="readingTaskState === 2"
>
<el-radio
v-for="val in question.TypeValue.split('|')"
@@ -145,6 +147,7 @@
<el-checkbox-group
v-if="question.Type==='checkbox'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState === 2"
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
@@ -158,12 +161,12 @@
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
@@ -176,7 +179,7 @@
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
@@ -190,7 +193,7 @@
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 4"
type="number"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
v-model="questionForm[question.Id]"
@change="(val) => { formItemNumberChange(val, question) }"
/>
@@ -215,6 +218,7 @@
v-model="questionForm[question.Id]"
clearable
@change="(val) => { formItemNumberChange(val, question) }"
:disabled="readingTaskState === 2"
>
<el-option
v-for="val in question.TypeValue.split('|')"
@@ -229,8 +233,9 @@
@change="(val) => { formItemNumberChange(val, question) }"
@blur="handleBlur(questionForm[question.Id], 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-else-if="question.ValueType === 2">%</template>
</el-input>
@@ -238,16 +243,17 @@
type="number"
v-if="question.Type === 'number' && !question.TypeValue && question.DataSource === 1"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
:disabled="question.DataSource === 1"
:disabled="question.DataSource === 1 || readingTaskState === 2"
v-model="questionForm[question.Id]"
>
<template slot="append">2</template>
<!-- <template slot="append">2</template> -->
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
<template slot="append" v-else-if="question.ValueType === 2">%</template>
</el-input>
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='upload'"
:disabled="readingTaskState === 2"
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
@@ -258,7 +264,7 @@
:file-list="fileList"
: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')}}
</el-button>
</el-upload>
@@ -337,16 +343,37 @@
</el-button>
</template>
</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>
</template>
<script>
import { uploadReadingAnswerImage, getTrialOrganList, deleteReadingRowAnswer, getCustomTableQuestionPreview, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials'
import QuestionTableFormItem from './CustomizeQuestionTableFormItem'
import BaseModel from '@/components/BaseModel'
import PreviewFile from '@/components/PreviewFile/index'
import DicomEvent from './../components/DicomEvent'
export default {
name: 'CustomizeQuestionFormItem',
components: { QuestionTableFormItem, BaseModel },
components: { QuestionTableFormItem, BaseModel, PreviewFile },
props: {
IsBaseline: {
type: Boolean,
@@ -398,7 +425,10 @@ export default {
RowId: null,
digitPlaces: 2,
CalculationTabelList: [],
classArr: []
classArr: [],
previewVisible: false,
currentPath: '',
currentType: ''
}
},
watch: {
@@ -422,6 +452,13 @@ export default {
this.formItemNumberChange(this.question.Id, false)
}
},
readingTaskState: {
deep: true,
immediate: true,
handler(v, oldv) {
console.log(v)
}
}
},
mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
@@ -547,6 +584,7 @@ export default {
this.$set(this.QuestionsForm, obj.key, null)
},
handleSave() {
console.log('tableQsForm')
this.$refs.tableQsForm.validate(valid => {
if (!valid) return
const loading = this.$loading({ fullscreen: true })
@@ -612,6 +650,7 @@ export default {
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
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.formItemNumberChange(this.question.Id, true)
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)
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.$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()
// uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// if (res.IsSuccess) {
@@ -972,7 +1012,10 @@ export default {
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')
// window.open(this.OSSclientConfig.basePath + file.url,'_blank')
this.currentPath = file.url
this.currentType = suffix
this.previewVisible = true
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
@@ -986,8 +1029,12 @@ export default {
if (file && file.status === "success") {
this.imageUrl = ''
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.$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('|') : '')
}
}
}
@@ -20,7 +20,7 @@
:prop="question.Id"
:rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
message: '请注明', trigger: ['blur', 'change']},
message: $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
>
@@ -77,6 +77,7 @@ export default {
methods: {
handleSave(isMsg) {
return new Promise(resolve => {
console.log('handleSave')
this.$refs['questions'].validate((valid) => {
if (!valid) {
resolve(false)
@@ -232,7 +233,9 @@ export default {
this.questionForm[v] = ''
},
setFormItemData(obj) {
console.log('setFormItemData', obj)
this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
console.log(this.questionForm)
this.classArr.map(i=>{
if (i.triggerId === obj.key) {
let answer = null
@@ -194,7 +194,7 @@
</template>
</template>
<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)"
:visitTaskId="visitTaskId"
:question="scope.row"
@@ -202,8 +202,8 @@
:readingTaskState="readingTaskState"
: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)}"
></CustomizeReportPageUpload>
<CustomizeReportPageUpload
></customize-report-page-upload>
<customize-report-page-upload
v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId"
:question="scope.row"
@@ -211,25 +211,25 @@
:readingTaskState="readingTaskState"
:initUrl="questionForm[scope.row.QuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
></CustomizeReportPageUpload>
></customize-report-page-upload>
</template>
<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)"
:visitTaskId="visitTaskId"
:question="scope.row"
:task="task"
:readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload>
<CustomizeReportPageUpload
></customize-report-page-upload>
<customize-report-page-upload
v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId"
:question="scope.row"
:task="task"
:readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload>
></customize-report-page-upload>
</template>
<template v-else-if="scope.row.QuestionType=== 22">
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
@@ -276,6 +276,7 @@
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code'
@@ -736,15 +737,16 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
submitDicomVisitTask(params).then(res => {
try {
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
let res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
@@ -752,41 +754,36 @@ export default {
}
this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
//
this.readingTaskState = 2
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
const res = await getAutoCutNextTask()
let isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.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()
})
.catch(action => {
})
}
}
this.loading = false
}).catch(() => {
} catch(e) {
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
})
}
},
previewDicoms(task) {
var token = getToken()
@@ -19,12 +19,20 @@
class="dicom-desc"
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>
<span>{{ study.StudyCode }} {{ study.Description }}</span>
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
<div>
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span>{{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
</el-tooltip>
<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>
</template>
@@ -212,7 +220,8 @@ export default {
srDialogVisible: false,
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1
visitTaskIdx: -1,
taskInfo: null
}
},
@@ -250,6 +259,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
@@ -339,6 +339,7 @@ export default {
localStorage.setItem('CriterionType', res.Result.CriterionType)
localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
this.readingCategory = res.Result.ReadingCategory
this.questionFormChangeState = false
this.questionFormChangeNum = 0
@@ -66,7 +66,8 @@ export default function(evt) {
draw(context, context => {
// Configurable shadow
setShadow(context, this.configuration)
// Draw perpendicular line
const strokeWidth = lineWidth
const {
start,
end,
@@ -86,9 +87,6 @@ export default function(evt) {
// Draw the measurement line
drawLine(context, element, start, end, lineOptions)
// Draw perpendicular line
const strokeWidth = lineWidth
updatePerpendicularLineHandles(eventData, data)
drawLine(
@@ -10,9 +10,13 @@ const getNewContext = cornerstoneTools.import('drawing/getNewContext')
const draw = cornerstoneTools.import('drawing/draw')
const drawHandles = cornerstoneTools.import('drawing/drawHandles')
const drawTextBox = cornerstoneTools.import('drawing/drawTextBox')
const drawLink = cornerstoneTools.import('drawing/drawLink')
const drawLinkedTextBox = cornerstoneTools.import('drawing/drawLinkedTextBox')
// Utilities
const getRGBPixels = cornerstoneTools.import('util/getRGBPixels')
const calculateSUV = cornerstoneTools.import('util/calculateSUV')
const getROITextBoxCoords = cornerstoneTools.import('util/getROITextBoxCoords')
// import { probeCursor } from '../cursors/index.js';
// import { getLogger } from '../../util/logger.js';
const throttle = cornerstoneTools.import('util/throttle')
@@ -20,6 +24,8 @@ const getModule = cornerstoneTools.getModule
const getPixelSpacing = cornerstoneTools.import('util/getPixelSpacing')
// import numbersWithCommas from './../../util/numbersWithCommas.js';
const numbersWithCommas = cornerstoneTools.import('util/numbersWithCommas')
const clipBoxToDisplayedArea = cornerstoneTools.import('util/clip')
// const logger = getLogger('tools:annotation:ProbeTool');
import calculateEllipseStatistics from './calculateEllipseStatistics'
import getCircleCoords from './getCircleCoords'
@@ -31,6 +37,19 @@ import getCircleCoords from './getCircleCoords'
* desired position.
* @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 {
constructor(props = {}) {
const defaultProps = {
@@ -64,7 +83,8 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
return;
}
const { x, y } = eventData.currentPoints.image
return {
visible: true,
active: true,
@@ -84,6 +104,23 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
active: true,
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 => {
const color = toolColors.getColorIfActive(data);
const lineWidth = toolStyle.getToolWidth()
if (this.configuration.drawHandles) {
// Draw the handles
let radius = getCanvasRadius(data.handles, fixedRadius, element, pixelSpacing)
@@ -273,28 +310,133 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
}
let r = getPixelRadius(fixedRadius, pixelSpacing)
// Coords for text
const coords = {
// Translate the x/y away from the cursor
x: data.handles.end.x + r,
y: data.handles.end.y - r,
};
const textCoords = external.cornerstone.pixelToCanvas(
eventData.element,
coords
);
drawTextBox(
if (!data.handles.hasOwnProperty('textBox')) {
const coords = {
// Translate the x/y away from the cursor
x: data.handles.end.x + r,
y: data.handles.end.y - r,
};
const textCoords = external.cornerstone.pixelToCanvas(
eventData.element,
coords
);
drawTextBox(
context,
textLines,
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,
textCoords.x,
textCoords.y ,
color
);
// drawTextBox(context, '', textCoords.x, textCoords.y, color);
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) {
return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';
}
@@ -442,7 +442,7 @@ export default {
this.loading = false
} catch (e) {
this.loading = false
this.$refs['signForm'].btnLoading = false
this.$refs['signForm'] ? this.$refs['signForm'].btnLoading = false : ''
}
},
handleView(row) {
@@ -3,35 +3,95 @@
<!-- 访视阅片 -->
<visit-review v-if="taskInfo && taskInfo.ReadingCategory=== 1" />
<!-- 全局阅片 -->
<global-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 2" />
<global-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 2"
:trial-id="trialId"
:subject-id="taskInfo.SubjectId"
:visit-task-id="taskInfo.VisitTaskId"
:reading-category="taskInfo.ReadingCategory"
:subject-code="taskInfo.SubjectCode"
:task-blind-name="taskInfo.TaskBlindName"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/>
<!-- 裁判阅片 -->
<ad-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 4" />
<ad-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 4"
:trial-id="trialId"
:subject-id="taskInfo.SubjectId"
:visit-task-id="taskInfo.VisitTaskId"
:reading-category="taskInfo.ReadingCategory"
:subject-code="taskInfo.SubjectCode"
:task-blind-name="taskInfo.TaskBlindName"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/>
<!-- 肿瘤学阅片 -->
<oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" />
<!-- <oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" /> -->
<el-dialog
:visible.sync="clinicalDataVisible"
:custom-class="isClinicalDataFullscreen?'full-dialog-container':'dialog-container'"
:show-close="false"
:close-on-click-modal="false"
:fullscreen="isClinicalDataFullscreen"
>
<span slot="title" class="dialog-footer">
<!-- 当前阅片任务存在临床数据请查看若已查看请点击确认 -->
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
<div style="position: absolute;right: 20px;top: 10px;">
<svg-icon :icon-class="isClinicalDataFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isClinicalDataFullscreen=!isClinicalDataFullscreen" />
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="clinicalDataVisible = false" />
</div>
</span>
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
<clinical-data
v-if="clinicalDataVisible"
style="flex: 1"
:trial-id="trialId"
:subject-id="taskInfo.SubjectId"
:visit-task-id="cdVisitTaskId"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
/>
<div v-if="!closeCDVisible" style="text-align:right">
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { getNextTask } from '@/api/trials'
import { getNextTask, readClinicalData } from '@/api/trials'
import store from '@/store'
import VisitReview from '@/views/trials/trials-panel/reading/visit-review'
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
// import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
export default {
name: 'ReadingViewer',
components: {
VisitReview,
GlobalReview,
AdReview,
OncologyReview
// OncologyReview
ClinicalData
},
data() {
return {
taskInfo: null,
loading: false
trialId: '',
loading: false,
clinicalDataVisible: false,
isClinicalDataFullscreen: false,
closeCDVisible: false,
cdVisitTaskId: ''
}
},
mounted() {
this.trialId = this.$route.query.trialId
this.getTaskInfo()
},
methods: {
@@ -48,22 +108,32 @@ export default {
const res = await getNextTask(params)
this.taskInfo = res.Result
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
// if (res.Result.IsExistsClinicalData && res.Result.IsNeedReadClinicalData && !res.Result.IsReadClinicalData) {
// this.isFullscreen = false
// this.dialogVisible = true
// this.cdVisitTaskId = res.Result.visitTaskId
// }
// this.$nextTick(() => {
// if (res.Result.IsFirstChangeTask && res.Result.ReadingTaskState === 0) {
// this.tipVisible = true
// }
// })
localStorage.setItem('digitPlaces', JSON.stringify(res.Result.DigitPlaces))
this.loading = false
this.$nextTick(() => {
if (this.taskInfo.IsExistsClinicalData && this.taskInfo.IsNeedReadClinicalData && !this.taskInfo.IsReadClinicalData) {
this.isClinicalDataFullscreen = false
this.clinicalDataVisible = true
this.cdVisitTaskId = this.taskInfo.VisitTaskId
}
})
} catch (e) {
console.log(e)
store.dispatch('reading/setCurrentReadingTaskState', 2)
this.loading = false
}
},
async handleConfirmCD() {
this.loading = true
var visitTaskId = this.taskInfo.VisitTaskId
try {
await readClinicalData({ visitTaskId })
this.loading = false
this.clinicalDataVisible = false
// this.closeCDVisible = true
} catch (e) {
this.loading = false
}
}
}
}
@@ -72,5 +142,22 @@ export default {
.reading-viewer-container {
width: 100%;
height: 100%;
::v-deep .dialog-container{
margin-top: 50px !important;
width:75%;
height:80%;
}
::v-deep .el-dialog__body{
padding: 10px;
height: calc(100% - 70px);
}
.el-dialog__header{
position: relative;
}
.full-dialog-container{
::v-deep .is-fullscreen .el-dialog__body{
height: calc(100% - 70px);
}
}
}
</style>
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>
<div v-loading="loading" class="ecrf-list-container">
<el-form
v-if="taskInfo"
ref="questions"
size="small"
:model="questionForm"
class="ecrf-form"
>
<FormItem
<!-- <FormItem
v-for="question of questions"
:key="question.Id"
:question="question"
@@ -16,6 +17,19 @@
:calculation-list="calculationList"
@setFormItemData="setFormItemData"
@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">
@@ -53,17 +67,18 @@
<script>
import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code'
import store from '@/store'
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'
export default {
name: 'EcrfList',
components: {
FormItem,
QuestionFormItem,
SignForm
},
props: {
@@ -88,7 +103,8 @@ export default {
activeName: 0,
classArr: [],
calculationList: [],
taskInfo: null
taskInfo: null,
isBaseline: false
}
},
computed: {
@@ -109,6 +125,7 @@ export default {
currentTaskState: {
immediate: true,
handler(state) {
console.log(state)
if (state === 2) {
this.readingTaskState = 2
}
@@ -117,45 +134,65 @@ export default {
},
mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.isBaseline = this.taskInfo.IsBaseLine
},
methods: {
async getQuestions() {
async getQuestions(visitTaskId) {
this.loading = true
try {
const param = {
readingQuestionCriterionTrialId: this.criterionId,
visitTaskId: this.visitTaskId
}
const res = await getTrialReadingQuestion(param)
const res = await getCustomTableQuestionAnswer(param)
if (res.IsSuccess) {
this.readingTaskState = res.OtherInfo.readingTaskState
this.readingTaskState = res.OtherInfo.ReadingTaskState
res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
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)
}
if (v.Type === 'table' || v.Type === 'basicTable') {
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
}
if (v.Type === 'class') {
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) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
this.loading = false
}
this.loading = false
} catch (e) {
console.log(e)
this.loading = false
}
},
setChild(obj) {
obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
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') {
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) {
this.setChild(i.Childrens)
}
@@ -169,26 +206,28 @@ export default {
console.log(e)
}
},
async handleSave() {
async handleSave(isMsg) {
const valid = await this.$refs['questions'].validate()
if (!valid) return
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 {
const res = await saveVisitTaskQuestions(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
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 (isMsg) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.loading = false
}
this.loading = false
} catch (e) {
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>
@@ -2,89 +2,110 @@
<div class="none-dicom-viewer">
<!-- tools -->
<div class="tools-wrapper">
<!-- 布局 -->
<div class="tool-item" :title="$t('trials:reading:button:layout')">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class="tools-left">
<!-- 布局 -->
<div class="tool-item" :title="$t('trials:reading:button:layout')">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- 缩放 -->
<div
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:zoom')"
@click.prevent="setToolActive('Zoom')"
>
<svg-icon icon-class="magnifier" class="svg-icon" />
</div>
<!-- 移动 -->
<div
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:move')"
@click.prevent="setToolActive('Pan')"
>
<svg-icon icon-class="move" class="svg-icon" />
</div>
<!-- 旋转 -->
<div
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:rotate')"
@click.prevent="setToolActive('PlanarRotate')"
>
<svg-icon icon-class="rotate" class="svg-icon" />
</div>
<!-- 箭头工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:arrowAnnotate')"
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
>
<svg-icon icon-class="arrow" class="svg-icon" />
</div>
<!-- 矩形工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'RectangleROI' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:RectangleRoi')"
@click.prevent="setAnnotateToolActive('RectangleROI')"
>
<svg-icon icon-class="rectangle" class="svg-icon" />
</div>
<!-- 自由曲线 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'PlanarFreehandROI' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:planarFreehandROI')"
@click.prevent="setAnnotateToolActive('PlanarFreehandROI')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</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
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:Eraser')"
@click.prevent="setAnnotateToolActive('Eraser')"
>
<svg-icon icon-class="clear" class="svg-icon" />
</div>
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Length' ? 'tool-item-active' : '']"
:title="$t('trials:nondicom-show:scale')"
@click.prevent="setAnnotateToolActive('Length')"
>
<svg-icon icon-class="length" class="svg-icon" />
</div>
<!-- 截图 -->
<!-- <div
class="tool-item"
:title="$t('trials:reading:button:screenShot')"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div> -->
<!-- 重置 -->
<div
class="tool-item"
:title="$t('trials:reading:button:reset')"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
</div>
</div>
<!-- 缩放 -->
<div
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:zoom')"
@click.prevent="setToolActive('Zoom')"
>
<svg-icon icon-class="magnifier" class="svg-icon" />
</div>
<!-- 移动 -->
<div
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:move')"
@click.prevent="setToolActive('Pan')"
>
<svg-icon icon-class="move" class="svg-icon" />
</div>
<!-- 旋转 -->
<div
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:rotate')"
@click.prevent="setToolActive('PlanarRotate')"
>
<svg-icon icon-class="rotate" class="svg-icon" />
</div>
<!-- 箭头工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:arrowAnnotate')"
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
>
<svg-icon icon-class="arrow" class="svg-icon" />
</div>
<!-- 矩形工具RectangleROITool -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'RectangleROI' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:RectangleRoi')"
@click.prevent="setAnnotateToolActive('RectangleROI')"
>
<svg-icon icon-class="rectangle" class="svg-icon" />
</div>
<!-- 自由曲线 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'PlanarFreehandROI' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:planarFreehandROI')"
@click.prevent="setAnnotateToolActive('PlanarFreehandROI')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div>
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:Eraser')"
@click.prevent="setAnnotateToolActive('Eraser')"
>
<svg-icon icon-class="clear" class="svg-icon" />
</div>
<!-- 截图 -->
<!-- <div
class="tool-item"
:title="$t('trials:reading:button:screenShot')"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div> -->
<!-- 重置 -->
<div
class="tool-item"
:title="$t('trials:reading:button:reset')"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
<div>
<el-button type="text" @click="previewConfig">{{ $t('trials:reading:button:customCfg') }}</el-button>
</div>
</div>
<!-- viewports -->
@@ -100,6 +121,7 @@
@click="activeCanvas(index)"
@mouseup="sliderMouseup($event, index)"
@mousemove="sliderMousemove($event, index)"
@mouseleave="sliderMouseleave($event, index)"
>
<div v-show="imageType.includes(v.fileType)" :ref="`canvas-${index}`" class="content">
<div class="left-top-text">
@@ -107,9 +129,8 @@
v-if="v.taskInfo.IsExistsClinicalData"
class="cd-info"
:title="$t('trials:reading:button:clinicalData')"
@click.stop="viewCD(v.taskInfo.VisitTaskId)"
>
<svg-icon icon-class="documentation" class="svg-icon" />
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon" @click.stop="viewCD(v.taskInfo.VisitTaskId)" />
</div>
<h2
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && v.taskInfo"
@@ -127,7 +148,7 @@
<div
class="arrw_icon"
:style="{ cursor: v.taskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum !== 0 ? '#fff': '#6b6b6b' }"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, -1)"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, -1, v.index)"
@dblclick.stop="preventDefault($event)"
>
<i class="el-icon-caret-left" />
@@ -138,7 +159,7 @@
<div
class="arrw_icon"
:style="{ cursor: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff': '#6b6b6b' }"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, 1)"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, 1, v.index)"
@dblclick.stop="preventDefault($event)"
>
<i class="el-icon-caret-right" />
@@ -156,9 +177,8 @@
v-if="v.taskInfo.IsExistsClinicalData"
class="cd-info"
:title="$t('trials:reading:button:clinicalData')"
@click.stop="viewCD(v.taskInfo.VisitTaskId)"
>
<svg-icon icon-class="documentation" class="svg-icon" />
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon" @click.stop="viewCD(v.taskInfo.VisitTaskId)" />
</div>
<h2
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && v.taskInfo"
@@ -176,7 +196,7 @@
<div
class="arrw_icon"
:style="{ cursor: v.taskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum !== 0 ? '#fff': '#6b6b6b' }"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, -1)"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, -1, v.index)"
@dblclick.stop="preventDefault($event)"
>
<i class="el-icon-caret-left" />
@@ -187,7 +207,7 @@
<div
class="arrw_icon"
:style="{ cursor: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff': '#6b6b6b' }"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, 1)"
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, 1, v.index)"
@dblclick.stop="preventDefault($event)"
>
<i class="el-icon-caret-right" />
@@ -203,6 +223,36 @@
</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>
</template>
<script>
@@ -213,7 +263,8 @@ import {
imageLoader,
metaData,
getRenderingEngine,
eventTarget
eventTarget,
utilities as csUtils
// getEnabledElementByIds
} from '@cornerstonejs/core'
@@ -223,6 +274,7 @@ import hardcodedMetaDataProvider from './../js/hardcodedMetaDataProvider'
import registerWebImageLoader from './../js/registerWebImageLoader'
import { mapGetters } from 'vuex'
import store from '@/store'
import Others from '@/views/trials/trials-panel/reading/dicoms/components/Others'
const { ViewportType } = Enums
const renderingEngineId = 'myRenderingEngine'
const {
@@ -235,18 +287,27 @@ const {
ArrowAnnotateTool,
RectangleROITool,
PlanarFreehandROITool,
EraserTool
SplineROITool,
EraserTool,
LengthTool
// cursors
} = cornerstoneTools
const { MouseBindings, Events: toolsEvents } = csToolsEnums
export default {
name: 'ImageViewer',
components: { Others },
props: {
relatedStudyInfo: {
type: Object,
default() {
return {}
}
},
psArr: {
type: Array,
default() {
return []
}
}
},
data() {
@@ -264,7 +325,20 @@ export default {
activeTool: '',
readingTaskState: 2,
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: {
@@ -336,6 +410,8 @@ export default {
isMove: false,
height: 0
}))
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.initLoader()
window.addEventListener('message', this.handleIframeMessage)
},
@@ -405,7 +481,9 @@ export default {
cornerstoneTools.addTool(ArrowAnnotateTool)
cornerstoneTools.addTool(RectangleROITool)
cornerstoneTools.addTool(PlanarFreehandROITool)
cornerstoneTools.addTool(SplineROITool)
cornerstoneTools.addTool(EraserTool)
cornerstoneTools.addTool(LengthTool)
viewportIds.forEach((viewportId, i) => {
const toolGroupId = `canvas-${i}`
@@ -424,12 +502,27 @@ export default {
return doneChangingTextCallback(await this.customPrompt())
}
})
toolGroup.addTool(RectangleROITool.toolName)
toolGroup.addTool(PlanarFreehandROITool.toolName, {
allowOpenContours: false
// cachedStats: false
toolGroup.addTool(RectangleROITool.toolName, {
cachedStats: false,
getTextLines: this.getRectangleROIToolTextLines
})
toolGroup.addTool(PlanarFreehandROITool.toolName, {
allowOpenContours: false,
cachedStats: false,
getTextLines: this.getPlanarFreehandROIToolTextLines
})
// const splineConfig = toolGroup.getToolConfiguration(
// splineToolName,
// 'spline'
// )
toolGroup.addTool(SplineROITool.toolName)
toolGroup.addTool(EraserTool.toolName)
toolGroup.addTool(LengthTool.toolName, {
getTextLines: this.getLengthToolTextLines,
cachedStats: false
})
toolGroup.setToolActive(StackScrollTool.toolName, {
bindings: [{ mouseButton: MouseBindings.Wheel }]
})
@@ -440,10 +533,14 @@ export default {
toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
toolGroup.setToolPassive(RectangleROITool.toolName)
toolGroup.setToolPassive(PlanarFreehandROITool.toolName)
toolGroup.setToolPassive(SplineROITool.toolName)
toolGroup.setToolPassive(LengthTool.toolName)
} else {
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
toolGroup.setToolEnabled(RectangleROITool.toolName)
toolGroup.setToolEnabled(PlanarFreehandROITool.toolName)
toolGroup.setToolEnabled(SplineROITool.toolName)
toolGroup.setToolEnabled(LengthTool.toolName)
}
toolGroup.setToolPassive(EraserTool.toolName)
})
@@ -466,16 +563,13 @@ export default {
renderHistoryAnnotations(obj) {
if (this.renderHistoryAnnotationTaskIds.includes(obj.VisitTaskId)) return
this.renderHistoryAnnotationTaskIds.push(obj.VisitTaskId)
const arr = []
// let arr = []
obj.Annotations.map(i => {
if (typeof i.MeasureData === 'string') {
const annotation = JSON.parse(i.MeasureData)
annotation.annotationId = i.Id
arr.push(annotation)
cornerstoneTools.annotation.state.addAnnotation(annotation)
if (obj.ReadingTaskState === 2) {
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
}
const annotation = i.MeasureData
annotation.annotationId = i.Id
cornerstoneTools.annotation.state.addAnnotation(annotation)
if (obj.ReadingTaskState === 2) {
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
}
})
},
@@ -498,6 +592,9 @@ export default {
const fileIndex = this.viewportInfos[i].fileList.findIndex(i => i.Path === obj.fileInfo.Path)
this.sliceIndex(fileIndex)
} else {
if (!this.imageType.includes(obj.fileInfo.FileType)) {
this.fullScreenIndex = null
}
this.updateViewportInfos(this.activeCanvasIndex, obj)
}
if (this.activeCanvasIndex === this.cells.length - 1) {
@@ -568,6 +665,11 @@ export default {
this.layout = command
this.rows = parseInt(command.split('*')[0])
this.cols = parseInt(command.split('*')[1])
if (this.rows === 1 && this.cols === 1) {
this.$nextTick(() => {
this.activeCanvas(0)
})
}
// 1*1 1*2 线* 2*2
// const obj = this.viewportInfos.find(i => i.index === this.activeCanvasIndex)
// if (obj && this.rows === 1 && this.cols === 1) {
@@ -649,12 +751,16 @@ export default {
//
toggleFullScreen(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
if (i === -1 && this.imageType.includes(this.viewportInfos[i].fileType)) return
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
this.activeCanvasIndex = index
if (i === -1) return
if (!this.viewportInfos[i].currentFileName) return
if (this.imageType.includes(this.viewportInfos[i].fileType)) {
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
this.activeCanvasIndex = index
}
},
//
toggleTask(evt, visitTaskNum, i) {
toggleTask(evt, visitTaskNum, i, index) {
this.activeCanvas(index)
const num = visitTaskNum + i
if (num >= 0 && num <= this.taskInfo.VisitNum) {
this.$emit('toggleTaskByViewer', num)
@@ -698,6 +804,19 @@ export default {
if (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, {
bindings: [{ mouseButton: MouseBindings.Primary }]
})
@@ -742,12 +861,22 @@ export default {
if (this.readingTaskState === 2) return
const { annotation } = e.detail
if (!annotation) return
if (!annotation.annotationId) return
await deleteTrialFileType(annotation.annotationId)
if (annotation.annotationId) {
await deleteTrialFileType(annotation.annotationId)
} else {
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
}
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
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) {
console.log('Modified')
@@ -764,6 +893,16 @@ export default {
const fileList = this.viewportInfos[i].fileList
const fileIndex = fileList.findIndex(f => f.Path === path)
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 = {
id: annotation.annotationId,
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
@@ -790,6 +929,23 @@ export default {
const fileList = this.viewportInfos[i].fileList
const fileIndex = fileList.findIndex(f => f.Path === path)
if (fileIndex === -1) return
if (annotation.metadata.toolName === 'Length') {
this.form.annotationObj = {
id: '',
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
studyId: this.viewportInfos[i].studyId,
noneDicomFileId: fileList[fileIndex].Id,
path: fileList[fileIndex].Path,
annotation,
fileList,
fileIndex
}
this.form.length = null
this.dialogVisible = true
this.setToolsPassive()
return
}
const params = {
id: '',
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
@@ -800,9 +956,145 @@ export default {
}
const res = await addNoneDicomMark(params)
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'))
},
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) {
const cachedVolumeStats = data.cachedStats[targetId]
const { length, unit } = cachedVolumeStats
if (length === undefined || length === null || isNaN(length)) {
return
}
if (data.l === undefined || data.l === null || isNaN(data.l)) {
return
}
const textLines = []
textLines.push(`P: ${parseFloat(length).toFixed(this.digitPlaces)} ${unit}`)
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 || {}
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) {
let timerId
return function() {
@@ -824,7 +1116,8 @@ export default {
//
async customPrompt() {
try {
const { value } = await this.$prompt('请输入标记名称')
//
const { value } = await this.$prompt(this.$t('trials:noneDicom:message:msg1'))
return value
} catch {
return null
@@ -863,15 +1156,21 @@ export default {
let sliceIdx = Math.trunc(this.viewportInfos[i].imageIds.length * height / 100)
sliceIdx = sliceIdx >= this.viewportInfos[i].imageIds.length ? this.viewportInfos[i].imageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
this.viewportInfos[i].height = height
if (this.viewportInfos[i].currentImageIdIndex !== i) {
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(
this.viewportInfos[i].viewportId
)
viewport.setImageIdIndex(sliceIdx)
viewport.render()
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
}
// if (this.viewportInfos[i].currentImageIdIndex !== i) {
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine.getViewport(
this.viewportInfos[i].viewportId
)
viewport.setImageIdIndex(sliceIdx)
viewport.render()
// }
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
},
sliderMouseleave(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
if (i === -1 && this.imageType.includes(this.viewportInfos[i].fileType)) return
if (!this.viewportInfos[i].isMove) return
this.viewportInfos[i].isMove = false
},
sliderMousedown(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
@@ -900,6 +1199,9 @@ export default {
//
viewCD(id) {
this.$emit('previewCD', id)
},
previewConfig() {
this.personalConfigDialog.visible = true
}
}
}
@@ -914,11 +1216,17 @@ export default {
.tools-wrapper {
height: 50px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid #727272;
color: #ddd;
padding: 0 5px;
.tools-left {
flex: 1;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.tool-item {
padding: 5px;
margin: 0 5px;
@@ -973,7 +1281,6 @@ export default {
.cd-info {
color: #ddd;
font-size: 18px;
cursor: pointer;
}
.subject-info {
color:#f44336;
@@ -1038,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>
@@ -127,6 +127,7 @@
v-model="questionForm[question.Id]"
clearable
@change="(val) => { formItemNumberChange(val, question) }"
:disabled="readingTaskState >= 2"
>
<el-option
v-for="val in question.TypeValue.split('|')"
@@ -139,9 +140,9 @@
v-else-if="question.DataSource !== 1"
v-model="questionForm[question.Id]"
type="number"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
@change="(val) => { formItemNumberChange(val, question) }"
@input="limitInput($event, questionForm, question.Id)"
:disabled="readingTaskState >= 2"
>
<template v-if="question.Unit !== 0" slot="append">{{ question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit }}</template>
<template v-else-if="question.ValueType === 2" slot="append">%</template>
@@ -150,9 +151,8 @@
v-else-if="question.DataSource === 1"
v-model="questionForm[question.Id]"
type="number"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
:disabled="question.DataSource === 1"
@input="limitInput($event, questionForm, question.Id)"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
:disabled="question.DataSource === 1 || readingTaskState >= 2"
>
<template v-if="question.Unit !== 0" slot="append">{{ question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit }}</template>
<template v-else-if="question.ValueType === 2" slot="append">%</template>
@@ -305,7 +305,7 @@ export default {
imgVisible: false,
imageUrl: '',
urls: [],
digitPlaces: null
digitPlaces: 2
}
},
watch: {
@@ -336,7 +336,8 @@ export default {
})
}
}
this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
},
methods: {
limitInput(value, a, b) {
@@ -346,6 +347,9 @@ export default {
}
}
},
handleBlur(value, a, b) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
},
logic(rules, num = 0) {
try {
if (rules.CalculateQuestionList.length === 0) {
@@ -461,14 +465,13 @@ export default {
} catch (e) {
console.log(e)
}
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
if (rules.ValueType === 2) {
num = num * 100
}
if (rules.CustomCalculateMark === 13 || rules.CustomCalculateMark === 14) {
return num
} else {
return num.toFixed(digitPlaces)
return num.toFixed(this.digitPlaces)
}
},
formItemNumberChange(questionId, isTable) {
@@ -51,10 +51,12 @@
<file-viewer
ref="fileViewer"
:related-study-info="relatedStudyInfo"
:ps-arr="psArr"
@toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask"
@toggleImage="toggleImage"
@previewCD="previewCD"
@setPS="setPS"
/>
</div>
<!-- 表单 -->
@@ -91,11 +93,9 @@
:fullscreen="isClinicalDataFullscreen"
>
<span slot="title" class="dialog-footer">
<!-- 当前阅片任务存在临床数据请查看若已查看请点击确认 -->
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
<div style="position: absolute;right: 20px;top: 10px;">
<svg-icon :icon-class="isClinicalDataFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isClinicalDataFullscreen=!isClinicalDataFullscreen" />
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="clinicalDataVisible = false" />
<svg-icon icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="clinicalDataVisible = false" />
</div>
</span>
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
@@ -107,9 +107,6 @@
:visit-task-id="cdVisitTaskId"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
/>
<div v-if="!closeCDVisible" style="text-align:right">
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
</div>
</div>
</el-dialog>
@@ -117,7 +114,7 @@
</template>
<script>
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto, readClinicalData } from '@/api/trials'
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto } from '@/api/trials'
import StudyList from './StudyList'
// import ImageViewer from './ImageViewer'
// import PdfViewer from './PDFViewer'
@@ -156,9 +153,9 @@ export default {
relatedStudyInfo: null,
clinicalDataVisible: false,
isClinicalDataFullscreen: false,
closeCDVisible: false,
trialId: '',
cdVisitTaskId: ''
cdVisitTaskId: '',
psArr: []
}
},
computed: {
@@ -181,13 +178,6 @@ export default {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.trialId = this.$route.query.trialId
this.getRelatedTask()
this.$nextTick(() => {
if (this.taskInfo.IsExistsClinicalData && this.taskInfo.IsNeedReadClinicalData && !this.taskInfo.IsReadClinicalData) {
this.isClinicalDataFullscreen = false
this.clinicalDataVisible = true
this.cdVisitTaskId = this.taskInfo.VisitTaskId
}
})
},
methods: {
//
@@ -243,71 +233,6 @@ export default {
}
const res = await getReadingImageFile(params)
this.$set(this.visitTaskList[visitTaskIdx], 'StudyList', res.Result)
// const arr = [
// {
// BodyPart: '',
// Code: 0,
// CodeView: '',
// Description: '',
// FileCount: 0,
// Id: '6783b9e8-738f-42d6-bc36-8d3b36b060ee',
// ImageDate: '0001-01-01 00:00:00',
// IsCriticalSequence: true,
// IsDeleted: false,
// IsReading: false,
// Modality: '',
// StudyName: '',
// SubjectId: '08dd3125-be6c-d544-0242-0a0001000000',
// SubjectVisitId: '01000000-0a10-0242-4a73-08dd3125be6d',
// TrialId: '08dd2ee1-0754-9e3d-0242-0a0001000000',
// UpdateTime: '0001-01-01 00:00:00',
// NoneDicomStudyFileList: [
// {
// Id: '08dd3480-5a81-cb9d-0242-0a0001000000',
// Path: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706111094_Independent%20Review%20Charter.pdf',
// FileName: 'A11CF934.jpg',
// CreateTime: '2025-01-14 17:46:43',
// CreateUserId: '746d0000-3e2c-0016-f276-08daeedff8de',
// NoneDicomStudyId: '08dd3480-4747-4454-0242-0a0001000000',
// FileSize: 29137,
// FullFilePath: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706111094_Independent%20Review%20Charter.pdf',
// FileType: 'image/jpeg'
// }
// ]
// },
// {
// BodyPart: '',
// Code: 0,
// CodeView: '',
// Description: '',
// FileCount: 0,
// Id: '6783b9e8-738f-42f6-bc36-8d3b36b060ee',
// ImageDate: '0001-01-01 00:00:00',
// IsCriticalSequence: true,
// IsDeleted: false,
// IsReading: false,
// Modality: '',
// StudyName: '',
// SubjectId: '08dd3125-be6c-d544-0242-0a0001000000',
// SubjectVisitId: '01000000-0a00-0242-4a73-08dd3125be6d',
// TrialId: '08dd2ee1-0754-9e3d-0242-0a0001000000',
// UpdateTime: '0001-01-01 00:00:00',
// NoneDicomStudyFileList: [
// {
// Id: '08dd3480-5a81-cb8d-0242-0a0001000000',
// Path: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706163441_IRaCIS%20%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9FV%201.0%20CRO%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3_20200601.pdf',
// FileName: 'A11CF934.jpg',
// CreateTime: '2025-01-14 17:46:43',
// CreateUserId: '746d0000-3e2c-0016-f276-08daeedff8de',
// NoneDicomStudyId: '08dd3480-4747-4454-0242-0a0001000000',
// FileSize: 29137,
// FullFilePath: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706163441_IRaCIS%20%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9FV%201.0%20CRO%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3_20200601.pdf',
// FileType: 'image/jpeg'
// }
// ]
// }
// ]
// this.$set(this.visitTaskList[visitTaskIdx], 'StudyList', arr)
this.loading = false
resolve()
} catch (e) {
@@ -326,7 +251,16 @@ export default {
visitTaskId: visitTaskId
}
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
resolve()
} catch (e) {
@@ -336,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) {
this.setActiveTaskVisitId(taskInfo.VisitTaskId)
@@ -370,21 +312,8 @@ export default {
toggleImage(obj) {
this.$refs[obj.taskId][0].activeImage(obj)
},
async handleConfirmCD() {
this.loading = true
var visitTaskId = this.taskInfo.VisitTaskId
try {
await readClinicalData({ visitTaskId })
this.loading = false
this.clinicalDataVisible = false
this.closeCDVisible = true
// this.isReadClinicalData = true
} catch (e) {
this.loading = false
}
},
previewCD(taskId) {
this.closeCDVisible = true
this.isClinicalDataFullscreen = false
this.dialogVisible = true
this.cdVisitTaskId = taskId
@@ -466,6 +395,7 @@ export default {
width: 400px;
border: 1px solid #727272;
padding: 0 10px;
overflow-y: auto;
.text-info {
display: flex;
align-items: center;
@@ -170,6 +170,13 @@
</span>
</div>
</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">
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
</template>
@@ -206,19 +213,41 @@
</div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</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>
</template>
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
// import UploadFile from './UploadFile'
import { getAutoCutNextTask } from '@/api/user'
import const_ from '@/const/sign-code'
import SignForm from '@/views/trials/components/newSignForm'
import PreviewFile from '@/components/PreviewFile/index'
import { getToken } from '@/utils/auth'
import store from '@/store'
export default {
name: 'ReportPage',
components: { SignForm },
name: 'CustomizeReportPage',
components: { SignForm, PreviewFile },
data() {
return {
trialId: '',
@@ -242,7 +271,10 @@ export default {
tableAnswers: {},
questionForm: {},
questionId: null,
taskInfo: null
taskInfo: null,
previewVisible: false,
currentPath: '',
currentType: ''
}
},
watch: {
@@ -264,7 +296,8 @@ export default {
this.visitTaskId = this.taskInfo.VisitTaskId
this.subjectId = this.taskInfo.SubjectId
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
window.addEventListener('resize', () => {
this.handleResize()
@@ -351,11 +384,11 @@ export default {
},
InitVisitTaskQuestionForm() {
this.taskQuestions.map((v, i) => {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') {
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 !== 'basicTable' && v.Type !== 'number') {
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)
this.$set(this.questionForm, v.QuestionId, tableAnswers)
// this.$set(v, 'xfIndex', i)
@@ -379,10 +412,10 @@ export default {
},
setChild(obj) {
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])
}
if (i.Type === 'table') {
if (i.Type === 'table' || i.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
this.$set(this.questionForm, i.QuestionId, tableAnswers)
}
@@ -397,7 +430,7 @@ export default {
}
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)
}
})
@@ -450,19 +483,18 @@ export default {
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
break
case 8:
var arr = []
const arr = []
this.questionForm[o.QuestionId].forEach(q => {
arr.push(q[o.TableQuestionId])
})
num = arr.length === 0 ? 0 : Math.max(...arr)
break
case 9:
// eslint-disable-next-line no-redeclare
var arr = []
const arr1 = []
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
}
} else {
@@ -489,11 +521,10 @@ export default {
} catch (e) {
console.log(e)
}
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
if (rules.ValueType === 2) {
num = num * 100
}
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(digitPlaces) : '∞'
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(this.digitPlaces) : '∞'
},
getReportInfo() {
this.loading = true
@@ -522,8 +553,6 @@ export default {
questions.forEach((item) => {
const obj = item
this.$set(obj, 'Answers', {})
var digitPlaces = parseInt(localStorage.getItem('digitPlaces')) || 0
item.Answer.forEach(i => {
if (item.DictionaryCode) {
this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null)
@@ -536,7 +565,7 @@ export default {
} else if (item.ValueType === 3) {
val = i.Answer
} 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)
} else {
@@ -590,15 +619,16 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
submitDicomVisitTask(params).then(res => {
try {
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
const res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
@@ -606,43 +636,39 @@ export default {
}
this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
//
this.readingTaskState = 2
this.taskInfo.ReadingTaskState = 2
localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo))
store.dispatch('noneDicomReview/setCurrentTaskState', 2)
// DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.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()
})
.catch(action => {
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',
distinguishCancelAndClose: true
})
.then(() => {
window.location.reload()
})
.catch(action => {
// changeURLStatic('visitTaskId', this.visitTaskId)
})
}
}
this.loading = false
}).catch(() => {
} catch (e) {
console.log(e)
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
})
}
},
previewDicoms(task) {
var token = getToken()
@@ -721,6 +747,13 @@ export default {
this.loading = false
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;
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{
color: #428bca;
@@ -22,15 +22,19 @@
v-if="!study.IsCriticalSequence"
class="dicom-desc"
>
<div>{{ study.CodeView }}</div>
<div>
<!-- <div v-if="taskInfo && taskInfo.IsShowStudyName">{{ study.StudyName }}</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 style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
</div>
</div>
<div v-else>
<!-- 关键序列 -->
关键文件
<!-- 关键文件 -->
{{ $t('trials:noneDicom:title:keyFiles') }}
</div>
</template>
<div class="file-list-container">
@@ -44,7 +48,7 @@
:class="{'file-active': index === activeStudyIndex && i === activeFileIndex}"
class="file-wrapper"
>
<div class="file-image">
<div class="file-image">
<el-image
v-if="k.FileType === 'image/jpeg' || k.FileType === 'image/jpg' || k.FileType === 'image/bmp' || k.FileType === 'image/png'"
style="width: 100%;height: 100%;"
@@ -73,7 +77,7 @@
</div>
</template>
<script>
import pdf from '@/assets/pdf.jpg'
import pdf from '@/assets/pdf.png'
export default {
name: 'StudyList',
props: {
@@ -164,6 +168,9 @@ export default {
text-align: left;
color: #d0d0d0;
padding: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ps {
@@ -912,10 +912,19 @@
</el-form>
</template>
<template slot="dialog-footer">
<el-button type="primary" @click="addOrUpdateTrialStudyName">
<el-button
type="primary"
@click="addOrUpdateTrialStudyName"
:loading="studyNameLoading"
>
{{ $t('common:button:confirm') }}
</el-button>
<el-button @click="addStudyName_model.visible = false">
<el-button
@click="
;(addStudyName_model.visible = false),
(addStudyNameForm.Name = null)
"
>
{{ $t('common:button:cancel') }}
</el-button>
</template>
@@ -933,6 +942,7 @@ import {
ConfigTrialBasicInfoConfirm,
getTrialBodyPartList,
addOrUpdateTrialBodyPart,
updateTrialStudyNameList,
} from '@/api/trials/setting'
import SignForm from '@/views/trials/components/newSignForm'
import ClinicalDataForm from './clinicalDataForm'
@@ -1094,6 +1104,7 @@ export default {
width: '500px',
appendToBody: true,
},
studyNameLoading: false,
addBodyPartForm: {
bodyPartStr: null,
Id: null,
@@ -1328,13 +1339,51 @@ export default {
if (!validate) return
this.addStudyNameForm.EnName = this.addStudyNameForm.Name
let data = { ...this.addStudyNameForm }
this.trialStudyNameList.push(data)
let arr = []
this.trialStudyNameList.forEach((item) => {
let obj = {
EnName: item.EnName,
Name: item.EnName,
IsChoose: false,
}
arr.push(obj)
})
arr.push(data)
this.studyNameLoading = true
let res = await this.updateStudyNameList(arr)
this.studyNameLoading = false
if (!res)
return this.$message.warning(
this.$t('trials:seeting:message:addStudyNameFail')
)
this.$message.success(
this.$t('trials:seeting:message:addStudyNameSucccess')
)
this.addStudyNameForm = {
EnName: null,
Name: null,
IsChoose: false,
}
this.addStudyName_model.visible = false
// this.getStudyNameList()
this.trialStudyNameList.push(data)
},
async updateStudyNameList(StudyNameList) {
try {
let data = {
TrialId: this.$route.query.trialId,
StudyNameList,
}
let res = await updateTrialStudyNameList(data)
if (res.IsSuccess) {
return true
}
return false
} catch (err) {
console.log(err)
return false
}
},
//
handleEditBodyPart(item) {
@@ -1344,11 +1393,33 @@ export default {
this.addBodyPart_model.title = this.$t('trials:setting:button:edit')
this.addBodyPart_model.visible = true
},
handleDelStudyName(item) {
async handleDelStudyName(item) {
let index = this.trialStudyNameList.findIndex(
(data) => item.Name === data.Name
)
let arr = []
this.trialStudyNameList.forEach((item, i) => {
if (index !== i) {
let obj = {
EnName: item.EnName,
Name: item.EnName,
IsChoose: false,
}
arr.push(obj)
}
})
this.listLoading = true
let res = await this.updateStudyNameList(arr)
this.listLoading = false
if (!res)
return this.$message.warning(
this.$t('trials:seeting:message:delStudyNameFail')
)
this.$message.success(
this.$t('trials:seeting:message:delStudyNameSucccess')
)
this.trialStudyNameList.splice(index, 1)
// this.getStudyNameList()
},
handleSetBodyPart() {
this.bodyPartListVisible = true
@@ -1835,7 +1906,9 @@ export default {
this.form.ClinicalDataSetNames.join(', ')
}
this.getClinicalDataList(true)
this.$message.success('删除成功!')
this.$message.success(
this.$t('common:message:deletedSuccessfully')
)
}
})
.catch(() => {
@@ -99,9 +99,9 @@
<template slot-scope="scope">
<span>{{
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 / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -324,7 +324,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
handleReset() {
this.searchData = searchDataDefault()
@@ -164,7 +164,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -278,6 +278,7 @@
>
<template slot-scope="scope">
<el-switch
:disabled="!scope.row.TrialFileRecord"
v-if="isManage && !viewStatus && hasEdit"
v-model="scope.row.IsAuthorizedView"
@change="(val) => auth(false, scope.row, val)"
@@ -747,7 +748,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -769,18 +770,18 @@ export default {
},
immediate: true,
},
rowData: {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
let types = typeArr[this.ArchiveTypeEnum]
this.uploadPath = `/${this.$route.query.trialId}/Document/${types}`
console.log(this.uploadPath, this.ArchiveTypeEnum)
},
computed: {
isEN() {
@@ -273,6 +273,12 @@ export default {
this.loading = true
let res = await setAuthorizedView(data)
this.loading = false
if (res.IsSuccess) {
this.$emit('update:rowData', {})
this.$nextTick(() => {
this.$emit('update:rowData', item)
})
}
} catch (err) {
this.loading = false
item.IsEnable = !item.IsEnable
@@ -361,11 +361,11 @@ export default {
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()
// let fileNameNoType = param.file.name
// .substring(0, param.file.name.lastIndexOf('.'))
// .toLocaleLowerCase()
const res = await this.OSSclient.put(
`/${trialId}/Document/${types}/${fileNameNoType}${extendName}`,
`/${trialId}/Document/${types}/${this.$guid()}${extendName}`,
file
)
this.form[`${key}FileRecord`] = {
@@ -766,11 +766,12 @@ export default {
},
immediate: true,
},
rowData: {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
computed: {
@@ -690,7 +690,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -722,18 +722,18 @@ export default {
},
immediate: true,
},
rowData: {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
let types = typeArr[this.ArchiveTypeEnum]
this.uploadPath = `/${this.$route.query.trialId}/Document/${types}`
console.log(this.uploadPath, this.ArchiveTypeEnum)
},
computed: {
isEN() {
@@ -1,101 +1,45 @@
<template>
<base-model :config="config">
<div slot="dialog-body">
<el-form
ref="trainRecordForm"
:model="form"
label-width="140px"
size="small"
:rules="rules"
>
<el-form ref="trainRecordForm" :model="form" label-width="140px" size="small" :rules="rules">
<div class="base-dialog-body">
<el-form-item
v-if="!config.upload"
:label="$t('trials:trialDocument:trainRecord:form:TrianingDate')"
prop="TrianingDate"
>
<el-date-picker
v-model="form.TrianingDate"
type="date"
placeholder=""
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"
>
<el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingDate')"
prop="TrianingDate">
<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-form-item>
<el-form-item
v-if="!config.upload"
:label="$t('trials:trialDocument:trainRecord:form:TrianingCount')"
prop="TrianingCount"
>
<el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingCount')"
prop="TrianingCount">
<el-input v-model.number="form.TrianingCount" type="number" />
</el-form-item>
<el-form-item
v-if="!config.upload"
:label="$t('trials:trialDocument:trainRecord:form:TrianingState')"
prop="TrianingState"
>
<el-input v-model="form.TrianingState" type="number" />
<el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:TrianingState')"
prop="TrianingState">
<el-input v-model="form.TrianingState" />
</el-form-item>
<el-form-item
v-if="!config.upload"
:label="$t('trials:trialDocument:trainRecord:form:Note')"
prop="Note"
>
<el-input v-model="form.Note" type="number" />
<el-form-item v-if="!config.upload" :label="$t('trials:trialDocument:trainRecord:form:Note')" prop="Note">
<el-input v-model="form.Note" />
</el-form-item>
<el-form-item
v-if="!config.upload || config.upload === 'Trial'"
:label="$t('trials:trialDocument:trainRecord:form:TrialFileRecord')"
prop="TrialFileRecord"
>
<el-upload
class="upload-demo"
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-form-item v-if="!config.upload || config.upload === 'Trial'"
:label="$t('trials:trialDocument:trainRecord:form:TrialFileRecord')" prop="TrialFileRecord">
<el-upload class="upload-demo" 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>
<span slot="tip" class="el-upload__tip">
{{ $t('trials:trialDocument:trainRecord:rule:mustPDF') }}
</span>
</el-upload>
</el-form-item>
<el-form-item
v-if="!config.upload || config.upload === 'History'"
:label="
$t('trials:trialDocument:trainRecord:form:historyFileRecord')
"
>
<el-upload
class="upload-demo"
action
:before-upload="(param) => beforeUpload(param, 'History', '.zip')"
<el-form-item v-if="!config.upload || config.upload === 'History'" :label="$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')"
:on-remove="() => handleRemoveFile('History')"
:limit="1"
accept=".zip"
:file-list="HistoryFile"
>
<el-button
size="small"
type="primary"
:disabled="
!!form.HistoryFileRecord && !!form.HistoryFileRecord.FilePath
"
>{{ $t('common:button:upload') }}
:on-remove="() => handleRemoveFile('History')" :limit="1" accept=".zip" :file-list="HistoryFile">
<el-button size="small" type="primary" :disabled="!!form.HistoryFileRecord && !!form.HistoryFileRecord.FilePath
">{{ $t('common:button:upload') }}
</el-button>
<span slot="tip" class="el-upload__tip">
{{ $t('trials:trialDocument:trainRecord:rule:mustZIP') }}
@@ -115,7 +59,7 @@
</div>
</base-model>
</template>
<script>
<script>
import baseModel from '@/components/BaseModel'
import { addOrUpdateTrialTrianingRecord } from '@/api/dictionary'
export default {
@@ -184,7 +128,7 @@ export default {
callback(
new Error(
this.$t(
'trials:trialDocument:trainRecord:ruleMessage:TrianingCountPatternS'
'trials:trialDocument:trainRecord:ruleMessage:TrianingCountPattern'
)
)
)
@@ -194,7 +138,7 @@ export default {
},
trigger: 'blur',
},
],
]
},
loading: false,
TrialFile: [],
@@ -279,11 +223,11 @@ export default {
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()
// let fileNameNoType = param.file.name
// .substring(0, param.file.name.lastIndexOf('.'))
// .toLocaleLowerCase()
const res = await this.OSSclient.put(
`/${trialId}/Document/${types}/${fileNameNoType}${extendName}`,
`/${trialId}/Document/${types}/${this.$guid()}${extendName}`,
file
)
this.form[`${key}FileRecord`] = {
@@ -376,7 +376,7 @@
v-if="hasDownLoad && isManage && !viewStatus"
icon="el-icon-download"
:title="
$t('trials:trialDocument:trainRecord:button:downLoadFileFileFile')
$t('trials:trialDocument:trainRecord:button:downLoadFile')
"
circle
:disabled="
@@ -843,7 +843,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -865,11 +865,12 @@ export default {
},
immediate: true,
},
rowData: {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
@@ -81,7 +81,7 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -335,10 +335,10 @@ export default {
let fileType = file.name
.substring(file.name.lastIndexOf('.'))
.toLocaleLowerCase()
let fileName = file.name
.substring(0, file.name.lastIndexOf('.'))
.toLocaleLowerCase()
let path = `${this.uploadPath}/${fileName}${fileType}`
// let fileName = file.name
// .substring(0, file.name.lastIndexOf('.'))
// .toLocaleLowerCase()
let path = `${this.uploadPath}/${this.$guid()}${fileType}`
file.curPath = path
const fileData = await this.fileToBlob(file.file)
let res = await this.fileToOss(path, fileData, file)
@@ -0,0 +1,253 @@
<template>
<base-model :config="config">
<div slot="dialog-body">
<el-form
ref="certificateForm"
:model="form"
label-width="140px"
size="small"
:rules="rules"
>
<div class="base-dialog-body">
<el-form-item
:label="$t('trials:trialDocument:certificate:form:fileType')"
prop="Type"
>
<el-select
v-model="form.Type"
placeholder=""
clearable
:disabled="config.status === 'edit' && !!this.data.Type"
>
<el-option
v-for="item in $d.CertificateFileType"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
:label="$t('trials:trialDocument:certificate:form:DoctorId')"
prop="DoctorId"
>
<el-select
v-model="form.DoctorId"
placeholder=""
clearable
:disabled="config.status === 'edit' && !!this.data.DoctorId"
>
<el-option
v-for="item in doctorList"
:key="item.Id"
:label="item.FullName"
:value="item.Id"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
:label="$t('trials:trialDocument:certificate:form:pdfFileRecord')"
prop="Path"
>
<el-upload
class="upload-demo"
action
:before-upload="(param) => beforeUpload(param, '.pdf')"
:http-request="handleUploadFile"
:on-remove="handleRemoveFile"
:limit="1"
accept=".pdf"
:file-list="PDFFile"
>
<el-button size="small" type="primary" :disabled="!!form.Path"
>{{ $t('common:button:upload') }}
</el-button>
<span slot="tip" class="el-upload__tip">
{{ $t('trials:trialDocument:certificate:rule:mustPDF') }}
</span>
</el-upload>
</el-form-item>
</div>
</el-form>
</div>
<div slot="dialog-footer">
<el-button size="small" @click="canel">
{{ $t('trials:trialDocument:certificate:button:canel') }}
</el-button>
<el-button size="small" type="primary" :loading="loading" @click="save">
{{ $t('trials:trialDocument:certificate:button:save') }}
</el-button>
</div>
</base-model>
</template>
<script>
import baseModel from '@/components/BaseModel'
import { saveTrialAttachments, updateTrialAttachments } from '@/api/dictionary'
export default {
props: {
config: {
required: true,
default: () => {
return {}
},
},
data: {
required: true,
default: () => {
return {}
},
},
ArchiveTypeEnum: {
type: Number,
default: 0,
},
doctorList: {
type: Array,
default: () => {
return []
},
},
},
components: {
'base-model': baseModel,
},
data() {
return {
form: {
Type: null,
DoctorId: null,
FileName: null,
Path: null,
FullPath: null,
},
rules: {
Type: [
{
required: true,
message: this.$t('common:ruleMessage:select'),
trigger: ['blur', 'change'],
},
],
DoctorId: [
{
required: true,
message: this.$t('common:ruleMessage:select'),
trigger: ['blur', 'change'],
},
],
Path: [
{
required: true,
validator: (rule, value, callback) => {
if (!this.form.Path) {
callback(
new Error(
this.$t('trials:trialDocument:certificate:msg:noFile')
)
)
} else {
callback()
}
},
// message: this.$t('common:ruleMessage:specify'),
trigger: ['blur', 'change'],
},
],
},
loading: false,
PDFFile: [],
}
},
created() {
if (this.config.status === 'edit') {
Object.keys(this.form).forEach((key) => {
this.form[key] = this.data[key]
})
if (this.form.Path) {
this.PDFFile = []
this.PDFFile.push({
name: this.form.FileName,
url: this.form.Path,
})
}
}
},
methods: {
async save() {
try {
let validate = await this.$refs.certificateForm.validate()
if (!validate) return false
this.loading = true
this.form.TrialId = this.$route.query.trialId
let res = null
if (this.config.status === 'edit') {
this.form.Id = this.data.Id
res = await updateTrialAttachments(this.form)
} else {
res = await saveTrialAttachments([this.form])
}
if (res.IsSuccess) {
this.$emit('close')
this.$emit('getList')
}
} catch (err) {
console.log(err)
this.loading = false
}
},
canel() {
this.$emit('close')
},
handleRemoveFile() {
this.form.Path = null
this.form.FileName = null
this.form.FullPath = null
this.PDFFile = []
},
beforeUpload(param, accept) {
if (this.PDFFile && this.PDFFile[0]) {
this.$alert(
this.$t('trials:trialDocument:certificate:msg:hasFile')
).catch()
return
}
let extendName = param.name
.substring(param.name.lastIndexOf('.'))
.toLocaleLowerCase()
if (accept !== extendName) {
this.$alert(
this.$t('trials:trialDocument:certificate:msg:typeErr')
).catch()
return
}
},
async handleUploadFile(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:certificate: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.form.Path = this.$getObjectName(res.url)
this.form.FullPath = this.$getObjectName(res.url)
this.form.FileName = param.file.name
this.loading = false
},
},
}
</script>
@@ -0,0 +1,713 @@
<template>
<box-content>
<div class="title">
{{ TITLE }}
</div>
<!-- 搜索框 -->
<div class="search" style="position: relative">
<el-form :inline="true" class="base-search-form">
<!--文件类型-->
<el-form-item
:label="$t('trials:trialDocument:certificate:search:fileType')"
>
<el-select
v-model="searchData.Type"
style="width: 100px"
placeholder=""
clearable
>
<el-option
v-for="item in $d.CertificateFileType"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<!--文件名称-->
<el-form-item
:label="$t('trials:trialDocument:certificate:search:name')"
>
<el-input
v-model="searchData.FileName"
style="width: 100px"
clearable
/>
</el-form-item>
<!--阅片人-->
<el-form-item
:label="$t('trials:trialDocument:certificate:search:viewer')"
>
<el-select
v-model="searchData.DoctorId"
style="width: 100px"
placeholder=""
clearable
>
<el-option
v-for="item in doctorList"
:key="item.Id"
:label="item.FullName"
:value="item.Id"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
:label="
$t('trials:trialDocument:certificate:search:isAuthorizedView')
"
v-if="isManage && !viewStatus"
>
<el-select
v-if="!viewStatus"
v-model="searchData.IsAuthorizedView"
style="width: 100px"
placeholder=""
clearable
>
<el-option
v-for="item in $d.YesOrNo"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
<el-form-item v-if="isManage && !viewStatus">
<el-button
type="primary"
:disabled="selectTable.length <= 0"
v-if="hasAccredit && isManage && !viewStatus"
@click.stop="auth"
>
{{ $t('trials:trialDocument:certificate:button:accredit') }}
</el-button>
<el-button
type="primary"
v-if="hasAdd && isManage && !viewStatus"
@click.stop="handleAdd"
>
{{ $t('trials:trialDocument:certificate:button:add') }}
</el-button>
<el-button
type="primary"
v-if="hasEdit && isManage && !viewStatus"
@click.stop="openFile(false)"
>
{{ $t('trials:trialDocument:certificate:button:uploadFile') }}
</el-button>
<el-button
type="primary"
v-if="hasEdit && isManage && !viewStatus"
@click.stop="openFile(true)"
>
{{ $t('trials:trialDocument:certificate:button:uploadFolder') }}
</el-button>
<el-button
type="primary"
icon="el-icon-bottom"
:disabled="selectTable.length <= 0"
v-if="hasDownLoad && isManage && !viewStatus"
@click.stop="downLoad"
>
{{ $t('trials:trialDocument:certificate:button:downLoadFile') }}
</el-button>
<el-button
type="primary"
:disabled="selectTable.length <= 0"
v-if="hasDel && isManage && !viewStatus"
@click.stop="handleDel"
>
{{ $t('trials:trialDocument:certificate:button:del') }}
</el-button>
</el-form-item>
</el-form>
</div>
<el-table
v-loading="loading"
v-adaptive="{ bottomOffset: 75 }"
:data="list"
stripe
height="100"
style="width: 100%"
@sort-change="handleSortByColumn"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
v-if="isManage && !viewStatus"
/>
<el-table-column type="index" v-else />
<!--文件类型-->
<el-table-column
prop="type"
:label="$t('trials:trialDocument:certificate:table:fileType')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd('CertificateFileType', scope.row.Type) }}</span>
</template>
</el-table-column>
<!--文件名称-->
<el-table-column
prop="FileName"
:label="$t('trials:trialDocument:certificate:table:FileName')"
show-overflow-tooltip
sortable="custom"
/>
<!--阅片人-->
<el-table-column
prop="UserName"
:label="$t('trials:trialDocument:certificate:table:viewer')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ scope.row.UserName }} ({{ scope.row.FullName }})</span>
</template>
</el-table-column>
<el-table-column
prop="IsAuthorizedView"
:label="$t('trials:trialDocument:certificate:table:isAuthorizedView')"
show-overflow-tooltip
sortable="custom"
v-if="isManage && !viewStatus"
>
<template slot-scope="scope">
<el-switch
:disabled="!scope.row.DoctorId"
v-if="isManage && !viewStatus && hasEdit"
v-model="scope.row.IsAuthorizedView"
@change="(val) => auth(false, scope.row, val)"
:active-value="true"
:inactive-value="false"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
>
</el-switch>
<span v-else>{{ $fd('YesOrNo', scope.row.IsAuthorizedView) }}</span>
</template>
</el-table-column>
<el-table-column
prop="UpdateTime"
:label="$t('trials:trialDocument:certificate:table:updateTime')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
:label="$t('trials:trialDocument:certificate:table:createTime')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column :label="$t('common:action:action')" width="200">
<template slot-scope="scope">
<el-button
icon="el-icon-view"
:title="$t('common:button:view')"
circle
@click.stop="preview(scope.row)"
/>
<el-button
v-if="hasEdit && isManage && !viewStatus"
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
circle
@click.stop="handleEdit(scope.row)"
/>
<el-button
v-if="hasDownLoad && isManage && !viewStatus"
icon="el-icon-download"
:title="$t('trials:trialDocument:certificate:button:downLoadFile')"
circle
@click.stop="downLoad(scope.row, 'file')"
/>
<el-button
v-if="hasDel && isManage && !viewStatus"
icon="el-icon-delete"
:title="$t('trials:trialDocument:certificate:button:delete')"
circle
@click.stop="handleDel(scope.row, false)"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<upload-files
:config="config"
:faccept="faccept"
:uploadPath="uploadPath"
:limitLength="limitLength"
v-if="config.visible"
@close="close"
@uplaodFile="uplaodFile"
/>
<certificate-form
:ArchiveTypeEnum="ArchiveTypeEnum"
:config="update_config"
:data="selectData"
:doctorList="doctorList"
v-if="update_config.visible"
@close="updateClose"
@getList="getList"
/>
</box-content>
</template>
<script>
import {
getTrialAttachments,
setAuthorizedViewC,
saveTrialAttachments,
getTrialDoctorListC,
deleteAttachment,
} from '@/api/dictionary'
import { downLoadFile } from '@/utils/stream.js'
import { deepClone } from '@/utils/index.js'
import Pagination from '@/components/Pagination'
import BoxContent from '@/components/BoxContent'
import uploadFiles from '../../uploadFiles.vue'
import certificateForm from './form.vue'
const searchDataDefault = () => {
return {
IsAuthorizedView: null,
FileName: null,
DoctorId: null,
Type: null,
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: 'UserName',
}
}
export default {
name: 'certificate',
components: { BoxContent, Pagination, uploadFiles, certificateForm },
props: {
viewStatus: {
type: Boolean,
default: true,
},
ArchiveTypeEnum: {
type: Number,
default: 0,
},
Id: {
type: String,
default: '',
},
rowData: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {
searchData: searchDataDefault(),
loading: false,
list: [],
total: 0,
selectTable: [],
config: {
visible: false,
showClose: true,
width: '800px',
title: '',
appendToBody: false,
isFolder: false,
},
selectData: {},
uploadPath: null,
faccept: ['.pdf'],
limitLength: 0,
update_config: {
visible: false,
showClose: true,
width: '600px',
title: '',
appendToBody: false,
status: 'add',
upload: null,
},
doctorList: [],
}
},
methods: {
//
async uplaodFile(list) {
console.log(list, 'list')
try {
if (!list || list.length <= 0) return false
let arr = []
list.forEach((item) => {
let obj = {
TrialId: this.$route.query.trialId,
FileName: item.FileName,
Path: item.FilePath,
FullPath: item.FilePath,
type: '',
DoctorId: null,
}
arr.push(obj)
})
this.loading = true
let res = await saveTrialAttachments(arr)
this.loading = false
if (res.IsSuccess) {
this.getList()
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
handleAdd() {
this.selectData = {}
this.update_config.title = `${this.$t(
'trials:trialDocument:certificate:form:title:add'
)}
-
${this.isEN ? this.rowData.Name : this.rowData.NameCN}`
this.update_config.status = 'add'
this.update_config.upload = null
this.update_config.visible = true
},
//
handleEdit(row) {
this.selectData = deepClone(row)
this.update_config.title = `${this.$t(
'trials:trialDocument:certificate:form:title:edit'
)}
-
${this.isEN ? this.rowData.Name : this.rowData.NameCN}`
this.update_config.status = 'edit'
this.update_config.upload = null
this.update_config.visible = true
},
//
async downLoad(row, type = 'zip') {
try {
if (type === 'file') {
return await downLoadFile(
this.OSSclientConfig.basePath + row.Path,
row.FileName
)
}
let { files, name } = this.formatDownloadFile()
let res = await downLoadFile(files, name, type)
// if (res && this.downloadId) {
// this.downloadImageSuccess()
// }
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile() {
let files = [],
name = `${this.TITLE}_${new Date().getTime()}.zip`
this.selectTable.forEach((item) => {
let obj = {
name: `${item.UserName} (${item.LastName}_${
item.FirstName
})/${this.$fd(
'CertificateFileType',
item.Type
)}_${item.FileName.substring(
0,
item.FileName.lastIndexOf('.')
)}__${new Date().getTime()}${item.FileName.substring(
item.FileName.lastIndexOf('.')
).toLocaleLowerCase()}`,
url: this.OSSclientConfig.basePath + item.Path,
}
files.push(obj)
})
return { files, name }
},
//
async auth(isArray = true, row, IsAuthorizedView) {
try {
let data = {}
if (isArray) {
let flag = this.selectTable.some((item) => !item.DoctorId)
if (flag)
return this.$message.warning(
this.$t('trials:trialDocument:certificate:message:hsaNoDoctorId')
)
data = {
Ids: this.selectTable.map((item) => item.Id),
IsAuthorizedView: true,
}
} else {
data = {
Ids: [row.Id],
IsAuthorizedView,
}
}
this.loading = true
let res = await setAuthorizedViewC(data)
this.loading = false
if (res.IsSuccess) {
this.$t('trials:trialDocument:certificate:message:authSuccessfully')
if (isArray) {
this.getList()
}
}
} catch (err) {
this.loading = false
if (!isArray) {
row.IsAuthorizedView = !row.IsAuthorizedView
}
console.log(err)
}
},
//
handleDel(row, isArray = true) {
this.$confirm(
this.$t('trials:trialDocument:certificate:message:deleteMessage'),
{
type: 'warning',
distinguishCancelAndClose: true,
}
)
.then(() => {
this.loading = true
let data = {}
if (isArray) {
data.Ids = this.selectTable.map((item) => item.Id)
} else {
data.Ids = [row.Id]
}
deleteAttachment(data)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(
this.$t('common:message:deletedSuccessfully')
)
}
})
.catch((err) => {
this.loading = false
console.log(err)
})
})
.catch((err) => {
this.loading = false
console.log(err)
})
},
//
async getTrialDoctorList() {
try {
let data = {
TrialId: this.$route.query.trialId,
}
let res = await getTrialDoctorListC(data)
if (res.IsSuccess) {
this.doctorList = res.Result
}
} catch (err) {
console.log(err)
}
},
async getList() {
try {
if (!this.Id) return false
// this.searchData.TrialFileTypeId = this.Id
this.searchData.TrialId = this.$route.query.trialId
if (this.viewStatus) {
this.searchData.IsAuthorizedView = true
}
this.loading = true
let res = await getTrialAttachments(this.searchData)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
handleSortByColumn(column) {
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false
}
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
handleSelectionChange(val) {
this.selectTable = val
},
//
preview(row) {
if (!row.Path) return false
this.$preview({
path: row.FilePath || row.fullPath || row.Path,
type: 'pdf',
title: row.FileName,
})
},
close() {
this.config.visible = false
// this.selectData = {}
// this.selectKey = null
this.faccept = ['.pdf']
this.limitLength = 0
},
updateClose() {
this.update_config.visible = false
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
this.faccept = ['.pdf']
this.limitLength = 0
this.config.title = this.$t(
'trials:trialDocument:certificate:form:title:uploadFile'
)
this.config.visible = true
this.config.isFolder = isFolder
},
},
watch: {
Id: {
handler() {
this.getList()
},
immediate: true,
},
},
created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
let types = typeArr[this.ArchiveTypeEnum]
this.uploadPath = `/${this.$route.query.trialId}/Document/${types}`
this.getTrialDoctorList()
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
isInspect() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:inspect',
])
},
isManage() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:manage',
])
},
hasAdd() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:add',
])
},
hasEdit() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:edit',
])
},
hasDel() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:del',
])
},
hasDownLoad() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:downLoad',
])
},
hasAccredit() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:accredit',
])
},
TITLE() {
return `${this.$fd('ArchiveType', this.ArchiveTypeEnum)}${
this.isEN ? this.rowData.Name : this.rowData.NameCN
}`
},
},
}
</script>
<style lang="scss" scoped>
.title {
line-height: 40px;
font-weight: bold;
margin-bottom: 10px;
}
.fileName {
display: inline-block;
max-width: calc(100% - 60px);
white-space: nowrap; /* 文本不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis;
}
.fileBtnBox {
display: inline-block;
width: 50px;
i {
cursor: pointer;
color: #409eff;
margin-right: 3px;
&:last-child {
margin: 0;
}
}
}
</style>
@@ -7,123 +7,67 @@
<div class="search" style="position: relative">
<el-form :inline="true" class="base-search-form">
<!--专业-->
<el-form-item
: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.value"
>
<el-form-item :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-option>
</el-select>
</el-form-item>
<!--亚专业-->
<el-form-item
: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.value"
>
<el-form-item :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-option>
</el-select>
</el-form-item>
<!--机构-->
<el-form-item
: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-form-item :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>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
</div>
<el-table
v-loading="loading"
v-adaptive="{ bottomOffset: 75 }"
:data="list"
stripe
height="100"
style="width: 100%"
>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 75 }" :data="list" stripe height="100"
style="width: 100%">
<el-table-column type="index" />
<!--姓名-->
<el-table-column
prop="BlindName"
:label="$t('trials:trialDocument:curriculumVitae:table:name')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="BlindName" :label="$t('trials:trialDocument:curriculumVitae:table:name')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<span>{{ isEN ? scope.row.BlindName : scope.row.BlindNameCN }}</span>
</template>
</el-table-column>
<el-table-column
prop="Speciality"
:label="$t('trials:trialDocument:curriculumVitae:table:Speciality')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="Code" :label="$t('trials:trialDocument:curriculumVitae:table:UserName')"
show-overflow-tooltip sortable="custom" />
<el-table-column prop="Speciality" :label="$t('trials:trialDocument:curriculumVitae:table:Speciality')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<span>
{{
scope.row.SpecialityId === otherId
? scope.row.SpecialityOther
: isEN
? scope.row.Speciality
: scope.row.SpecialityCN
? scope.row.Speciality
: scope.row.SpecialityCN
}}
</span>
</template>
</el-table-column>
<el-table-column
prop="Subspeciality"
:label="$t('trials:trialDocument:curriculumVitae:table:Subspeciality')"
show-overflow-tooltip
>
<el-table-column prop="Subspeciality" :label="$t('trials:trialDocument:curriculumVitae:table:Subspeciality')"
show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="isEN">
{{
@@ -141,62 +85,41 @@
</span>
</template>
</el-table-column>
<el-table-column
prop="HospitalName"
:label="$t('trials:trialDocument:curriculumVitae:table:HospitalName')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="HospitalName" :label="$t('trials:trialDocument:curriculumVitae:table:HospitalName')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<span>
{{ isEN ? scope.row.HospitalName : scope.row.HospitalNameCN }}
</span>
</template>
</el-table-column>
<el-table-column
prop="SubmmitTime"
:label="$t('trials:trialDocument:curriculumVitae:table:submmitTime')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column prop="OptTimeStr" :label="$t('trials:trialDocument:curriculumVitae:table:submmitTime')"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('common:action:action')" width="200">
<template slot-scope="scope">
<el-button
icon="el-icon-view"
:title="$t('common:button:view')"
circle
@click.stop="preview(scope.row)"
/>
<el-button icon="el-icon-view" :title="$t('common:button:view')" circle @click.stop="preview(scope.row)" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<el-dialog :visible.sync="preview_visible" fullscreen>
<div style="height: 100%; overflow: auto">
<preview
:isEN="isEN"
:isAll="isAll"
:reviewerId.sync="reviewerId"
v-if="preview_visible"
/>
<preview :isEN="isEN" :isAll="isAll" :reviewerId.sync="reviewerId" v-if="preview_visible" />
</div>
</el-dialog>
</box-content>
</template>
<script>
const otherId = 'ef84e9cb-f1a6-49d7-b6da-34be2c12abd5'
import { getTrialDoctorList } from '@/api/dictionary'
import Pagination from '@/components/Pagination'
import BoxContent from '@/components/BoxContent'
import preview from '@/views/reviewers/curriculumVitae/preview.vue'
import { mapGetters } from 'vuex'
import store from '@/store'
const searchDataDefault = () => {
return {
SubspecialityId: null,
@@ -232,6 +155,7 @@ export default {
reviewerId: null,
isAll: false,
preview_visible: false,
otherId,
}
},
methods: {
@@ -287,6 +211,9 @@ export default {
immediate: true,
},
},
mounted() {
store.dispatch('global/getHospital')
},
computed: {
...mapGetters(['hospitalList']),
isEN() {
@@ -328,38 +255,44 @@ export default {
])
},
TITLE() {
return `${this.$fd('ArchiveType', this.ArchiveTypeEnum)}${
this.isEN ? this.rowData.Name : this.rowData.NameCN
}`
return `${this.$fd('ArchiveType', this.ArchiveTypeEnum)}${this.isEN ? this.rowData.Name : this.rowData.NameCN
}`
},
},
}
</script>
<style lang="scss" scoped>
<style lang="scss" scoped>
.title {
line-height: 40px;
font-weight: bold;
margin-bottom: 10px;
}
.fileName {
display: inline-block;
max-width: 100%;
white-space: nowrap; /* 文本不换行 */
overflow: hidden; /* 超出部分隐藏 */
white-space: nowrap;
/* 文本不换行 */
overflow: hidden;
/* 超出部分隐藏 */
text-overflow: ellipsis;
}
.fileBtnBox {
display: inline-block;
width: 50px;
i {
cursor: pointer;
color: #409eff;
margin-right: 3px;
&:last-child {
margin: 0;
}
}
}
.topForm {
.el-form-item {
margin-right: 30px;

Some files were not shown because too many files have changed in this diff Show More