103 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
caiyiling bf57b75bed 肿瘤学阅片配置更改
continuous-integration/drone/push Build is passing
2025-03-12 10:46:38 +08:00
caiyiling 0d9a77f4a5 文件管理模块列宽调整
continuous-integration/drone/push Build is passing
2025-03-12 10:24:25 +08:00
caiyiling 7f3da436c4 后台管理页面样式调整
continuous-integration/drone/push Build is passing
2025-03-12 10:21:40 +08:00
caiyiling 9e1cd5a099 配置文件更改
continuous-integration/drone/push Build is passing
2025-03-12 09:34:50 +08:00
caiyiling 639351c469 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-12 09:31:16 +08:00
caiyiling fa173a32fb 非dicom文件更改 2025-03-12 09:30:51 +08:00
wangxiaoshuang b93ab130fb 追溯显示信息右对齐
continuous-integration/drone/push Build is passing
2025-03-12 09:20:56 +08:00
caiyiling c6a6029f38 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-11 17:41:03 +08:00
caiyiling ca907a5196 非dicom阅片更改 2025-03-11 17:40:44 +08:00
wangxiaoshuang b4fe2a1c06 ir重阅,pm驳回,签名后无响应
continuous-integration/drone/push Build is passing
2025-03-11 17:00:01 +08:00
wangxiaoshuang 40061db7f7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web 2025-03-11 16:59:49 +08:00
wangxiaoshuang 513e9b018a spm审批签署-重阅审批,中心编号筛选查询无效 2025-03-11 16:37:59 +08:00
wangxiaoshuang 0c7b4fbfdd 影像重传,确认完成时,签名中XXX未替换 2025-03-11 16:35:10 +08:00
caiyiling 74893a51c7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-11 16:04:55 +08:00
caiyiling 305b6ab294 非dicom缩略图更改 2025-03-11 16:00:10 +08:00
wangxiaoshuang 920c95f611 非dicom预览pdf和zip缩略图
continuous-integration/drone/push Build is passing
2025-03-11 15:05:31 +08:00
wangxiaoshuang f73eabed03 培训记录删除文件后授权状态改为否、禁用下载按钮
continuous-integration/drone/push Build is passing
2025-03-11 14:41:34 +08:00
wangxiaoshuang e99c77fb0d 培训记录上传单个文件问题修复
continuous-integration/drone/push Build is running
2025-03-11 14:39:36 +08:00
wangxiaoshuang ec37ca2d3e 一般文件记录删除文件后授权状态改为否、禁用下载按钮
continuous-integration/drone/push Build is passing
2025-03-11 14:32:49 +08:00
wangxiaoshuang 6a6a26feb7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-11 14:18:07 +08:00
wangxiaoshuang 5676bb6e57 1 2025-03-11 14:17:57 +08:00
caiyiling 200aa7c0f8 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is running
2025-03-11 14:16:16 +08:00
caiyiling bf4f0c7245 本地预览影像更改 2025-03-11 14:15:52 +08:00
wangxiaoshuang 21dab27e0b 国际化排序
continuous-integration/drone/push Build is passing
2025-03-11 14:11:18 +08:00
wangxiaoshuang 7b90715953 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-11 13:53:55 +08:00
wangxiaoshuang cb8bc506a7 项目文档上传弹框文件数量没有限制时2才显示上传文件夹按钮 2025-03-11 13:53:38 +08:00
caiyiling 7a69227888 邮件列表列宽调整
continuous-integration/drone/push Build is passing
2025-03-11 13:11:59 +08:00
caiyiling 0785219954 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing
2025-03-11 11:52:52 +08:00
caiyiling b5f2cfeaff 国际化补充 2025-03-11 11:52:38 +08:00
wangxiaoshuang 4164b24bd9 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing
2025-03-11 11:41:49 +08:00
wangxiaoshuang 49b723ab01 上传同名文件时进度条出错 2025-03-11 11:41:30 +08:00
128 changed files with 5157 additions and 2464 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
+34 -4
View File
@@ -62,12 +62,14 @@
v-adaptive="{ bottomOffset: 50 }"
height="100"
style="width: 100%"
@sort-change="handleSortByColumn"
>
<el-table-column
prop="Code"
:label="$t('il8n:table:label')"
width="300"
show-overflow-tooltip
sortable="custom"
>
</el-table-column>
<!-- <el-table-column-->
@@ -79,7 +81,11 @@
<!-- {{scope.row.Description}}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="Value" :label="$t('il8n:table:en')">
<el-table-column
prop="Value"
:label="$t('il8n:table:en')"
sortable="custom"
>
<template slot-scope="scope">
<el-input
v-model="scope.row.Value"
@@ -92,7 +98,11 @@
></el-input>
</template>
</el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:cn')">
<el-table-column
prop="ValueCN"
:label="$t('il8n:table:cn')"
sortable="custom"
>
<template slot-scope="scope">
<el-input
v-model="scope.row.ValueCN"
@@ -105,7 +115,11 @@
></el-input>
</template>
</el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:state')">
<el-table-column
prop="ValueCN"
:label="$t('il8n:table:state')"
sortable="custom"
>
<template slot-scope="scope">
<el-select
v-model="scope.row.State"
@@ -122,7 +136,11 @@
</el-select>
</template>
</el-table-column>
<el-table-column prop="Version" :label="$t('il8n:table:Version')">
<el-table-column
prop="Version"
:label="$t('il8n:table:Version')"
sortable="custom"
>
</el-table-column>
</el-table>
<div style="text-align: right; padding-top: 10px; padding-right: 10px">
@@ -195,6 +213,18 @@ export default {
// },
// },
methods: {
// 排序
handleSortByColumn(column) {
if (column.order === 'ascending') {
this.tableData.sort((a, b) =>
a[column.prop].localeCompare(b[column.prop])
)
} else {
this.tableData.sort((a, b) =>
b[column.prop].localeCompare(a[column.prop])
)
}
},
handleStateChange() {
this.tableData.forEach((item) => {
item.State = this.State
+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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 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]) ||
+17 -16
View File
@@ -90,7 +90,7 @@
custom-class="base-dialog-wrapper"
append-to-body
>
<DicomTags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
<dicom-tags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
</el-dialog>
</div>
</template>
@@ -217,10 +217,10 @@ export default {
this.stack.description = dicomSeries.description
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
var imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
// var imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
// var instanceId = imageId.split('/')[imageId.split('/').length - 1]
// instanceId = instanceId.split('.')[0]
// this.stack.instanceId = instanceId
this.toolState.clipPlaying = false
const element = this.$refs.canvas
cornerstone.enable(element)
@@ -346,9 +346,9 @@ export default {
// return
// }
// this.stack.instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
// instanceId = instanceId.split('.')[0]
// this.stack.instanceId = instanceId
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
this.resetWwwc()
},
@@ -415,15 +415,16 @@ export default {
},
onImageRendered(e) {
var imageId = e.detail.image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
// var imageId = e.detail.image.imageId
// var instanceId = imageId.split('/')[imageId.split('/').length - 1]
// instanceId = instanceId.split('.')[0]
if (this.imageId !== instanceId) {
this.getOrientationMarker(e.detail.element)
this.imageId = instanceId
}
this.stack.instanceId = instanceId
// if (this.imageId !== instanceId) {
// this.getOrientationMarker(e.detail.element)
// this.imageId = instanceId
// }
this.getOrientationMarker(e.detail.element)
// this.stack.instanceId = instanceId
var viewport = e.detail.viewport
this.dicomInfo.wwwc = `${Math.round(
viewport.voi.windowWidth
@@ -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>
+5 -5
View File
@@ -50,11 +50,11 @@ export const constantRoutes = [
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/test',
component: () => import('@/views/test/index'),
hidden: true
},
// {
// path: '/test',
// component: () => import('@/views/test/index'),
// hidden: true
// },
{
path: '/resetpassword',
component: () => import('@/views/forgetpassword/index'),
+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
})
+235 -121
View File
@@ -1,5 +1,5 @@
<template>
<div ref="preview-wrapper">
<div ref="preview-wrapper" class="preview-wrapper">
<div class="viewerContainer">
<div class="viewerContentWrapper" style="padding-top:25px;">
<div class="viewerLeftSidePanel">
@@ -38,7 +38,39 @@
</span>
</span>-->
<div class="viewernavitextwrapper">
<div style="padding: 1px;">#{{ item.seriesNumber }}</div>
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div style="padding: 1px;">#{{ item.seriesNumber }}</div>
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
<el-popover
v-model="item.isShowPopper"
placement="right-start"
trigger="manual"
popper-class="instance_frame_wrapper"
>
<div style="text-align: right;">
<i class="el-icon-circle-close" style="font-size: 20px;cursor: pointer;color:#ddd;" @click="item.isShowPopper = false" />
</div>
<div class="frame_list">
<div
v-for="(instance, idx) in item.instanceInfoList"
:key="instance.InstanceUid"
class="frame_content"
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(item, index, instance)"
>
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>
{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}
</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" @click="popperClick(seriesList, item)" />
</el-popover>
</div>
</div>
<div style="padding: 1px;">{{ item.description }}</div>
<div
v-show="item.instanceCount"
@@ -147,7 +179,11 @@ export default {
})
var imageIds = []
let isExistMutiFrames = false
let instanceInfoList = []
series.instanceList.forEach(function(instance) {
console.log(instance)
let instanceInfo = {}
var fileId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
instance.file
)
@@ -155,7 +191,19 @@ export default {
for (var i = 0; i < instance.frameCount; ++i) {
imageIds.push(`${fileId}?frame=${i}`)
}
} else imageIds.push(fileId)
isExistMutiFrames = true
instanceInfo.NumberOfFrames = instance.frameCount
instanceInfo.InstanceNumber = instance.instanceNumber
instanceInfo.InstanceUid = instance.instanceUid
instanceInfo.FileId = fileId
} else {
imageIds.push(fileId)
instanceInfo.NumberOfFrames = 0
instanceInfo.InstanceNumber = instance.instanceNumber
instanceInfo.InstanceUid = instance.instanceUid
instanceInfo.FileId = fileId
}
instanceInfoList.push(instanceInfo)
})
scope.seriesList.push({
@@ -164,13 +212,43 @@ export default {
modality: series.modality,
instanceCount: series.instanceList.length,
imageIds: imageIds,
previewImageId: imageIds[0]
previewImageId: imageIds[0],
isExistMutiFrames: isExistMutiFrames,
instanceInfoList: instanceInfoList,
isShowPopper: false
})
})
this.showSeriesImage(0)
},
popperClick(seriesList, series) {
for (let i = 0; i < seriesList.length; i++) {
if (seriesList[i].isShowPopper) {
seriesList[i].isShowPopper = false
}
}
series.isShowPopper = !series.isShowPopper
},
showMultiFrames(series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
const imageIds = []
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
imageIds.push(`${instanceInfo.FileId}?frame=${j}`)
}
} else {
imageIds.push(instanceInfo.FileId)
}
const seriesInfo = {
seriesNumber: series.seriesNumber,
description: series.description,
modality: series.modality,
instanceCount: series.instanceCount,
imageIds: imageIds,
previewImageId: imageIds[0],
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
},
showSeriesImage(seriesIndex) {
// if (seriesIndex === this.currentSeriesIndex) return;
this.currentSeriesIndex = seriesIndex
@@ -183,136 +261,172 @@ export default {
}
</script>
<style scoped>
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
<style lang="scss">
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.viewerContainer {
display: block;
height: 100%;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
background-color: #444;
overflow: hidden;
}
.viewerContainer {
width: 100%;
display: block;
height: 100%;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
background-color: #444;
overflow: hidden;
}
.viewerBanner {
background: linear-gradient(0, #444, #222);
min-height: 28px;
font-size: 16px;
margin: 0;
height: 30px;
padding-top: 0;
padding-left: 5px;
padding-right: 5px;
font-weight: bold;
}
.viewerBanner {
background: linear-gradient(0, #444, #222);
min-height: 28px;
font-size: 16px;
margin: 0;
height: 30px;
padding-top: 0;
padding-left: 5px;
padding-right: 5px;
font-weight: bold;
}
.viewerContentWrapper {
display: flex;
flex-direction: row;
width: 100%;
padding: 5px;
height: 99%;
/* height: 95%; */
overflow: hidden;
text-overflow: clip;
white-space: nowrap;
}
.viewerContentWrapper {
display: flex;
flex-direction: row;
width: 100%;
padding: 5px;
height: 99%;
/* height: 95%; */
overflow: hidden;
text-overflow: clip;
white-space: nowrap;
}
.viewerContentWrapper > div {
display: inline-block;
white-space: normal;
}
.viewerContentWrapper > div {
display: inline-block;
white-space: normal;
}
.viewerLeftSidePanel {
width: 200px;
background-color: #323232;
box-sizing: border-box;
margin: 0;
padding: 0;
margin-right: 2px;
color: #d0d0d0;
overflow-y: auto;
}
.viewerLeftSidePanel {
width: 200px;
background-color: #323232;
box-sizing: border-box;
margin: 0;
padding: 0;
margin-right: 2px;
color: #d0d0d0;
overflow-y: auto;
}
.viewerContentWrapper > div > .sidePanelBody {
background: rgba(50, 50, 50, 1);
word-break: break-all;
display: table;
width: 100%;
border: 1px solid #3e3f3a;
}
.viewerContentWrapper > div > .sidePanelBody {
background: rgba(50, 50, 50, 1);
word-break: break-all;
display: table;
width: 100%;
border: 1px solid #3e3f3a;
}
.viewerContentWrapper > div > div.sidePanelBody > div {
width: 100%;
height: 100%;
}
.viewerContentWrapper > div > div.sidePanelBody > div {
width: 100%;
height: 100%;
}
.studyDesc {
font-weight: bold;
font-size: 13px;
text-align: center;
background: rgb(88 84 83);
color: #d0d0d0;
padding: 5px;
}
.studyDesc {
font-weight: bold;
font-size: 13px;
text-align: center;
background: rgb(88 84 83);
color: #d0d0d0;
padding: 5px;
}
.ps {
overflow: hidden !important;
overflow-anchor: none;
-ms-overflow-style: none;
touch-action: auto;
-ms-touch-action: auto;
}
.ps {
overflow: hidden !important;
overflow-anchor: none;
-ms-overflow-style: none;
touch-action: auto;
-ms-touch-action: auto;
}
.viewerLeftSidePanel .viewernavigatorwrapper {
display: flex;
width: 196px;
height: 84px;
padding: 1px 2px 1px 8px;
margin: 6px 0 6px 1px;
border-radius: 2px;
border: 1px solid #404040;
}
.viewerLeftSidePanel .viewernavigatorwrapper {
display: flex;
width: 196px;
height: 84px;
padding: 1px 2px 1px 8px;
margin: 6px 0 6px 1px;
border-radius: 2px;
border: 1px solid #404040;
}
.ui-draggable-handle {
-ms-touch-action: none;
touch-action: none;
}
.ui-draggable-handle {
-ms-touch-action: none;
touch-action: none;
}
.viewerLeftSidePanel .image-preview {
border: 2px solid #252525;
cursor: pointer;
}
.viewerLeftSidePanel .image-preview {
border: 2px solid #252525;
cursor: pointer;
}
.viewerLeftSidePanel .viewernavitextwrapper {
flex: 1;
padding: 3px 1px 3px 4px;
vertical-align: top;
font-size: 12px;
}
.viewerLeftSidePanel .viewernavitextwrapper {
flex: 1;
padding: 3px 1px 3px 4px;
vertical-align: top;
font-size: 12px;
}
.viewerSideActive {
background: #16477b;
background: #16477b80;
border: 1px solid #23527b;
}
.viewerSideActive {
background: #16477b;
background: #16477b80;
border: 1px solid #23527b;
}
.viewerContent {
flex: 1;
height: 100%;
display: block;
background-color: black;
color: #d0d0d0;
font-size: 13px;
}
.viewerContent {
flex: 1;
height: 100%;
display: block;
background-color: black;
color: #d0d0d0;
font-size: 13px;
}
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_list{
max-height: 500px;
overflow-y: auto;
}
.instance_frame_wrapper ::-webkit-scrollbar {
width: 7px;
height: 7px;
}
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.frame_content{
/* height: 50px; */
padding: 10px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
</style>
@@ -9,10 +9,10 @@
class="upload-temporary-file"
>
<div class="base-dialog-body">
<el-form-item label="Code" prop="Code">
<el-form-item :label="$t('dictionary:attachment:label:code')" prop="Code">
<el-input v-model="form.Code" />
</el-form-item>
<el-form-item label="业务场景: " prop="BusinessScenarioEnum">
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')" prop="BusinessScenarioEnum">
<el-select
v-model="form.BusinessScenarioEnum"
style="width:100%;"
@@ -28,7 +28,7 @@
</el-select>
</el-form-item>
<el-form-item label="文件: ">
<el-form-item :label="$t('dictionary:attachment:export:form:file')">
<div class="upload-container">
<el-upload
class="upload-demo"
@@ -2,7 +2,8 @@
<BaseContainer>
<template slot="search-container">
<el-form :inline="true" size="small">
<el-form-item label="业务场景">
<!-- 业务场景 -->
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')">
<el-select
v-model="searchData.BusinessScenarioEnum"
style="width:150px;"
@@ -16,7 +17,8 @@
</el-select>
</el-form-item>
<el-form-item label="文件名称">
<!-- 文件名称 -->
<el-form-item :label="$t('dictionary:attachment:label:name')">
<el-input
v-model="searchData.Name"
style="width:130px;"
@@ -37,7 +39,6 @@
</el-form>
<el-button
type="primary"
icon="el-icon-plus"
style="margin-left:auto;"
size="small"
@click="handleAdd"
@@ -57,14 +58,14 @@
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="Code"
:label="$t('dictionary:attachment:label:code')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="BusinessScenarioEnum"
label="业务场景"
:label="$t('dictionary:attachment:label:businessScenario')"
show-overflow-tooltip
sortable="custom"
>
@@ -76,18 +77,18 @@
<el-table-column
prop="Name"
label="文件名称"
:label="$t('dictionary:attachment:label:name')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Description"
label="描述"
:label="$t('dictionary:attachment:label:description')"
show-overflow-tooltip
/>
<el-table-column
prop="IsDeleted"
label="是否废除"
:label="$t('dictionary:attachment:label:isDeleted')"
show-overflow-tooltip
sortable="custom"
>
@@ -98,30 +99,30 @@
</el-table-column>
<el-table-column
prop="UpdateTime"
label="上传时间"
:label="$t('dictionary:attachment:label:updateTime')"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action">
<el-table-column label="Action" width="300">
<template slot-scope="scope">
<el-button
type="text"
@click="handleDownload(scope.row)"
>
下载
{{ $t('common:button:download') }}
</el-button>
<el-button
type="text"
@click="handleEdit(scope.row)"
>
编辑
{{ $t('common:action:edit') }}
</el-button>
<el-button
type="text"
@click="handleDelete(scope.row)"
>
删除
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
@@ -176,9 +177,9 @@ export default {
},
methods: {
handleDelete(row) {
this.$confirm('确定删除该文件?').then(() => {
this.$confirm(this.$t('dictionary:attachment:export:confirm:delete')).then(() => {
deleteCommonDocument(row.Id).then(() => {
this.$message.success('删除成功')
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.getList()
})
})
@@ -195,7 +196,7 @@ export default {
},
// 新增
handleAdd() {
this.editDialog.title = 'Add'
this.editDialog.title = this.$t('common:button:new')
this.currentRow = { FileTypeEnum: FileTypeEnum }
this.editDialog.visible = true
},
@@ -208,7 +209,7 @@ export default {
},
// 编辑
handleEdit(row) {
this.editDialog.title = 'Edit'
this.editDialog.title = this.$t('common:action:edit')
this.currentRow = { ...row }
this.editDialog.visible = true
},
@@ -9,7 +9,7 @@
class="upload-temporary-file"
>
<div class="base-dialog-body">
<el-form-item label="Code" prop="Code">
<el-form-item :label="$t('dictionary:attachment:export:search:code')" prop="Code">
<el-input v-model="form.Code" />
</el-form-item>
<el-form-item
@@ -76,8 +76,9 @@
:label="$t('dictionary:attachment:export:form:isDeleted')"
>
<el-radio-group v-model="form.IsDeleted">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
<el-radio v-for="item of $d.YesOrNo" :key="`IsDeleted${item.value}`" :label="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
@@ -39,7 +39,6 @@
</el-form-item>
<el-button
type="primary"
icon="el-icon-plus"
style="float: right"
size="small"
@click="handleAdd"
@@ -60,7 +59,7 @@
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="Code"
:label="$t('dictionary:attachment:export:search:code')"
show-overflow-tooltip
sortable="custom"
/>
@@ -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') }}
@@ -235,7 +234,7 @@ export default {
},
// 新增
handleAdd() {
this.editDialog.title = 'Add'
this.editDialog.title = this.$t('common:button:new')
this.currentRow = { FileTypeEnum: FileTypeEnum }
this.editDialog.visible = true
},
@@ -252,7 +251,7 @@ export default {
},
// 编辑
handleEdit(row) {
this.editDialog.title = 'Edit'
this.editDialog.title = this.$t('common:action:edit')
this.currentRow = { ...row }
this.editDialog.visible = true
},
@@ -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') }}
@@ -247,7 +246,7 @@ export default {
},
// 新增
handleAdd() {
this.title = 'Add'
this.title = this.$t('common:button:new')
this.currentRow = {}
this.editVisible = true
},
@@ -262,7 +261,7 @@ export default {
},
// 编辑
handleEdit(row) {
this.title = 'Edit'
this.title = this.$t('common:action:edit')
this.currentRow = { ...row }
this.editVisible = true
},
@@ -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>
@@ -5,7 +5,7 @@
:rules="rules"
class="demo-ruleForm"
size="small"
label-width="120px"
label-width="140px"
>
<div class="base-dialog-body">
<!-- CRO Name -->
@@ -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>
@@ -124,7 +121,7 @@
<el-table-column
prop="CityCN"
:label="$t('institutions:hospitals:label:cityCN')"
width="120"
width="130"
show-overflow-tooltip
sortable="custom"
/>
@@ -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>
@@ -3,7 +3,7 @@
ref="organForm"
v-loading="loading"
:model="form"
label-width="130px"
label-width="170px"
size="small"
:rules="rules"
>
@@ -8,32 +8,36 @@
label-width="160px"
size="small"
>
<el-form-item label="Group: " prop="Group">
<el-form-item :label="$t('template:anonymization:label:group')" prop="Group">
<el-input v-model="form.Group" />
</el-form-item>
<el-form-item label="Element: " prop="Group">
<el-form-item :label="$t('template:anonymization:label:element')" prop="Group">
<el-input v-model="form.Element" />
</el-form-item>
<el-form-item label="tag Description: " prop="Group">
<!-- tag Description -->
<el-form-item :label="$t('template:anonymization:label:tagDescription')" prop="Group">
<el-input v-model="form.TagDescription" />
</el-form-item>
<el-form-item label="Tag DescriptionCN: " prop="Group">
<!-- Tag DescriptionCN -->
<el-form-item :label="$t('template:anonymization:label:tagDescriptionCN')" prop="Group">
<el-input v-model="form.TagDescriptionCN" />
</el-form-item>
<el-form-item label="Value Representation: " prop="Group">
<!-- Value Representation -->
<el-form-item :label="$t('template:anonymization:label:valueRepresentation')" prop="Group">
<el-input v-model="form.ValueRepresentation" />
</el-form-item>
<el-form-item label="Is Fixed: ">
<!-- Is Fixed -->
<el-form-item :label="$t('template:anonymization:label:isFixed')">
<el-switch
v-model="form.IsFixed"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
<el-form-item label="Replace Value: ">
<el-form-item :label="$t('template:anonymization:label:valueReplace')">
<el-input v-model="form.ReplaceValue" />
</el-form-item>
<el-form-item label="Is Enable: ">
<el-form-item :label="$t('template:anonymization:label:isEnable')">
<el-switch
v-model="form.IsEnable"
:active-value="true"
@@ -43,8 +47,8 @@
</el-form>
</template>
<template slot="dialog-footer">
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">{{ $t('common:button:cancel') }}</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
</template>
</base-model>
</template>
@@ -82,7 +86,7 @@ export default {
IsAdd: false
},
rules: {
Group: [{ required: true, message: 'Please specify', trigger: 'blur' }]
Group: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }]
},
model_cfg: { visible: false, showClose: true, width: '600px', title: '' }
}
@@ -108,7 +112,7 @@ export default {
this.btnLoading = true
addOrUpdateSystemAnonymization(this.form).then(res => {
this.btnLoading = false
this.$message.success('Saved successfully!')
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.model_cfg.visible = false
this.$emit('getList')
}).catch(() => {
@@ -2,17 +2,21 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="Group:">
<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;" />
</el-form-item>
<el-form-item label="Element:">
<!-- Element -->
<el-form-item :label="$t('template:anonymization:label:element')">
<el-input v-model="searchData.Element" clearable style="width:120px;" />
</el-form-item>
<el-form-item label="Tag Description:">
<!-- Tag Description -->
<el-form-item :label="$t('template:anonymization:label:tagDescription')">
<el-input v-model="searchData.TagDescription" clearable style="width:120px;" />
</el-form-item>
<el-form-item label="Tag DescriptionCN:">
<!-- Tag DescriptionCN -->
<el-form-item :label="$t('template:anonymization:label:tagDescriptionCN')">
<el-input v-model="searchData.TagDescriptionCN" clearable style="width:120px;" />
</el-form-item>
<el-form-item>
@@ -29,7 +33,7 @@
</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">{{ $t('common:button:new') }}</el-button>
</span>
</div>
@@ -38,37 +42,42 @@
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
size="small"
height="100"
>
<el-table-column type="index" width="60" />
<!-- Group -->
<el-table-column
prop="Group"
label="Group"
:label="$t('template:anonymization:label:group')"
show-overflow-tooltip
/>
<!-- Element -->
<el-table-column
prop="Element"
label="Element"
:label="$t('template:anonymization:label:element')"
show-overflow-tooltip
min-width="110"
/>
<!-- Tag Description -->
<el-table-column
prop="TagDescription"
label="Tag Description"
:label="$t('template:anonymization:label:tagDescription')"
min-width="110"
/>
<!-- Tag DescriptionCN -->
<el-table-column
prop="TagDescriptionCN"
label="Tag DescriptionCN"
:label="$t('template:anonymization:label:tagDescriptionCN')"
min-width="110"
/>
<!-- Value Representation -->
<el-table-column
prop="ValueRepresentation"
label="Value Representation"
:label="$t('template:anonymization:label:valueRepresentation')"
min-width="110"
/>
<el-table-column label="Is Fixed" width="100">
<!-- Is Fixed -->
<el-table-column :label="$t('template:anonymization:label:isFixed')" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsFixed"
@@ -78,12 +87,14 @@
/>
</template>
</el-table-column>
<!-- Value Replace -->
<el-table-column
prop="ReplaceValue"
label="Value Replace"
:label="$t('template:anonymization:label:valueReplace')"
min-width="110"
/>
<el-table-column label="Is Enable" width="100" fixed="right">
<!-- Is Enable -->
<el-table-column :label="$t('template:anonymization:label:isEnable')" width="100" fixed="right">
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsEnable"
@@ -93,21 +104,19 @@
/>
</template>
</el-table-column>
<el-table-column label="Action" width="200" fixed="right">
<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)"
>
Edit
{{ $t('common:button:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
Delete
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
@@ -153,7 +162,7 @@ export default {
switchChange(event, item) {
this.loading = true
addOrUpdateSystemAnonymization(item).then(res => {
this.$message.success('Saved successfully!')
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false
}).catch(() => {
this.loading = false
@@ -161,12 +170,12 @@ export default {
},
handleAdd() {
this.$nextTick(() => {
this.$refs['AddDICOMConfig'].openDialog('New Anonymization', {})
this.$refs['AddDICOMConfig'].openDialog(this.$t('common:button:new'), {})
})
},
handleEdit(row) {
this.$nextTick(() => {
this.$refs['AddDICOMConfig'].openDialog('Edit Anonymization', row)
this.$refs['AddDICOMConfig'].openDialog(this.$t('common:action:edit'), row)
})
},
handleDelete(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: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>
@@ -53,27 +53,29 @@
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
size="small"
height="100"
>
<el-table-column type="index" width="60" />
<el-table-column type="index" width="40" />
<!-- 临床数据名称 -->
<el-table-column
prop="ClinicalDataSetName"
:label="$t('trials:processCfg:title:clinicalDataName')"
show-overflow-tooltip
min-width="160"
/>
<!-- 临床数据名称EN -->
<el-table-column
prop="ClinicalDataSetEnName"
:label="$t('dictionary:clinicalData:label:clinicalDataNameEn')"
show-overflow-tooltip
min-width="190"
/>
<!-- 上传人 -->
<el-table-column
prop="UploadRole"
:label="$t('trials:processCfg:title:uploader')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope">
{{ $fd('ClinicalDataUploadRole',scope.row.UploadRole) }}
@@ -84,6 +86,7 @@
prop="ClinicalDataLevel"
:label="$t('trials:processCfg:title:dataLevel')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope">
{{ $fd('ClinicalLevel',scope.row.ClinicalDataLevel) }}
@@ -94,6 +97,7 @@
prop="ClinicalUploadType"
:label="$t('trials:processCfg:title:transferType')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope">
{{ $fd('ClinicalUploadType',scope.row.ClinicalUploadType) }}
@@ -104,6 +108,7 @@
prop="CriterionEnumList"
:label="$t('trials:processCfg:label:criterion')"
show-overflow-tooltip
min-width="200"
>
<template slot-scope="scope">
{{ scope.row.CriterionEnumList.map(v => $fd('CriterionType', v)).toString() }}
@@ -114,6 +119,7 @@
prop="FileName"
:label="$t('trials:processCfg:title:module')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope">
{{ scope.row.FileName }}
@@ -124,6 +130,7 @@
prop="EnFileName"
:label="$t('trials:processCfg:title:enModule')"
show-overflow-tooltip
min-width="140"
>
<template slot-scope="scope">
{{ scope.row.EnFileName }}
@@ -134,6 +141,7 @@
prop="IsEnable"
:label="$t('dictionary:clinicalData:label:status')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope">
<!-- <el-tag v-if="scope.row.IsEnable">启用</el-tag>
@@ -147,14 +155,14 @@
prop="CreateTime"
:label="$t('dictionary:clinicalData:label:CreateTime')"
show-overflow-tooltip
min-width="140"
/>
<el-table-column :label="$t('common:action:action')" width="340" 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)"
>
@@ -163,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)"
>
@@ -173,8 +180,7 @@
<!-- 下载 -->
<el-button
v-else
type="primary"
size="mini"
type="text"
:disabled="!scope.row.EnFileName"
@click="handleDownloadTpl(scope.row.EnPath)"
>
@@ -182,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})
},
@@ -6,7 +6,7 @@
size="small"
:rules="rules"
:disabled="type === 'look'"
label-width="140px"
label-width="220px"
>
<div class="base-dialog-body" style="height: 550px; display:flex;flex-direction: column;">
<div style="height: 150px;">
@@ -62,32 +62,35 @@
prop="GroupName"
:label="$t('trials:readingUnit:qsList:title:groupName')"
show-overflow-tooltip
min-width="120"
/>
<!-- 分组(EN) -->
<el-table-column
prop="GroupEnName"
:label="$t('dictionary:template:criterionConfig:title:groupNameEn')"
show-overflow-tooltip
width="140"
min-width="140"
/>
<!-- 名称 -->
<el-table-column
prop="QuestionName"
:label="$t('trials:readingUnit:qsList:title:qsName')"
show-overflow-tooltip
min-width="140"
/>
<!-- 名称(EN) -->
<el-table-column
prop="QuestionEnName"
:label="$t('dictionary:template:criterionConfig:title:qsNameEn')"
show-overflow-tooltip
width="140"
min-width="160"
/>
<!-- 题型 -->
<el-table-column
prop="Type"
:label="$t('trials:readingUnit:qsList:title:type')"
show-overflow-tooltip
min-width="180"
>
<template slot-scope="scope">
{{ $fd('Criterion_Question_Type',scope.row.Type) }}
@@ -98,6 +101,7 @@
prop="ShowQuestion"
:label="$t('trials:readingUnit:qsList:title:isShow')"
show-overflow-tooltip
min-width="100"
>
<template slot-scope="scope">
{{ $fd('ShowQuestion',scope.row.ShowQuestion) }}
@@ -108,6 +112,7 @@
prop="IsRequired"
:label="$t('trials:readingUnit:qsList:title:isRequired')"
show-overflow-tooltip
min-width="100"
>
<template slot-scope="scope">
{{ $fd('QuestionRequired',scope.row.IsRequired) }}
@@ -117,7 +122,7 @@
<el-table-column
prop="IsJudgeQuestion"
:label="$t('trials:readingUnit:qsList:title:isJudgeQuestion')"
width="120"
min-width="200"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -128,7 +133,7 @@
<el-table-column
prop="IsShowInDicom"
:label="$t('trials:readingUnit:qsList:title:isShowInDicom')"
width="150"
min-width="200"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -147,7 +152,7 @@
<el-table-column
prop="GlobalReadingShowType"
:label="$t('trials:readingUnit:qsList:title:globalReadingShowType')"
width="160"
min-width="240"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -169,7 +174,7 @@
<el-table-column
prop="QuestionType"
:label="$t('dictionary:template:criterionConfig:table:questionType')"
width="140"
min-width="160"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -201,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)"
>
@@ -232,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)"
>
@@ -258,11 +259,11 @@
:visible.sync="addOrEdit.visible"
:close-on-click-modal="false"
:title="`${addOrEdit.title}`"
width="650px"
width="800px"
append-to-body
custom-class="base-dialog-wrapper"
>
<CriterionQuestionForm
<criterion-question-form
ref="addOrEdit"
:data="rowData"
:type="type"
@@ -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>
@@ -84,7 +84,6 @@
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
size="small"
height="100"
@sort-change="handleSortByColumn"
ref="criterionsTbl"
@@ -96,6 +95,7 @@
:label="$t('trials:auditRecord:table:criterion')"
show-overflow-tooltip
sortable="custom"
width="180"
/>
<!-- 标准类型 -->
<el-table-column
@@ -103,6 +103,7 @@
:label="$t('dictionary:template:criterionConfig:table:criterionType')"
show-overflow-tooltip
sortable="custom"
width="180"
>
<template slot-scope="scope">
{{ $fd('CriterionType',scope.row.CriterionType) }}
@@ -114,6 +115,7 @@
:label="$t('dictionary:template:criterionConfig:table:criterionGroup')"
show-overflow-tooltip
sortable="custom"
width="160"
>
<template slot-scope="scope">
{{ $fd('CriterionGroup',scope.row.CriterionGroup) }}
@@ -124,6 +126,7 @@
prop="IsCompleteConfig"
:label="$t('dictionary:template:criterionConfig:table:isCompleteConfig')"
sortable="custom"
width="220"
>
<template slot-scope="scope">
@@ -170,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)"
>
@@ -219,9 +218,9 @@
:close-on-click-modal="false"
append-to-body
custom-class="base-dialog-wrapper"
width="500px"
width="600px"
>
<AddCriterion
<add-criterion
:data="rowData"
@close="addDialog.visible = false"
@getList="getList"
@@ -1,6 +1,6 @@
<template>
<div style="position: relative">
<el-form size="small" :inline="true" label-width="130px" style="position: relative;">
<el-form size="small" :inline="true" style="position: relative;">
<!-- 阅片规则 -->
<el-divider content-position="left">{{ $t('dictionary:template:globalConfig:readingRules') }}</el-divider>
<!-- 是否必须全局阅片 -->
@@ -18,7 +18,7 @@
{{ $t('dictionary:template:globalConfig:config') }}
</el-button>
</el-form>
<el-form size="small" :inline="true" label-width="110px" style="position: relative">
<el-form size="small" :inline="true" style="position: relative">
<!-- 名称 -->
<el-divider content-position="left">{{ $t('dictionary:template:globalConfig:name') }}</el-divider>
<!-- 配置 -->
@@ -44,7 +44,7 @@
<el-table-column
prop=""
:label="$t('dictionary:template:globalConfig:order')"
width="50"
width="80"
>
<template slot-scope="scope">
{{scope.$index + 1}}
@@ -1,6 +1,6 @@
<template>
<div>
<el-form size="small" :inline="true" label-width="110px" style="position: relative;">
<el-form size="small" :inline="true" style="position: relative;">
<!-- 阅片规则 -->
<el-divider content-position="left">{{ $t('dictionary:template:globalConfig:readingRules') }}</el-divider>
<!-- 是否肿瘤学阅片 -->
@@ -18,7 +18,7 @@
{{ $t('dictionary:template:globalConfig:config') }}
</el-button>
</el-form>
<el-form size="small" :inline="true" label-width="110px" style="position: relative">
<el-form size="small" :inline="true" style="position: relative">
<!-- 阅片问题 -->
<el-divider content-position="left">{{ $t('dictionary:template:oncologyConfig:reviewQs') }}</el-divider>
<!-- 配置 -->
@@ -45,7 +45,7 @@
<el-table-column
prop=""
:label="$t('dictionary:template:globalConfig:order')"
width="50"
width="80"
>
<template slot-scope="scope">
{{scope.$index + 1}}
@@ -126,7 +126,7 @@ import { getSystemOncologyInfo, setSystemOncologyInfo, getCriterionDictionary }
export default {
props: {
data: {
type: String,
type: Object,
default() { return {} }
},
criterionId: {
@@ -2,17 +2,21 @@
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="Group:">
<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;" />
</el-form-item>
<el-form-item label="Element:">
<!-- Element -->
<el-form-item :label="$t('template:anonymization:label:element')">
<el-input v-model="searchData.Element" clearable style="width:120px;" />
</el-form-item>
<el-form-item label="Tag Description:">
<!-- Tag Description -->
<el-form-item :label="$t('template:anonymization:label:tagDescription')">
<el-input v-model="searchData.TagDescription" clearable style="width:120px;" />
</el-form-item>
<el-form-item label="Tag DescriptionCN:">
<!-- Tag DescriptionCN -->
<el-form-item :label="$t('template:anonymization:label:tagDescriptionCN')">
<el-input v-model="searchData.TagDescriptionCN" clearable style="width:120px;" />
</el-form-item>
<el-form-item>
@@ -29,7 +33,7 @@
</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">{{ $t('common:button:new') }}</el-button>
</span>
</div>
@@ -38,37 +42,42 @@
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
size="small"
height="100"
>
<el-table-column type="index" width="60" />
<!-- Group -->
<el-table-column
prop="Group"
label="Group"
:label="$t('template:anonymization:label:group')"
show-overflow-tooltip
/>
<!-- Element -->
<el-table-column
prop="Element"
label="Element"
:label="$t('template:anonymization:label:element')"
show-overflow-tooltip
min-width="110"
/>
<!-- Tag Description -->
<el-table-column
prop="TagDescription"
label="Tag Description"
:label="$t('template:anonymization:label:tagDescription')"
min-width="110"
/>
<!-- Tag DescriptionCN -->
<el-table-column
prop="TagDescriptionCN"
label="Tag DescriptionCN"
:label="$t('template:anonymization:label:tagDescriptionCN')"
min-width="110"
/>
<!-- Value Representation -->
<el-table-column
prop="ValueRepresentation"
label="Value Representation"
:label="$t('template:anonymization:label:valueRepresentation')"
min-width="110"
/>
<el-table-column label="Is Fixed" width="100">
<!-- Is Fixed -->
<el-table-column :label="$t('template:anonymization:label:isFixed')" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsFixed"
@@ -78,12 +87,14 @@
/>
</template>
</el-table-column>
<!-- Value Replace -->
<el-table-column
prop="ReplaceValue"
label="Value Replace"
:label="$t('template:anonymization:label:valueReplace')"
min-width="110"
/>
<el-table-column label="Is Enable" width="100" fixed="right">
<!-- Is Enable -->
<el-table-column :label="$t('template:anonymization:label:isEnable')" width="100" fixed="right">
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsEnable"
@@ -93,21 +104,19 @@
/>
</template>
</el-table-column>
<el-table-column label="Action" width="200" fixed="right">
<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)"
>
Edit
{{ $t('common:action:edit') }}
</el-button>
<el-button
type="danger"
size="mini"
type="text"
@click="handleDelete(scope.row)"
>
Delete
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
@@ -152,7 +161,7 @@ export default {
switchChange(event, item) {
this.loading = true
addOrUpdateSystemAnonymization(item).then(res => {
this.$message.success('Saved successfully!')
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false
}).catch(() => {
this.loading = false
@@ -160,12 +169,12 @@ export default {
},
handleEdit(row) {
this.$nextTick(() => {
this.$refs['AddDICOMConfig'].openDialog('Edit Anonymization', row)
this.$refs['AddDICOMConfig'].openDialog(this.$t('common:action:edit'), row)
})
},
handleAdd() {
this.$nextTick(() => {
this.$refs['AddDICOMConfig'].openDialog('New IncreaseFields', {
this.$refs['AddDICOMConfig'].openDialog(this.$t('common:button:new'), {
Group: '',
Element: '',
TagDescription: '',
@@ -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>
@@ -65,7 +65,6 @@
v-adaptive="{bottomOffset:50}"
:data="list"
stripe
size="small"
height="100"
>
<!-- 序号 -->
@@ -79,12 +78,14 @@
prop="QuestionName"
:label="$t('trials:MIMqcCfg:table:questionName')"
show-overflow-tooltip
min-width="140"
/>
<!-- 审核问题 -->
<el-table-column
prop="LanguageType"
:label="$t('common:title:languageType')"
show-overflow-tooltip
min-width="160"
>
<template slot-scope="scope">
{{ $fd('LanguageType', scope.row.LanguageType) }}
@@ -95,6 +96,7 @@
prop="Type"
:label="$t('trials:qcCfg:table:type')"
show-overflow-tooltip
min-width="140"
>
<template slot-scope="scope">
{{ $fd('QcType', scope.row.Type) }}
@@ -105,12 +107,14 @@
prop="TypeValue"
:label="$t('trials:qcCfg:table:typeValue')"
show-overflow-tooltip
min-width="140"
/>
<!-- 任务类型 -->
<el-table-column
prop="ReadingCategory"
:label="$t('trials:medicalFeedbackCfg:title:taskType')"
show-overflow-tooltip
min-width="140"
>
<template slot-scope="scope">
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">
@@ -130,7 +134,7 @@
<el-table-column
prop="ReadingCategory"
:label="$t('trials:auditRecord:table:criterion')"
width="240"
min-width="160"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -142,7 +146,7 @@
<el-table-column
prop="IsGeneral"
:label="$t('dictionary:medicalAudit:label:IsGeneral')"
width="80"
min-width="120"
show-overflow-tooltip
>
<template slot-scope="scope">
@@ -156,17 +160,20 @@
prop="ParentShowOrder"
:label="$t('trials:qcCfg:table:parentQs')"
show-overflow-tooltip
min-width="140"
/>
<!-- 父问题触发值 -->
<el-table-column
prop="ParentTriggerValue"
:label="$t('trials:qcCfg:table:parentTriggerValue')"
show-overflow-tooltip
min-width="160"
/>
<!-- 是否必填 -->
<el-table-column
prop="IsRequired"
:label="$t('trials:qcCfg:table:isRequired')"
min-width="120"
>
<template slot-scope="scope">
{{ $fd('YesOrNo', scope.row.IsRequired) }}
@@ -176,24 +183,23 @@
<el-table-column
prop="IsEnable"
:label="$t('trials:qcCfg:table:isEnable')"
min-width="120"
>
<template slot-scope="scope">
{{ $fd('YesOrNo', scope.row.IsEnable) }}
</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') }}
@@ -96,7 +96,7 @@
<el-table-column
prop="OrganType"
:label="$t('trials:readingUnit:baseDataCfg:title:organType')"
min-width="120"
min-width="140"
show-overflow-tooltip
sortable="custom"
>
@@ -110,11 +110,12 @@
:label="$t('trials:readingUnit:baseDataCfg:title:classification')"
show-overflow-tooltip
sortable="custom"
min-width="140"
/>
<el-table-column
prop="ClassificationEN"
:label="$t('trials:readingUnit:baseDataCfg:title:classificationEn')"
min-width="140"
min-width="160"
show-overflow-tooltip
sortable="custom"
/>
@@ -124,6 +125,7 @@
:label="$t('trials:readingUnit:baseDataCfg:title:bodyPart')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<el-table-column
prop="PartEN"
@@ -138,6 +140,7 @@
:label="$t('trials:readingUnit:baseDataCfg:title:organ')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<el-table-column
prop="TULOCEN"
@@ -152,6 +155,7 @@
:label="$t('trials:readingUnit:baseDataCfg:title:TULAT')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<el-table-column
prop="TULATEN"
@@ -212,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>
@@ -57,7 +56,6 @@
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
size="small"
height="100"
>
<!-- 序号 -->
@@ -137,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>
@@ -206,7 +206,7 @@
:label="$t('dictionary:email:label:businessLevel')"
sortable="custom"
show-overflow-tooltip
min-width="100"
min-width="150"
>
<template slot-scope="scope">
{{ $fd('BusinessLevel', scope.row.BusinessLevelEnum) }}
@@ -218,7 +218,7 @@
:label="$t('dictionary:email:label:businessModule')"
sortable="custom"
show-overflow-tooltip
min-width="100"
min-width="160"
>
<template slot-scope="scope">
{{ $fd('BusinessModule', scope.row.BusinessModuleEnum) }}
@@ -276,7 +276,7 @@
:label="$t('dictionary:email:label:IsUrgent')"
sortable="custom"
show-overflow-tooltip
min-width="100"
min-width="110"
>
<template slot-scope="scope">
{{ $fd('EmailUrgent', scope.row.EmailUrgentEnum) }}
+4 -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>
@@ -167,6 +167,7 @@
prop="IsConfirmRecord"
show-overflow-tooltip
sortable="custom"
width="200"
>
<template slot-scope="scope">
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
@@ -240,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>
+30 -2
View File
@@ -39,13 +39,37 @@
class="img-box"
@click="selected(item, i, j, true)"
>
<div v-if="item.FileType === 'image/jpeg'" class="file-image">
<div class="file-image">
<el-image
v-if="
[
'image/jpeg',
'image/jpg',
'image/png',
'image/bmp',
].includes(item.FileType)
"
style="width: 100%; height: 100%"
:src="`${OSSclientConfig.basePath}${item.Path}?x-oss-process=image/resize,w_50,h_50/format,png`"
fit="contain"
crossorigin="anonymous"
/>
<el-image
v-else-if="item.FileType === 'application/pdf'"
style="width: 100%; height: 100%"
:src="pdf"
fit="contain"
crossorigin="anonymous"
/>
<el-image
v-else-if="
item.FileType === 'application/x-zip-compressed'
"
style="width: 100%; height: 100%"
:src="zip"
fit="contain"
crossorigin="anonymous"
/>
</div>
<div v-if="item.FileName.length < 15" class="img-text">
{{ `${j + 1}. ${item.FileName}` }}
@@ -114,6 +138,8 @@
<script>
import { getNoneDicomStudyList, setNodicomStudyState } from '@/api/trials'
import store from '@/store'
import pdf from '@/assets/pdf.png'
import zip from '@/assets/zip.jpg'
import { changeURLStatic } from '@/utils/history.js'
import Preview from './components/preview'
import PreviewFile from '@/components/PreviewFile'
@@ -127,6 +153,8 @@ export default {
},
data() {
return {
pdf,
zip,
activeName: 'first',
currentFileId: '',
currentStudyIndex: 0,
@@ -501,4 +529,4 @@ export default {
::v-deep .el-collapse-item__content {
padding-bottom: 0;
}
</style>
</style>
+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
>
@@ -4,7 +4,12 @@
{{ $t('system:retrospect:title:userFrom') }}
</div>
<div class="userFrom">
<el-form size="mini" class="base-search-form">
<el-form
size="mini"
class="base-search-form"
label-position="right"
:label-width="isEN ? '130px' : '100px'"
>
<el-form-item :label="$t('system:retrospect:form:createType')">
<span>{{ $fd('UserCeateSource', otherInfo.UserCeateSource) }}</span>
</el-form-item>
@@ -222,7 +227,7 @@
<template slot-scope="scope">
<!-- 详情 -->
<el-button
circle
type="text"
:disabled="
(scope.row.TrialStatusStr === 'Initializing' &&
!hasPermi(['role:pm'])) ||
@@ -235,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>
@@ -437,6 +442,11 @@ export default {
this.getList()
},
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
},
}
</script>
<style lang="scss" scoped>
+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"
@@ -5,7 +5,7 @@
<el-form :inline="true">
<!-- 中心编号 -->
<el-form-item :label="$t('trials:reviewAssign:readingTask:table:siteCode')">
<el-select v-model="searchData.SiteId" clearable filterable style="width:120px;">
<el-select v-model="searchData.TrialSiteId" clearable filterable style="width:120px;">
<el-option
v-for="(item,index) of siteOptions"
:key="index"
@@ -526,7 +526,7 @@ const searchDataDefault = () => {
Asc: true,
SortField: '',
TrialId: null,
SiteId: null,
TrialSiteId: null,
SubjectId: null,
SubjectCode: null,
IsUrgent: null,
@@ -598,7 +598,7 @@ export default {
},
mounted() {
if (this.$route.query.SiteId) {
this.searchData.SiteId = this.$route.query.SiteId
this.searchData.TrialSiteId = this.$route.query.SiteId
this.searchData.SubjectCode = this.$route.query.SubjectCode
this.searchData.TaskName = this.$route.query.TaskName
this.searchData.DoctorUserId = this.$route.query.DoctorUserId
@@ -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) {
@@ -11,7 +11,7 @@ import * as cornerstoneTools from '@cornerstonejs/tools';
import * as cornerstone from '@cornerstonejs/core';
import { init as csToolsInit } from '@cornerstonejs/tools';
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
cornerstone.Settings.getRuntimeSettings().set('useCursors', false);
window.cornerstone = cornerstone;
window.cornerstoneTools = cornerstoneTools;
export default async function initLibraries() {
@@ -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>
@@ -155,11 +155,7 @@
<el-option v-for="item of $d.TaskAllocationState" :key="'TaskAllocationState' + item.label" :value="item.value" :label="item.label" />
</el-select>
</el-form-item> -->
<!-- 申请原因 -->
<!-- <el-form-item style="margin-bottom:10px" :label="$t('trials:rereadTrack:table:applyReason')">
<el-input
@@ -630,7 +626,6 @@
@pagination="getList"
/>
<el-dialog
v-if="ConfirmReReadingVisible"
:title="$t('trials:rereadTrack:reject:title:reject')"
:visible.sync="ConfirmReReadingVisible"
width="600px"
@@ -645,6 +640,7 @@
max-height: 650px;
overflow-y: auto;
"
v-if="ConfirmReReadingVisible"
>
<el-form
ref="reasonForm"
@@ -670,7 +666,7 @@
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<div slot="footer" class="dialog-footer" v-if="ConfirmReReadingVisible">
<!-- 取消 -->
<el-button
:disabled="btnLoading"
@@ -1209,18 +1205,17 @@ export default {
this.loading = false
this.btnLoading = false
// /
this.$message.success(
`${
type === 1
? this.$t('trials:rereadTrack:message:msg3')
: this.$t('trials:rereadTrack:message:msg4')
}`
)
this.$refs['signForm'].btnLoading = false
let message =
type === 1
? this.$t('trials:rereadTrack:message:msg3')
: this.$t('trials:rereadTrack:message:msg4')
this.$message.success(message)
// this.$refs['signForm'].btnLoading = false
this.signVisible = false
this.getList()
this.ConfirmReReadingVisible = false
} catch (e) {
console.log(e)
this.loading = false
this.$refs['signForm'].btnLoading = false
this.btnLoading = false
@@ -1257,13 +1252,11 @@ export default {
this.getList()
} else {
// /
this.$message.success(
`${
type === 1
? this.$t('trials:rereadTrack:message:msg3')
: this.$t('trials:rereadTrack:message:msg4')
}`
)
let message =
type === 1
? this.$t('trials:rereadTrack:message:msg3')
: this.$t('trials:rereadTrack:message:msg4')
this.$message.success(message)
this.ReReadingOrBackVisible = false
this.signVisible = false
this.getList()
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,16 +121,16 @@
@click="activeCanvas(index)"
@mouseup="sliderMouseup($event, index)"
@mousemove="sliderMousemove($event, index)"
@mouseleave="sliderMouseleave($event, index)"
>
<div v-show="v.fileType === 'image/jpeg'" :ref="`canvas-${index}`" class="content">
<div v-show="imageType.includes(v.fileType)" :ref="`canvas-${index}`" class="content">
<div class="left-top-text">
<div
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,14 +263,18 @@ import {
imageLoader,
metaData,
getRenderingEngine,
eventTarget
eventTarget,
utilities as csUtils
// getEnabledElementByIds
} from '@cornerstonejs/core'
import * as cornerstoneTools from '@cornerstonejs/tools'
import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries'
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 {
@@ -233,17 +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() {
@@ -260,7 +324,21 @@ export default {
taskInfo: null,
activeTool: '',
readingTaskState: 2,
renderHistoryAnnotationTaskIds: []
renderHistoryAnnotationTaskIds: [],
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: {
@@ -332,9 +410,10 @@ 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)
console.log(cornerstoneTools)
},
beforeDestroy() {
window.removeEventListener('message', this.handleIframeMessage)
@@ -402,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}`
@@ -421,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 }]
})
@@ -437,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)
})
@@ -463,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)
}
})
},
@@ -491,10 +588,13 @@ export default {
if (!obj || Object.keys(obj).length === 0) return
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
if (i === -1) return
if (obj.studyId === this.viewportInfos[i].studyId && this.viewportInfos[i].fileType === 'image/jpeg' && obj.fileInfo.FileType === 'image/jpeg') {
if (obj.studyId === this.viewportInfos[i].studyId && this.imageType.includes(this.viewportInfos[i].fileType) && this.imageType.includes(obj.fileInfo.FileType)) {
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) {
@@ -523,8 +623,8 @@ export default {
this.viewportInfos[i].currentFileName = obj.fileInfo.FileName
this.viewportInfos[i].studyId = obj.studyId
this.viewportInfos[i].fileType = obj.fileInfo.FileType
if (obj.fileInfo.FileType === 'image/jpeg') {
const arr = obj.fileList.filter(i => i.FileType === obj.fileInfo.FileType)
if (this.imageType.includes(obj.fileInfo.FileType)) {
const arr = obj.fileList.filter(i => this.imageType.includes(i.FileType))
this.viewportInfos[i].fileList = arr
const fileIndex = this.viewportInfos[i].fileList.findIndex(i => i.Path === obj.fileInfo.Path)
this.viewportInfos[i].currentImageIdIndex = fileIndex
@@ -565,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) {
@@ -646,12 +751,16 @@ export default {
//
toggleFullScreen(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
if (i === -1 && this.viewportInfos[i].fileType !== 'image/jpeg') 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)
@@ -695,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 }]
})
@@ -710,6 +832,11 @@ export default {
toolGroup.setToolPassive(this.activeTool)
})
this.activeTool = ''
// const enabledElement = getEnabledElementByIds(
// `canvas-${this.activeCanvasIndex}`,
// renderingEngineId
// )
// cursors.setCursorForElement(enabledElement.viewport.element, 'default')
},
addAnnotationListeners() {
const debouncedCallback = this.debounce((evt) => {
@@ -734,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')
@@ -756,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,
@@ -782,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,
@@ -792,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() {
@@ -816,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
@@ -840,12 +1141,12 @@ export default {
},
sliderMouseup(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
if (i === -1 && this.viewportInfos[i].fileType !== 'image/jpeg') return
if (i === -1 && this.imageType.includes(this.viewportInfos[i].fileType)) return
this.viewportInfos[i].isMove = false
},
sliderMousemove(e, index) {
const i = this.viewportInfos.findIndex(i => i.index === index)
if (i === -1 && this.viewportInfos[i].fileType !== 'image/jpeg') return
if (i === -1 && this.imageType.includes(this.viewportInfos[i].fileType)) return
if (!this.viewportInfos[i].isMove) return
const delta = this.viewportInfos[i].oldB - (this.viewportInfos[i].oldM - e.clientY)
const boxHeight = this.$refs[`sliderBox-${index}`][0].clientHeight
@@ -855,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)
@@ -892,6 +1199,9 @@ export default {
//
viewCD(id) {
this.$emit('previewCD', id)
},
previewConfig() {
this.personalConfigDialog.visible = true
}
}
}
@@ -906,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;
@@ -965,7 +1281,6 @@ export default {
.cd-info {
color: #ddd;
font-size: 18px;
cursor: pointer;
}
.subject-info {
color:#f44336;
@@ -1030,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('|')"
@@ -136,23 +137,22 @@
/>
</el-select>
<el-input
v-if="question.DataSource !== 1"
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>
</el-input>
<el-input
v-if="question.DataSource === 1"
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;

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