Compare commits

...

552 Commits
v1.9.0 ... main

Author SHA1 Message Date
wangxiaoshuang 6674989249 自定义结构化录入的临床数据,配置工具存在问题
continuous-integration/drone/push Build is passing Details
2025-06-20 18:04:34 +08:00
wangxiaoshuang 06167d4ff5 项目邮件阅片标准修改
continuous-integration/drone/push Build is passing Details
2025-06-20 15:27:39 +08:00
wangxiaoshuang 2a1dc4d2dd 自定义结构化录入的临床数据,配置工具存在问题
continuous-integration/drone/push Build is running Details
2025-06-20 13:17:21 +08:00
wangxiaoshuang 3d6cd67493 字典配置修改为可查看
continuous-integration/drone/push Build is passing Details
2025-06-20 11:26:20 +08:00
wangxiaoshuang c448f4cda8 上传影像预览窗宽窗位问题
continuous-integration/drone/push Build is passing Details
2025-06-20 11:05:27 +08:00
wangxiaoshuang 155158f954 项目配置检查名称问题解决
continuous-integration/drone/push Build is passing Details
2025-06-20 09:44:08 +08:00
wangxiaoshuang 551620c3c3 1
continuous-integration/drone/push Build is passing Details
2025-06-19 17:44:31 +08:00
wangxiaoshuang 4540f39051 切换靶段时清空备注 2025-06-19 17:42:25 +08:00
wangxiaoshuang 848bf0c8b2 自定义报告单选显示问题修改
continuous-integration/drone/push Build is passing Details
2025-06-19 17:24:35 +08:00
wangxiaoshuang aa1f4dae9b IVUS和OCT表单修改,新增靶段
continuous-integration/drone/push Build is passing Details
2025-06-19 16:53:11 +08:00
wangxiaoshuang a41359111f 字典子项增加排序
continuous-integration/drone/push Build is passing Details
2025-06-19 13:39:12 +08:00
wangxiaoshuang 50ae94bf08 1
continuous-integration/drone/push Build is passing Details
2025-06-19 13:18:07 +08:00
wangxiaoshuang 19785bd266 邮件模板编辑阅片标准改为多选
continuous-integration/drone/push Build is passing Details
2025-06-19 13:13:12 +08:00
wangxiaoshuang cc5a4ed2df 邮件模板编辑样式修改
continuous-integration/drone/push Build is passing Details
2025-06-19 11:42:53 +08:00
wangxiaoshuang 5efcbae09a 邮件模板阅片标准字段更改 2025-06-19 11:40:46 +08:00
wangxiaoshuang 6f5d48cdcd 如果上传影像都是问题影像,此时会显示数量0/0
continuous-integration/drone/push Build is passing Details
2025-06-19 11:28:14 +08:00
wangxiaoshuang fead8b8c8f 导出文件格式问题
continuous-integration/drone/push Build is passing Details
2025-06-18 14:28:08 +08:00
wangxiaoshuang 6980cd275e Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-06-18 13:48:05 +08:00
wangxiaoshuang a14aefca2c 上传影像文件统计问题
continuous-integration/drone/push Build encountered an error Details
2025-06-18 13:33:39 +08:00
wangxiaoshuang 334882cc68 阅片下载压缩包名称修改 2025-06-18 13:30:36 +08:00
wangxiaoshuang de250ecbf5 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
# Conflicts:
#	src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
2025-06-18 09:56:39 +08:00
wangxiaoshuang d8315fbfff 阅片上传下载按钮添加
continuous-integration/drone/push Build encountered an error Details
2025-06-18 09:55:16 +08:00
wangxiaoshuang 1022fa2888 阅片顺序添加admin角色权限
continuous-integration/drone/push Build encountered an error Details
2025-06-17 16:49:15 +08:00
wangxiaoshuang a14451b82b 影像汇总导出表格
continuous-integration/drone/push Build is passing Details
2025-06-17 16:43:55 +08:00
wangxiaoshuang 24ff1772dd Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-06-16 17:24:31 +08:00
wangxiaoshuang 48633a1ed4 阅片顺序手动修改添加限制条件
continuous-integration/drone/push Build encountered an error Details
2025-06-16 17:24:14 +08:00
wangxiaoshuang 0634df6e33 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
# Conflicts:
#	src/views/trials/trials-panel/trial-summary/audit-record/index.vue
2025-06-16 16:06:54 +08:00
wangxiaoshuang 108d01f81c 阅片顺序默认排序、阅片中禁用
continuous-integration/drone/push Build encountered an error Details
2025-06-16 16:05:49 +08:00
caiyiling ae808679a0 1
continuous-integration/drone/push Build is passing Details
2025-06-13 18:02:55 +08:00
wangxiaoshuang 12e4128b7b 提交裁判阅片结果详情oldValue改为--
continuous-integration/drone/push Build encountered an error Details
2025-06-13 16:49:50 +08:00
caiyiling fbb23065e5 1
continuous-integration/drone/push Build is passing Details
2025-06-13 16:33:59 +08:00
caiyiling 0d85f138a5 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-13 16:07:17 +08:00
caiyiling f60d845725 自定义阅片更改 2025-06-13 16:06:54 +08:00
wangxiaoshuang f848e9a9dd Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
# Conflicts:
#	src/api/trials/reading.js
#	src/views/trials/trials-panel/trial-summary/audit-record/index.vue
2025-06-13 14:34:59 +08:00
wangxiaoshuang b512112d96 肿瘤学阅片查看屏蔽跳过按钮
continuous-integration/drone/push Build encountered an error Details
2025-06-13 14:33:55 +08:00
wangxiaoshuang a7251ce65c 阅片顺序
continuous-integration/drone/push Build encountered an error Details
2025-06-13 14:17:58 +08:00
wangxiaoshuang 19896b85e0 1
continuous-integration/drone/push Build is passing Details
2025-06-13 11:43:07 +08:00
wangxiaoshuang f94013103e Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-06-13 11:17:38 +08:00
wangxiaoshuang ccdfe9d83e 阅片排序 2025-06-13 11:17:28 +08:00
caiyiling 657010202c Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-13 10:44:35 +08:00
caiyiling 9c2c6191d2 播放工具更改 2025-06-13 10:44:12 +08:00
wangxiaoshuang 7e2ff6de1b 稽查图片不存在展示问题
continuous-integration/drone/push Build encountered an error Details
2025-06-12 16:23:44 +08:00
wangxiaoshuang c865608313 阅片顺序页面
continuous-integration/drone/push Build is passing Details
2025-06-12 16:19:08 +08:00
wangxiaoshuang 818a8add3d Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web 2025-06-12 16:18:49 +08:00
wangxiaoshuang 53343e37d6 稽查图片不存在展示问题 2025-06-12 16:18:45 +08:00
caiyiling a3e17bbefe Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is failing Details
2025-06-12 15:44:23 +08:00
caiyiling 19bb1eccd8 自定义阅片表单更改 2025-06-12 15:43:59 +08:00
wangxiaoshuang e60260f68d 培训记录查看页面中角色筛选项缺少ZYBS、ZYSS角色
continuous-integration/drone/push Build is pending Details
2025-06-12 11:02:37 +08:00
wangxiaoshuang 2b89163419 项目文档历史记录文件名称修改方式修改
continuous-integration/drone/push Build is passing Details
2025-06-11 16:53:22 +08:00
wangxiaoshuang 3489d34628 影像汇总导出影像、关键图
continuous-integration/drone/push Build is passing Details
2025-06-11 16:34:46 +08:00
wangxiaoshuang 613d434af9 影像汇总
continuous-integration/drone/push Build is passing Details
2025-06-10 18:02:37 +08:00
wangxiaoshuang 123f178673 稽查图片显示问题
continuous-integration/drone/push Build is passing Details
2025-06-10 15:26:34 +08:00
wangxiaoshuang e8e066ab80 稽查操作名查询字段变更
continuous-integration/drone/push Build is passing Details
2025-06-10 09:41:55 +08:00
wangxiaoshuang 4aa5acc401 1
continuous-integration/drone/push Build is passing Details
2025-06-09 16:56:29 +08:00
wangxiaoshuang fa4c00230f 项目文档历史记录修改
continuous-integration/drone/push Build is passing Details
2025-06-09 15:58:52 +08:00
wangxiaoshuang 6ea46c076b 检查部位、检查技术、检查名称已使用禁止取消、删除
continuous-integration/drone/push Build is passing Details
2025-06-09 11:18:09 +08:00
caiyiling dbffc2787d Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-06 17:25:59 +08:00
caiyiling f98ea18205 自定义标准阅片交互更改 2025-06-06 17:25:23 +08:00
wangxiaoshuang 00e53c4742 项目培训图片预览问题
continuous-integration/drone/push Build is passing Details
2025-06-06 16:58:38 +08:00
wangxiaoshuang 5de61dd125 项目培训发布状态默认值
continuous-integration/drone/push Build is passing Details
2025-06-06 16:28:07 +08:00
wangxiaoshuang ae8767c70f 配置中检查部位已在项目中使用禁止取消勾选和修改
continuous-integration/drone/push Build is passing Details
2025-06-06 14:34:42 +08:00
wangxiaoshuang 623a7b9858 1
continuous-integration/drone/push Build is passing Details
2025-06-06 14:26:45 +08:00
wangxiaoshuang ce2a0d9936 邮件管理批量编辑 2025-06-06 14:26:37 +08:00
wangxiaoshuang 18b0ec2042 pm重阅跟踪、spm重阅审批弹框列表高度修改
continuous-integration/drone/push Build is passing Details
2025-06-06 13:47:33 +08:00
caiyiling 8d5dfd0258 自定义阅片配置更改
continuous-integration/drone/push Build is passing Details
2025-06-06 11:15:31 +08:00
caiyiling 45f83322ec 1
continuous-integration/drone/push Build is passing Details
2025-06-05 18:32:22 +08:00
caiyiling 3d7ccafa76 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-05 18:03:50 +08:00
caiyiling f148c76a7f 自定义阅片更改 2025-06-05 18:03:32 +08:00
wangxiaoshuang 1ffd9e3863 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is failing Details
2025-06-05 16:59:56 +08:00
wangxiaoshuang 3bcf097c52 邮件管理编辑内容方式修改 2025-06-05 16:59:44 +08:00
caiyiling 1e4fd0083a 1
continuous-integration/drone/push Build is passing Details
2025-06-05 16:26:02 +08:00
caiyiling d504039d82 自定义标准配置更改
continuous-integration/drone/push Build is passing Details
2025-06-05 16:22:42 +08:00
caiyiling 0c4b3e5aed 表格问题配置更改
continuous-integration/drone/push Build is passing Details
2025-06-05 16:10:23 +08:00
caiyiling 262541ac08 1
continuous-integration/drone/push Build is passing Details
2025-06-05 16:03:06 +08:00
caiyiling dce3719c58 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is running Details
2025-06-05 16:00:49 +08:00
caiyiling d05a4437d4 自定义标准配置更改及自定义阅片更改 2025-06-05 16:00:12 +08:00
wangxiaoshuang 10f2953a94 如果不能下载影像,则检查也不需要能够选择
continuous-integration/drone/push Build is passing Details
2025-06-05 13:12:49 +08:00
wangxiaoshuang 7a6cded333 培训材料视频禁止下载
continuous-integration/drone/push Build is passing Details
2025-06-05 11:38:08 +08:00
wangxiaoshuang c1f10036b0 项目文档增加附件
continuous-integration/drone/push Build is passing Details
2025-06-04 17:15:45 +08:00
caiyiling 8e01f3af87 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-06-04 16:50:53 +08:00
caiyiling a66e15eb39 MRI-PDFF测量逻辑更改
continuous-integration/drone/push Build encountered an error Details
2025-06-04 16:25:48 +08:00
wangxiaoshuang 386901316d 1
continuous-integration/drone/push Build is passing Details
2025-06-04 15:58:30 +08:00
caiyiling 122f333c77 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-06-04 13:42:00 +08:00
caiyiling 164437ea70 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-04 13:37:46 +08:00
caiyiling 86a8e2faeb 测量工具配置文件更改 2025-06-04 13:37:12 +08:00
caiyiling 895e3a6bed MRI-PDFF更改
continuous-integration/drone/push Build encountered an error Details
2025-06-04 13:35:42 +08:00
wangxiaoshuang b5b67cc5e3 稽查搜索框内容接口获取
continuous-integration/drone/push Build is passing Details
2025-06-04 13:34:42 +08:00
caiyiling 9dddc0c012 MRI-PDFF测量逻辑更改
continuous-integration/drone/push Build encountered an error Details
2025-06-04 10:53:45 +08:00
caiyiling a965f08a1e MRI-PDFF标准更改
continuous-integration/drone/push Build encountered an error Details
2025-06-04 09:24:41 +08:00
wangxiaoshuang d667bb4e79 审批页面优化
continuous-integration/drone/push Build is passing Details
2025-06-03 18:01:04 +08:00
caiyiling c7e0fab789 非Dicom工具更改
continuous-integration/drone/push Build is passing Details
2025-06-03 16:14:28 +08:00
caiyiling 35b16876c9 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-06-03 14:27:27 +08:00
caiyiling 549b028809 非dicom更改 2025-06-03 14:27:09 +08:00
wangxiaoshuang 330b1cf644 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-06-03 13:54:34 +08:00
wangxiaoshuang b51a8e94de 稽查轨迹的记录的操作可以在在项目配置 2025-06-03 13:54:19 +08:00
caiyiling b85853aa5e 阅片结果导出配置更改
continuous-integration/drone/push Build is passing Details
2025-06-03 11:32:48 +08:00
wangxiaoshuang 5386dba134 稽查新增字段是否默认
continuous-integration/drone/push Build is passing Details
2025-05-30 09:27:30 +08:00
caiyiling 3f63c126ff 1
continuous-integration/drone/push Build is passing Details
2025-05-29 17:21:25 +08:00
caiyiling f1b816fd85 自定义阅片更改
continuous-integration/drone/push Build is passing Details
2025-05-29 17:04:00 +08:00
caiyiling 43a221de00 自定义阅片更改
continuous-integration/drone/push Build is passing Details
2025-05-29 14:49:53 +08:00
caiyiling 642c708c74 Merge remote-tracking branch 'origin/uat' into main
continuous-integration/drone/push Build is passing Details
2025-05-29 09:58:39 +08:00
caiyiling aa8831ce54 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is running Details
2025-05-29 09:57:35 +08:00
caiyiling d73970117d 自定义标准更改 2025-05-29 09:57:02 +08:00
wangxiaoshuang 9d462f69f6 人员管理中,当人员退出时,显示加入项目的时间
continuous-integration/drone/push Build is passing Details
2025-05-29 09:38:11 +08:00
caiyiling 9962b1a829 反色bug修复
continuous-integration/drone/push Build encountered an error Details
2025-05-28 18:46:53 +08:00
caiyiling 049128b90e 添加阅片完成支持添加临时标注(历史标注不允许更改)功能及阅片页面双击放大缺陷修复
continuous-integration/drone/push Build encountered an error Details
2025-05-28 15:44:38 +08:00
caiyiling d77c79acbd 自定义标准问题配置扩充影像标记属性
continuous-integration/drone/push Build is passing Details
2025-05-27 11:10:56 +08:00
caiyiling 1e300b4529 CDISC导出配置支持表格问题更改
continuous-integration/drone/push Build is passing Details
2025-05-27 09:06:04 +08:00
wangxiaoshuang 45e6a20988 Merge branch 'uat'
continuous-integration/drone/push Build encountered an error Details
# Conflicts:
#	src/utils/metaDataProvider.js
2025-05-26 12:30:44 +08:00
wangxiaoshuang 5141eb5cbd 发布配置修改
continuous-integration/drone/push Build is passing Details
2025-05-23 18:12:49 +08:00
wangxiaoshuang 073b06a76f 1
continuous-integration/drone/push Build is passing Details
2025-05-23 17:10:45 +08:00
wangxiaoshuang 20723e8d2c 1
continuous-integration/drone/push Build is passing Details
2025-05-23 16:25:30 +08:00
wangxiaoshuang fba00157a1 crc一致性核查回复弹窗添加取消按钮
continuous-integration/drone/push Build is passing Details
2025-05-23 16:06:12 +08:00
wangxiaoshuang f0e6708533 1
continuous-integration/drone/push Build is passing Details
2025-05-23 15:24:49 +08:00
wangxiaoshuang e770dc1078 1 2025-05-23 15:24:07 +08:00
wangxiaoshuang e15934d7ba iqc质控页面数据已退回禁用所有按钮
continuous-integration/drone/push Build is passing Details
2025-05-23 13:49:36 +08:00
wangxiaoshuang 4baf039d71 iqc下载非dicom文件夹名称问题
continuous-integration/drone/push Build is passing Details
2025-05-23 13:38:59 +08:00
wangxiaoshuang 5c4bc96a26 pm重传审批样式修改
continuous-integration/drone/push Build is passing Details
2025-05-23 13:27:51 +08:00
wangxiaoshuang 30f9e807b7 crc一致性核查逻辑变更
continuous-integration/drone/push Build is passing Details
2025-05-23 11:07:17 +08:00
wangxiaoshuang 269f9f9477 pm重传审批修改
continuous-integration/drone/push Build is passing Details
2025-05-23 10:11:52 +08:00
wangxiaoshuang 810c786512 1
continuous-integration/drone/push Build is passing Details
2025-05-22 18:04:29 +08:00
wangxiaoshuang e27705eb22 IRC国际化替换
continuous-integration/drone/push Build is passing Details
2025-05-22 17:49:43 +08:00
wangxiaoshuang 83bf082c43 crc一致性核查回复信息有误
continuous-integration/drone/push Build is passing Details
2025-05-22 16:52:50 +08:00
wangxiaoshuang 37f12b30cc 阅片跟踪影像退回添加退回原因
continuous-integration/drone/push Build is passing Details
2025-05-22 15:30:14 +08:00
wangxiaoshuang f045f68115 一致性核查回复修改
continuous-integration/drone/push Build is passing Details
2025-05-22 14:06:38 +08:00
wangxiaoshuang 64e67ad106 一致性核查回复修改
continuous-integration/drone/push Build is passing Details
2025-05-22 13:54:27 +08:00
wangxiaoshuang f2ee666083 重阅审批的弹框,国际化取值不正确修改
continuous-integration/drone/push Build is passing Details
2025-05-22 11:04:30 +08:00
caiyiling 8ece8915ff 高亮颜色更改
continuous-integration/drone/push Build is passing Details
2025-05-21 16:01:04 +08:00
caiyiling 8270841ca1 典型肝内病灶鼠标悬浮显示
continuous-integration/drone/push Build is passing Details
2025-05-21 15:21:33 +08:00
caiyiling e99c4527b9 阅片页面radio样式更改及病灶信息高亮更改
continuous-integration/drone/push Build is passing Details
2025-05-21 15:10:49 +08:00
caiyiling e295bff859 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-21 14:06:54 +08:00
caiyiling 7a53a75038 影像质量不正常时维护病灶默认状态 2025-05-21 14:06:06 +08:00
wangxiaoshuang d96822818c 1
continuous-integration/drone/push Build is passing Details
2025-05-21 14:02:23 +08:00
caiyiling 9e2255e324 阅片标准更改
continuous-integration/drone/push Build is passing Details
2025-05-21 10:37:12 +08:00
caiyiling dbdd18dcf6 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-21 09:49:22 +08:00
caiyiling 4ae2504278 阅片标准更改 2025-05-21 09:48:54 +08:00
wangxiaoshuang 6a0a5f4724 1
continuous-integration/drone/push Build is passing Details
2025-05-20 16:14:40 +08:00
wangxiaoshuang ee2e33405c 申请原因必填添加星号
continuous-integration/drone/push Build is passing Details
2025-05-20 11:07:41 +08:00
wangxiaoshuang 286865ba8f 影像质疑列表操作栏样式调整
continuous-integration/drone/push Build is passing Details
2025-05-20 09:43:02 +08:00
wangxiaoshuang 75a0f3a91a 影像退回添加申请原因、备注
continuous-integration/drone/push Build is passing Details
2025-05-19 17:53:54 +08:00
wangxiaoshuang 4fbcd8f8f5 项目培训新增默认字段IsPublish修改
continuous-integration/drone/push Build is passing Details
2025-05-19 16:05:36 +08:00
wangxiaoshuang 3c2edbffc5 1
continuous-integration/drone/push Build is passing Details
2025-05-19 15:39:04 +08:00
caiyiling 38fb56e09e Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-19 15:19:18 +08:00
caiyiling 105537c49e 非淋巴结靶病灶保存验证更改 2025-05-19 15:18:48 +08:00
wangxiaoshuang 355f6bcf86 培训文档管理预览附件
continuous-integration/drone/push Build is passing Details
2025-05-19 14:48:47 +08:00
wangxiaoshuang d6e9f9ddc2 培训文档管理预览附件
continuous-integration/drone/push Build is passing Details
2025-05-19 14:35:17 +08:00
wangxiaoshuang 16e005e664 test环境新增onlyoffice地址配置
continuous-integration/drone/push Build is passing Details
2025-05-19 14:27:00 +08:00
wangxiaoshuang b92b55a45a 培训课程管理问题
continuous-integration/drone/push Build is passing Details
2025-05-19 14:18:59 +08:00
wangxiaoshuang 0ed070ecd7 【临床数据】新增临床数据时,选择模板同时存在中文模板和英文模板,根据语言环境只显示一个 2025-05-19 14:18:45 +08:00
caiyiling 49940ab034 lugano更改
continuous-integration/drone/push Build is passing Details
2025-05-19 14:15:41 +08:00
caiyiling aca5b0c721 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-19 11:28:14 +08:00
caiyiling 8ea7540581 阅片报告页更改 2025-05-19 11:27:50 +08:00
wangxiaoshuang ec6a72e143 影像质控问题配置未勾选问题提交会报错
continuous-integration/drone/push Build is passing Details
2025-05-15 16:44:16 +08:00
wangxiaoshuang f512c1456a 阅片结果查看跳转修改
continuous-integration/drone/push Build is passing Details
2025-05-15 15:39:23 +08:00
wangxiaoshuang 4aa74b5420 阅片结果查看跳转修改
continuous-integration/drone/push Build is passing Details
2025-05-15 15:32:24 +08:00
wangxiaoshuang 50c37824aa ir已阅查看跳转修改
continuous-integration/drone/push Build is passing Details
2025-05-15 15:21:47 +08:00
wangxiaoshuang 358864c6c6 onlyoffice引入方式修改
continuous-integration/drone/push Build is passing Details
2025-05-15 11:08:33 +08:00
wangxiaoshuang e2db9c2d51 通用培训文档修改 2025-05-15 11:08:06 +08:00
wangxiaoshuang 78fbae1c1f 通用培训记录的相关文件添加/编辑弹框需要增加标题
continuous-integration/drone/push Build is passing Details
2025-05-15 09:46:25 +08:00
wangxiaoshuang 26c58f14fa 稽查轨迹关联操作页面的标题需要区分
continuous-integration/drone/push Build is passing Details
2025-05-14 16:14:05 +08:00
caiyiling f8774224b3 视角信息更改
continuous-integration/drone/push Build is passing Details
2025-05-14 16:05:43 +08:00
caiyiling bc41f4b4c1 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-14 15:48:29 +08:00
caiyiling 0280dfb959 lugano更改 2025-05-14 15:48:08 +08:00
wangxiaoshuang 49aa98af9f suv融合pt图像调整
continuous-integration/drone/push Build is passing Details
2025-05-14 15:06:52 +08:00
wangxiaoshuang 9ce6ff25b9 1
continuous-integration/drone/push Build is passing Details
2025-05-14 14:23:04 +08:00
wangxiaoshuang fca8c1c9bf suv问题修复
continuous-integration/drone/push Build is passing Details
2025-05-14 14:12:31 +08:00
wangxiaoshuang d0ebc3e791 融合影像数存在较大差距校验
continuous-integration/drone/push Build is passing Details
2025-05-14 13:39:45 +08:00
caiyiling ea4f23fb16 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-14 13:18:17 +08:00
caiyiling 01d01b1126 视口信息更改 2025-05-14 13:17:56 +08:00
wangxiaoshuang 040d9309b9 影像质控问题配置未勾选问题提交会报错
continuous-integration/drone/push Build is passing Details
2025-05-14 13:05:00 +08:00
caiyiling 1d6656a5b8 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-05-14 11:25:22 +08:00
caiyiling 76e328dcca 阅片页面视角信息更改 2025-05-14 11:24:49 +08:00
wangxiaoshuang 9852d99a4a crc上传文件大小统计修改
continuous-integration/drone/push Build is passing Details
2025-05-13 15:40:30 +08:00
wangxiaoshuang 39f7ba7181 标记缓存修改
continuous-integration/drone/push Build is passing Details
2025-05-13 15:24:32 +08:00
wangxiaoshuang fb68892cd4 基线二维上的病灶被渲染到了随访的融合上
continuous-integration/drone/push Build is passing Details
2025-05-12 17:22:05 +08:00
caiyiling 1e6ec0df27 1
continuous-integration/drone/push Build is passing Details
2025-05-12 17:02:08 +08:00
caiyiling 4ff6416edb 矩形工具更改
continuous-integration/drone/push Build is passing Details
2025-05-12 16:45:48 +08:00
wangxiaoshuang b2645f6423 从随访切到基线再切到随访,测量工具会被禁用,当前访视无法标记
continuous-integration/drone/push Build is passing Details
2025-05-12 15:38:21 +08:00
wangxiaoshuang 122c76d9b2 suv部分问题解决
continuous-integration/drone/push Build is passing Details
2025-05-12 14:58:07 +08:00
wangxiaoshuang 2d155612e5 1
continuous-integration/drone/push Build is passing Details
2025-05-12 13:31:41 +08:00
wangxiaoshuang 329d6b1ff6 【NM自定义】三维MIP视口影像显示异常
continuous-integration/drone/push Build is passing Details
2025-05-12 13:22:36 +08:00
wangxiaoshuang 7006cf849e suv融合部分问题修复
continuous-integration/drone/push Build is passing Details
2025-05-12 13:13:36 +08:00
wangxiaoshuang 71f3519769 suv融合部分问题修复
continuous-integration/drone/push Build is passing Details
2025-05-09 17:54:14 +08:00
wangxiaoshuang bbf2dd16e6 【NM自定义】pet视口放大缩小,标记显示的位置产生了偏移
continuous-integration/drone/push Build is passing Details
2025-05-09 15:58:27 +08:00
wangxiaoshuang 520d499a0b 1
continuous-integration/drone/push Build is passing Details
2025-05-09 14:26:23 +08:00
wangxiaoshuang 00cfb92087 suv融合
continuous-integration/drone/push Build is passing Details
2025-05-09 14:20:24 +08:00
wangxiaoshuang 8eb0b96c8e 重传审批操作添加权限判断
continuous-integration/drone/push Build is passing Details
2025-05-09 10:05:22 +08:00
wangxiaoshuang 24b9120a0a 部分问题解决
continuous-integration/drone/push Build is passing Details
2025-05-08 14:47:26 +08:00
wangxiaoshuang 02fcc4a2c1 suv融合
continuous-integration/drone/push Build is passing Details
2025-05-08 10:36:57 +08:00
wangxiaoshuang f53412acbf 复制、粘贴快捷方式不禁用默认事件
continuous-integration/drone/push Build is passing Details
2025-05-07 13:39:30 +08:00
caiyiling 3948596014 阅片页面更改
continuous-integration/drone/push Build is passing Details
2025-05-06 09:13:59 +08:00
wangxiaoshuang e899c0814e 部分问题修复
continuous-integration/drone/push Build is passing Details
2025-04-30 14:51:13 +08:00
wangxiaoshuang d12b4adb68 部分问题修复
continuous-integration/drone/push Build is passing Details
2025-04-30 13:43:23 +08:00
wangxiaoshuang 3551a521c8 suv融合
continuous-integration/drone/push Build is passing Details
2025-04-29 17:51:54 +08:00
caiyiling e80d439377 阅片更改
continuous-integration/drone/push Build is passing Details
2025-04-28 18:32:16 +08:00
caiyiling f499557c01 1
continuous-integration/drone/push Build is passing Details
2025-04-28 17:37:34 +08:00
caiyiling ecaca550ab 自定义阅片工具更改
continuous-integration/drone/push Build is passing Details
2025-04-28 17:32:40 +08:00
caiyiling b7d7b93c4a 获取病灶截图更改
continuous-integration/drone/push Build is passing Details
2025-04-28 17:07:15 +08:00
caiyiling 7bf92c60ea 阅片完成后禁用“更多”操作
continuous-integration/drone/push Build is passing Details
2025-04-28 16:38:49 +08:00
caiyiling 36a08d1055 自定义阅片报告页更改
continuous-integration/drone/push Build is passing Details
2025-04-28 16:31:45 +08:00
caiyiling 5ebf9032a5 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-28 16:12:02 +08:00
caiyiling 1896c58b50 自定义阅片bug修复 2025-04-28 16:11:08 +08:00
wangxiaoshuang 9168ef3ad7 1
continuous-integration/drone/push Build is passing Details
2025-04-28 15:55:27 +08:00
wangxiaoshuang 4ad299e243 suv融合
continuous-integration/drone/push Build is passing Details
2025-04-28 15:47:07 +08:00
caiyiling 5d337b0b26 自定义阅片bug修复
continuous-integration/drone/push Build is passing Details
2025-04-28 14:22:35 +08:00
caiyiling ca579f8731 自定义阅片更改
continuous-integration/drone/push Build is passing Details
2025-04-28 10:19:37 +08:00
caiyiling 92d41dff28 1
continuous-integration/drone/push Build is passing Details
2025-04-27 18:00:53 +08:00
wangxiaoshuang 8d6ae3a49f suv融合
continuous-integration/drone/push Build is passing Details
2025-04-27 17:04:54 +08:00
caiyiling 18f23d2bba 阅片交互更改
continuous-integration/drone/push Build is passing Details
2025-04-25 15:27:00 +08:00
caiyiling 0a428bf954 多帧图像保存病灶更改及关键帧渲染更改
continuous-integration/drone/push Build is passing Details
2025-04-25 15:02:13 +08:00
caiyiling a6b5d0b196 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-25 10:53:09 +08:00
caiyiling 8bf6d5f515 自定义标准工具添加 2025-04-25 10:52:37 +08:00
wangxiaoshuang 74f3852ecc Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-25 09:39:03 +08:00
wangxiaoshuang 9408ce12e2 稽查文档删除添加二次确定 2025-04-25 09:38:08 +08:00
wangxiaoshuang 06a2361ea0 【通用培训管理】新员工培训时限默认值设为14天 2025-04-25 09:37:45 +08:00
caiyiling e3313edefd mRecist标准bug修复
continuous-integration/drone/push Build is passing Details
2025-04-24 16:47:08 +08:00
caiyiling 2676ff4295 阅片单元配置更改
continuous-integration/drone/push Build is passing Details
2025-04-24 10:34:24 +08:00
caiyiling 41b3a98594 recist1.1标准bug修复
continuous-integration/drone/push Build is passing Details
2025-04-23 16:59:54 +08:00
caiyiling c2aba6c3fe 自定义阅片更改
continuous-integration/drone/push Build is passing Details
2025-04-23 15:14:35 +08:00
caiyiling 81a5d5af17 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-23 14:10:26 +08:00
caiyiling 23ac15f978 布局更改 2025-04-23 14:10:08 +08:00
wangxiaoshuang 1ec4c25472 稽查文档通用培训记录导出
continuous-integration/drone/push Build is running Details
2025-04-23 14:10:06 +08:00
wangxiaoshuang ac8710b26b 稽查文档右键下载问题
continuous-integration/drone/push Build is passing Details
2025-04-23 11:44:05 +08:00
caiyiling 1130b55677 视口滚动图像翻页更改
continuous-integration/drone/push Build is passing Details
2025-04-23 09:21:32 +08:00
caiyiling fb57dfe90c 新版本阅片添加iRecist标准
continuous-integration/drone/push Build is failing Details
2025-04-22 17:44:50 +08:00
caiyiling 2784958ccb 多帧对齐更改
continuous-integration/drone/push Build is passing Details
2025-04-22 15:00:35 +08:00
caiyiling d6a3bcba30 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-22 13:43:19 +08:00
caiyiling 4ff9a7c482 多帧渲染更改 2025-04-22 13:42:58 +08:00
wangxiaoshuang 33b3818a9e 测试
continuous-integration/drone/push Build is passing Details
2025-04-22 10:44:48 +08:00
wangxiaoshuang 38c31af137 已发布、已下线的培训文档默认不可多选
continuous-integration/drone/push Build is passing Details
2025-04-21 11:28:41 +08:00
wangxiaoshuang fb671defb5 1
continuous-integration/drone/push Build is passing Details
2025-04-21 11:09:55 +08:00
wangxiaoshuang a25aa2482f 通用培训材料发布、下线功能修改
continuous-integration/drone/push Build is passing Details
2025-04-21 10:57:32 +08:00
wangxiaoshuang 4249ccd9d6 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-21 09:47:31 +08:00
wangxiaoshuang 9a88930a04 通用培训创建默认设置为失效 2025-04-21 09:47:20 +08:00
caiyiling aea6a3f8c8 病灶对齐逻辑更改
continuous-integration/drone/push Build is passing Details
2025-04-18 17:02:52 +08:00
caiyiling c657bb8783 标注序列图标维护
continuous-integration/drone/push Build is passing Details
2025-04-18 16:46:27 +08:00
caiyiling b0ae3cbd27 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-18 16:01:28 +08:00
caiyiling 10487640cd 视图工具维护 2025-04-18 16:01:00 +08:00
wangxiaoshuang 83fa937537 通用培训文档新增发布功能
continuous-integration/drone/push Build is passing Details
2025-04-18 14:23:29 +08:00
wangxiaoshuang dd1fb94562 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-18 09:55:17 +08:00
wangxiaoshuang 116402f865 【账号登录日志】去除用户类型查询条件 2025-04-18 09:55:06 +08:00
caiyiling 76fe08ed23 重置视口时重置窗宽窗位
continuous-integration/drone/push Build is passing Details
2025-04-18 09:43:21 +08:00
caiyiling 993d97e205 测量时病灶默认状态维护
continuous-integration/drone/push Build is passing Details
2025-04-18 09:21:47 +08:00
caiyiling 11471525af 任务切换或者单个病灶保存时前端缓存当前状态不刷新ecrf
continuous-integration/drone/push Build is passing Details
2025-04-17 17:36:35 +08:00
caiyiling 600abc3ce1 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-17 16:02:57 +08:00
caiyiling 9609768e5e 全局阅片更改 2025-04-17 16:02:39 +08:00
wangxiaoshuang ce565e00ff Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-17 15:14:00 +08:00
wangxiaoshuang e49fe23396 通用培训问题修复 2025-04-17 15:13:56 +08:00
caiyiling 85463ad240 典型肝内病灶提示更改
continuous-integration/drone/push Build is passing Details
2025-04-17 14:59:19 +08:00
caiyiling fc228622e1 病灶保存更改
continuous-integration/drone/push Build is passing Details
2025-04-17 14:20:00 +08:00
caiyiling 8840ddc77a 病灶清除修复
continuous-integration/drone/push Build is passing Details
2025-04-17 11:40:34 +08:00
caiyiling 3b31132616 mRecist表单更改
continuous-integration/drone/push Build is passing Details
2025-04-17 10:22:28 +08:00
caiyiling c7df59e564 1
continuous-integration/drone/push Build is passing Details
2025-04-17 09:29:23 +08:00
caiyiling aeef8eaacf 清除病灶信息bug修复
continuous-integration/drone/push Build is passing Details
2025-04-17 09:07:46 +08:00
caiyiling b0c4cfd0bf 阅片页面矩形工具补充
continuous-integration/drone/push Build is passing Details
2025-04-16 17:26:48 +08:00
caiyiling 38c06595aa 病灶保存bug修复
continuous-integration/drone/push Build is passing Details
2025-04-16 17:10:15 +08:00
caiyiling a0c5c7d304 病灶验证更改
continuous-integration/drone/push Build is passing Details
2025-04-16 16:43:30 +08:00
caiyiling 2323cbdd27 病灶保存成功时关闭窗口
continuous-integration/drone/push Build is passing Details
2025-04-16 15:57:33 +08:00
caiyiling c2f3e02ef1 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is running Details
2025-04-16 15:55:44 +08:00
caiyiling b069c881f2 mRecist病灶验证更改 2025-04-16 15:55:13 +08:00
wangxiaoshuang faaaf8f28f 附件数量为0时不打开预览弹框
continuous-integration/drone/push Build is passing Details
2025-04-15 17:39:54 +08:00
wangxiaoshuang 1e5bd46a40 附件预览筛选是否下线
continuous-integration/drone/push Build is passing Details
2025-04-15 17:27:54 +08:00
wangxiaoshuang 7d2af46845 通用培训问题解决
continuous-integration/drone/push Build is passing Details
2025-04-15 16:29:56 +08:00
wangxiaoshuang e1c41d2327 通用培训文档优化:增加附件、培训时限
continuous-integration/drone/push Build is passing Details
2025-04-15 15:49:22 +08:00
wangxiaoshuang d4ae366fa6 非dicom上传去除限制
continuous-integration/drone/push Build is passing Details
2025-04-15 11:13:52 +08:00
wangxiaoshuang 26963b0f94 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-15 10:01:10 +08:00
wangxiaoshuang c391e3e2e7 通用培训新增附件 2025-04-15 10:00:59 +08:00
caiyiling 23feb84e30 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-14 16:46:00 +08:00
caiyiling d5ae075aa8 多帧图像渲染更改 2025-04-14 16:45:40 +08:00
wangxiaoshuang b22374db9e Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-14 14:04:37 +08:00
wangxiaoshuang ba17d51f72 文档模板需要区分Elevate和Extensive的需要。 2025-04-14 14:04:28 +08:00
caiyiling 0f9963d939 箭头工具更改
continuous-integration/drone/push Build is passing Details
2025-04-14 13:41:42 +08:00
caiyiling ca0d406e45 recist标准更改
continuous-integration/drone/push Build is passing Details
2025-04-14 13:11:00 +08:00
caiyiling 8e0ad5ca9d mRecist标准更改
continuous-integration/drone/push Build is passing Details
2025-04-14 11:39:53 +08:00
DESKTOP-775TN7O\wxs e0321bae72 影像预览问题解决
continuous-integration/drone/push Build encountered an error Details
2025-04-12 12:04:20 +08:00
wangxiaoshuang 10c1fb0bbc 重传审批添加默认查询条件
continuous-integration/drone/push Build is passing Details
2025-04-11 15:42:24 +08:00
wangxiaoshuang 3ab9b48842 工作台增加通用培训
continuous-integration/drone/push Build is passing Details
2025-04-11 15:17:05 +08:00
wangxiaoshuang 58a590bbb7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-10 17:46:47 +08:00
wangxiaoshuang b331b43b28 表格双击、授权按钮区分 2025-04-10 17:46:35 +08:00
caiyiling 162b649c3c Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-10 17:12:06 +08:00
caiyiling fcc5398bcb 阅片更改 2025-04-10 17:11:47 +08:00
wangxiaoshuang 9df1444e3d 版本记录删除与下载问题
continuous-integration/drone/push Build is passing Details
2025-04-10 16:23:45 +08:00
wangxiaoshuang 0f944343b3 历史版本打开有误
continuous-integration/drone/push Build is passing Details
2025-04-10 15:46:14 +08:00
wangxiaoshuang adeecf0b07 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-04-10 15:41:23 +08:00
wangxiaoshuang 1965abc9fd 设置忽略异地登录 2025-04-10 15:41:13 +08:00
caiyiling 1c19301f28 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-10 15:26:31 +08:00
caiyiling 42711dadb5 dicom阅片更改 2025-04-10 15:26:11 +08:00
wangxiaoshuang d9d2a2169e 表格双击、展开行事件区分
continuous-integration/drone/push Build is passing Details
2025-04-10 14:53:16 +08:00
wangxiaoshuang 9775ef24c8 1
continuous-integration/drone/push Build is failing Details
2025-04-10 14:42:10 +08:00
wangxiaoshuang 9af3cd4280 稽查文档管理问题修复
continuous-integration/drone/push Build is passing Details
2025-04-10 14:32:21 +08:00
wangxiaoshuang ab058d6659 稽查文档排序、新增文件夹更换接口
continuous-integration/drone/push Build is passing Details
2025-04-10 13:27:10 +08:00
wangxiaoshuang 0d446746e6 稽查文档管理问题修复
continuous-integration/drone/push Build is passing Details
2025-04-10 10:29:25 +08:00
wangxiaoshuang aaa366934b 影像退回
continuous-integration/drone/push Build is passing Details
2025-04-10 09:56:02 +08:00
wangxiaoshuang 7614f7a327 1
continuous-integration/drone/push Build is passing Details
2025-04-09 15:59:36 +08:00
wangxiaoshuang 0035ac1266 邮件管理中子页的操作列中文显示为英文,英文环境下按钮位置需要调整
continuous-integration/drone/push Build is passing Details
2025-04-09 13:56:49 +08:00
wangxiaoshuang 298d335a03 【忘记密码】点击上一步无法退回到上一个页面
continuous-integration/drone/push Build is passing Details
2025-04-09 13:50:21 +08:00
wangxiaoshuang 1bddd30709 账户日志的操作类型支持多选
continuous-integration/drone/push Build is passing Details
2025-04-09 13:43:47 +08:00
wangxiaoshuang 1d6ebe6388 项目切换时,需要根据项目状态过滤项目
continuous-integration/drone/push Build is passing Details
2025-04-09 13:37:39 +08:00
wangxiaoshuang 236a565250 工作台稽查文档
continuous-integration/drone/push Build is passing Details
2025-04-09 10:05:30 +08:00
wangxiaoshuang 318954b360 稽查文档管理新增文件夹
continuous-integration/drone/push Build is passing Details
2025-04-08 17:28:40 +08:00
wangxiaoshuang 91d31b4226 稽查文档预览
continuous-integration/drone/push Build is passing Details
2025-04-08 16:17:54 +08:00
wangxiaoshuang 1fb76ca72d 稽查文档预览
continuous-integration/drone/push Build is passing Details
2025-04-08 15:09:04 +08:00
wangxiaoshuang b76d157fca 稽查文档管理
continuous-integration/drone/push Build is passing Details
2025-04-07 18:00:10 +08:00
wangxiaoshuang fa71af24ad 1
continuous-integration/drone/push Build is passing Details
2025-04-07 10:12:32 +08:00
wangxiaoshuang a9edab9227 稽查文档管理
continuous-integration/drone/push Build is failing Details
2025-04-03 17:35:25 +08:00
wangxiaoshuang 1e720e399d 确认收入项,修改选项后,其他文件也改了
continuous-integration/drone/push Build encountered an error Details
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 31c9db368c 稽查文档管理
continuous-integration/drone/push Build is failing Details
2025-04-03 10:28:59 +08:00
wangxiaoshuang 866dc923c7 中心查询条件修改trialSiteId
continuous-integration/drone/push Build is failing Details
2025-04-03 09:46:21 +08:00
wangxiaoshuang a6b958ce4e dicom文件maxValue tag有问题 2025-04-03 09:45:50 +08:00
wangxiaoshuang 662cc93d85 稽查文档管理
continuous-integration/drone/push Build is failing Details
2025-04-01 17:59:24 +08:00
caiyiling e3ad114207 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-04-01 16:48:50 +08:00
caiyiling 0960b480a6 阅片页面更改 2025-04-01 16:48:04 +08:00
wangxiaoshuang 9a4eb1b210 工作台稽查文档
continuous-integration/drone/push Build is passing Details
2025-03-28 18:01:45 +08:00
wangxiaoshuang 0567534367 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-03-27 13:31:59 +08:00
wangxiaoshuang 481a436169 项目文档确认收入项问题解决 2025-03-27 13:31:54 +08:00
caiyiling 4188c0110f 非dicom阅片受试者内随机初始化图像逻辑更改
continuous-integration/drone/push Build is passing Details
2025-03-26 15:23:29 +08:00
wangxiaoshuang 01206716ab 1
continuous-integration/drone/push Build is passing Details
2025-03-24 16:56:27 +08:00
wangxiaoshuang 7fcbd7f983 生产环境配置修改
continuous-integration/drone/push Build encountered an error Details
2025-03-24 13:59:21 +08:00
wangxiaoshuang 779badb041 项目文档系统数据中英文转换
continuous-integration/drone/push Build is passing Details
2025-03-24 09:31:49 +08:00
caiyiling ef5e5527fd 标注更改及检查名称更改
continuous-integration/drone/push Build is passing Details
2025-03-21 16:29:47 +08:00
caiyiling 52ac12d6b6 阅片页面显示检查名称
continuous-integration/drone/push Build is passing Details
2025-03-21 15:36:23 +08:00
caiyiling 272c28a988 自定义阅片更改及非dicom阅片添加个性化配置
continuous-integration/drone/push Build is passing Details
2025-03-21 15:03:21 +08:00
caiyiling 6b10d07e2a 自定义阅片预览paf更改
continuous-integration/drone/push Build is passing Details
2025-03-21 14:03:53 +08:00
caiyiling 032e710890 阅片工具及报告页查看pdf更改
continuous-integration/drone/push Build is passing Details
2025-03-21 13:09:36 +08:00
caiyiling 032150904e 非dicom阅片更改
continuous-integration/drone/push Build is passing Details
2025-03-20 19:23:20 +08:00
wangxiaoshuang d91161a139 网速监控改为三位小数
continuous-integration/drone/push Build is passing Details
2025-03-19 15:53:41 +08:00
wangxiaoshuang bba2237337 文件大小改为保留3位小数
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
2025-03-18 17:55:22 +08:00
caiyiling d753fbc2ab 非dicom阅片测量工具更改
continuous-integration/drone/push Build is passing Details
2025-03-18 16:53:03 +08:00
caiyiling 5678e3302b 国际化补充
continuous-integration/drone/push Build is passing Details
2025-03-18 15:34:12 +08:00
caiyiling c25cb097ab 1
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
2025-03-18 15:18:26 +08:00
wangxiaoshuang cfbe3b4839 项目文档培训记录培训人数校验修改
continuous-integration/drone/push Build is running Details
2025-03-18 15:16:31 +08:00
wangxiaoshuang 81bef8abe0 项目文档培训记录培训人数添加校验
continuous-integration/drone/push Build is passing Details
2025-03-18 14:15:31 +08:00
wangxiaoshuang 84b1263340 浏览器页签标题修改
continuous-integration/drone/push Build is passing Details
2025-03-18 13:57:07 +08:00
wangxiaoshuang 4016e71c37 项目文档阅片人问题修复
continuous-integration/drone/push Build is passing Details
2025-03-18 13:51:25 +08:00
wangxiaoshuang 3b0afd3913 1
continuous-integration/drone/push Build is passing Details
2025-03-18 13:45:13 +08:00
wangxiaoshuang 3672892451 项目文档阅片人问题修复
continuous-integration/drone/push Build is passing Details
2025-03-18 09:54:33 +08:00
wangxiaoshuang c46ca18a42 项目文档菜单与列表是否适用字段联动
continuous-integration/drone/push Build is passing Details
2025-03-17 16:38:14 +08:00
wangxiaoshuang 0e0b5c2c4c 项目文档同意入项记录上传方式修改
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
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 Details
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 Details
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 Details
2025-03-17 09:29:56 +08:00
wangxiaoshuang a060c1745d 项目文档资质材料
continuous-integration/drone/push Build is passing Details
2025-03-14 17:09:38 +08:00
wangxiaoshuang 1a4bfe64f9 项目文档上传文件路径更改
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
2025-03-14 10:25:35 +08:00
wangxiaoshuang 08cdcffd82 项目文档申报方同意入项记录
continuous-integration/drone/push Build is passing Details
2025-03-13 17:10:42 +08:00
wangxiaoshuang a5f16c866d 检查名称配置更改
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
2025-03-13 13:23:56 +08:00
wangxiaoshuang c4a498d953 检查被IQC标记删除:在crc查看时,该行记录增加删除线
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
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 Details
2025-03-12 16:11:16 +08:00
caiyiling cf39a84370 全局和裁判阅片签名更改
continuous-integration/drone/push Build is passing Details
2025-03-12 15:42:56 +08:00
caiyiling aae2d6a1c5 非dicom全局和裁判阅片更改
continuous-integration/drone/push Build is passing Details
2025-03-12 15:18:23 +08:00
caiyiling 10f4bf7480 pdf文件替换
continuous-integration/drone/push Build is passing Details
2025-03-12 14:56:17 +08:00
caiyiling 57f0938efc 非dicom文件交互更改
continuous-integration/drone/push Build is passing Details
2025-03-12 14:50:55 +08:00
caiyiling 615580331b 后台管理页面调整
continuous-integration/drone/push Build is passing Details
2025-03-12 14:42:05 +08:00
caiyiling 4b4058b0da 文件渲染视口样式更改
continuous-integration/drone/push Build is passing Details
2025-03-12 13:16:47 +08:00
caiyiling f77820df79 临床数据查看更改
continuous-integration/drone/push Build is running Details
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 Details
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 Details
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 Details
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 Details
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 Details
2025-03-12 10:46:38 +08:00
caiyiling 0d9a77f4a5 文件管理模块列宽调整
continuous-integration/drone/push Build is passing Details
2025-03-12 10:24:25 +08:00
caiyiling 7f3da436c4 后台管理页面样式调整
continuous-integration/drone/push Build is passing Details
2025-03-12 10:21:40 +08:00
caiyiling 9e1cd5a099 配置文件更改
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
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 Details
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 Details
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 Details
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 Details
2025-03-11 15:05:31 +08:00
wangxiaoshuang f73eabed03 培训记录删除文件后授权状态改为否、禁用下载按钮
continuous-integration/drone/push Build is passing Details
2025-03-11 14:41:34 +08:00
wangxiaoshuang e99c77fb0d 培训记录上传单个文件问题修复
continuous-integration/drone/push Build is running Details
2025-03-11 14:39:36 +08:00
wangxiaoshuang ec37ca2d3e 一般文件记录删除文件后授权状态改为否、禁用下载按钮
continuous-integration/drone/push Build is passing Details
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 Details
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 Details
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 Details
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 Details
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 Details
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 Details
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 Details
2025-03-11 11:41:49 +08:00
wangxiaoshuang 49b723ab01 上传同名文件时进度条出错 2025-03-11 11:41:30 +08:00
caiyiling 0de49faed1 国际化补充
continuous-integration/drone/push Build is passing Details
2025-03-11 10:59:22 +08:00
caiyiling 7f85302c1b 国际化补充
continuous-integration/drone/push Build is passing Details
2025-03-11 10:42:34 +08:00
caiyiling 4305f2536c institutions模块国际化更改
continuous-integration/drone/push Build is passing Details
2025-03-11 10:30:07 +08:00
caiyiling 55783de27f Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-10 17:59:25 +08:00
caiyiling 465ea59906 国际化更改 2025-03-10 17:59:10 +08:00
wangxiaoshuang 81fab97ee4 项目文档部分字段去除排序
continuous-integration/drone/push Build is passing Details
2025-03-10 17:33:38 +08:00
wangxiaoshuang 2c93ba2882 国际化修改
continuous-integration/drone/push Build is running Details
2025-03-10 17:31:42 +08:00
wangxiaoshuang f3a237b0bf 1
continuous-integration/drone/push Build is passing Details
2025-03-10 17:08:43 +08:00
caiyiling c0588661ce Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-10 16:11:22 +08:00
caiyiling 381acf8d76 ecrf表单中分类问题bug修复 2025-03-10 16:10:41 +08:00
wangxiaoshuang e6715a429b 项目文档阅片人简历、阅片人培训记录、阅片人阅片记录、阅片人医学审核记录
continuous-integration/drone/push Build is passing Details
2025-03-10 15:24:11 +08:00
caiyiling 33ac08f4e4 非dicom阅片更改
continuous-integration/drone/push Build is passing Details
2025-03-10 15:20:02 +08:00
caiyiling d117bac7f6 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-10 15:09:37 +08:00
caiyiling 7051312855 国际化更改 2025-03-10 15:09:18 +08:00
wangxiaoshuang ff5a868377 项目文档部分问题修复
continuous-integration/drone/push Build is passing Details
2025-03-10 11:03:19 +08:00
wangxiaoshuang ea44f97985 非dicom列表改变状态时列表不重置
continuous-integration/drone/push Build is passing Details
2025-03-07 16:04:34 +08:00
wangxiaoshuang 156411fea3 非dicom列表改变状态时列表不重置
continuous-integration/drone/push Build is passing Details
2025-03-07 15:51:59 +08:00
wangxiaoshuang 822c2dc955 预览按钮位置交换
continuous-integration/drone/push Build is passing Details
2025-03-07 15:26:49 +08:00
wangxiaoshuang d729c4d34e 阅片期操作按钮样式问题
continuous-integration/drone/push Build is passing Details
2025-03-07 15:00:46 +08:00
caiyiling a887e686a8 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-07 14:25:09 +08:00
caiyiling 21cb32f1a9 自定义阅片数值问题渲染bug修复 2025-03-07 14:24:32 +08:00
wangxiaoshuang c74b482f0d 非dicom预览样式调整
continuous-integration/drone/push Build is passing Details
2025-03-07 14:13:57 +08:00
wangxiaoshuang 1af302961b 非dicom预览样式调整
continuous-integration/drone/push Build is running Details
2025-03-07 14:11:53 +08:00
wangxiaoshuang e83ac6714d 非dicom列表获取参数iReading默认为false
continuous-integration/drone/push Build is passing Details
2025-03-07 13:37:22 +08:00
wangxiaoshuang fc98aa0312 1
continuous-integration/drone/push Build is running Details
2025-03-07 13:34:36 +08:00
wangxiaoshuang 278c051f51 质控非dicom添加预览阅片影像功能
continuous-integration/drone/push Build is passing Details
2025-03-07 12:23:40 +08:00
wangxiaoshuang 5b8716f9ae 质控删除后数据不显示
continuous-integration/drone/push Build is passing Details
2025-03-07 11:02:30 +08:00
wangxiaoshuang cfef89c703 根据角色权限表核对开放页面以及功能
continuous-integration/drone/push Build is passing Details
2025-03-06 15:37:13 +08:00
caiyiling bf33f9d589 中心调研表更改
continuous-integration/drone/push Build is passing Details
2025-03-06 15:15:09 +08:00
caiyiling d74da23d41 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-06 15:10:50 +08:00
caiyiling cd630a70fb 阅片布局调整及中心调研更改 2025-03-06 15:10:11 +08:00
wangxiaoshuang 0b688bc33f PM在阅片期上传临床数据页面调整
continuous-integration/drone/push Build is passing Details
2025-03-06 14:56:28 +08:00
wangxiaoshuang a602be255b 项目文档部分问题修复
continuous-integration/drone/push Build is passing Details
2025-03-06 14:39:51 +08:00
wangxiaoshuang fb7891a2af 项目文档部分问题解决
continuous-integration/drone/push Build is passing Details
2025-03-06 13:20:47 +08:00
wangxiaoshuang 620f0d92ca 追溯角色可查看详情 2025-03-06 13:13:43 +08:00
wangxiaoshuang 8f43c697c0 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-03-06 13:05:40 +08:00
wangxiaoshuang 55769e906d 项目文档菜单增加排序字段 2025-03-06 11:41:17 +08:00
caiyiling 4ad67e5501 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-06 11:02:41 +08:00
caiyiling 1265cef6f9 系统标准阅片bug修复及非dicom阅片更改 2025-03-06 11:01:46 +08:00
wangxiaoshuang 86f5e2c782 非DICOM影像质控时,可以设置影像为删除、不阅片
continuous-integration/drone/push Build is passing Details
2025-03-05 16:14:29 +08:00
wangxiaoshuang 5450188a6e DICOM影像上传时缩略图的生成与存储
continuous-integration/drone/push Build is passing Details
2025-03-05 14:52:27 +08:00
wangxiaoshuang c8601f6f8f 文件模板
continuous-integration/drone/push Build is passing Details
2025-03-05 14:34:07 +08:00
wangxiaoshuang 299481a124 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-03-05 13:32:23 +08:00
wangxiaoshuang 5ca123e90b 培训记录
continuous-integration/drone/push Build is running Details
2025-03-05 13:32:00 +08:00
wangxiaoshuang af452bb04e 排序改为升序
continuous-integration/drone/push Build encountered an error Details
2025-03-05 13:12:55 +08:00
wangxiaoshuang bc34ed5c25 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-03-05 10:58:20 +08:00
wangxiaoshuang 1ef1d4f303 质控dicom检查信息添加更新时间和上传时间
continuous-integration/drone/push Build encountered an error Details
2025-03-05 10:50:47 +08:00
wangxiaoshuang fd67edcb0e dicom列表时间顺序调换
continuous-integration/drone/push Build encountered an error Details
2025-03-05 10:14:06 +08:00
wangxiaoshuang ecebeb2271 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
# Conflicts:
#	src/views/trials/trials-panel/visit/crc-upload/components/studyInfo.vue
#	src/views/trials/trials-panel/visit/crc-upload/components/uploadDicomFiles2.vue
2025-03-05 10:12:21 +08:00
wangxiaoshuang ba26476c52 pdf预览默认缩放改为100%
continuous-integration/drone/push Build encountered an error Details
2025-03-05 09:56:51 +08:00
wangxiaoshuang 821475b7d6 影像检查排序、字符集问题
continuous-integration/drone/push Build encountered an error Details
2025-03-05 09:51:33 +08:00
wangxiaoshuang a0594cab96 培训记录
continuous-integration/drone/push Build is passing Details
2025-03-05 09:26:40 +08:00
wangxiaoshuang bcde358584 影像检查排序、字符集问题
continuous-integration/drone/push Build is passing Details
2025-03-04 16:16:04 +08:00
caiyiling 067162e1d7 自定义标准更改
continuous-integration/drone/push Build is passing Details
2025-03-04 11:48:00 +08:00
caiyiling b5b5830b1f Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-04 10:57:19 +08:00
caiyiling fb1d87e84b 非dicom阅片更改 2025-03-04 10:56:55 +08:00
wangxiaoshuang 6b42b4e88c 一般文件记录
continuous-integration/drone/push Build is passing Details
2025-03-03 17:54:07 +08:00
caiyiling 2516be481d Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-03-03 13:47:21 +08:00
caiyiling 3aa66af253 非dicom阅片更改 2025-03-03 13:46:57 +08:00
wangxiaoshuang fa339dcdb0 项目文档报告/文档功能实现
continuous-integration/drone/push Build is passing Details
2025-02-28 17:55:10 +08:00
wangxiaoshuang 541e309d1d 用户追溯添加跳转至项目详情
continuous-integration/drone/push Build is passing Details
2025-02-28 11:18:19 +08:00
wangxiaoshuang 949ec6d2d6 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-02-28 11:02:37 +08:00
wangxiaoshuang 83b6c9f2cc 1
continuous-integration/drone/push Build encountered an error Details
2025-02-28 10:24:09 +08:00
wangxiaoshuang 996b691ef4 访视中预览,dicom检查没有显示检查名称 2025-02-28 10:21:52 +08:00
wangxiaoshuang 8bfaf7241a 检查名称问题修复
continuous-integration/drone/push Build encountered an error Details
2025-02-28 09:58:07 +08:00
wangxiaoshuang 35bff089b7 非dicom预览显示顺序问题
continuous-integration/drone/push Build encountered an error Details
2025-02-27 18:01:38 +08:00
wangxiaoshuang 6b1f8c26b2 受试者第二编号也需要隐藏
continuous-integration/drone/push Build encountered an error Details
2025-02-27 17:28:53 +08:00
wangxiaoshuang 5bffb48b99 修改配置应用到影像上传以及影像质控
continuous-integration/drone/push Build encountered an error Details
2025-02-27 16:32:58 +08:00
wangxiaoshuang 858a650986 项目配置修改 2025-02-27 15:13:56 +08:00
wangxiaoshuang 6b331ab6f6 项目文档
continuous-integration/drone/push Build is passing Details
2025-02-27 10:34:06 +08:00
wangxiaoshuang 00a7e8e609 部分问题修复 2025-02-27 10:33:57 +08:00
wangxiaoshuang c686850292 锁定弹窗支持邮箱校验
continuous-integration/drone/push Build is passing Details
2025-02-26 11:43:12 +08:00
wangxiaoshuang 887bb2534b Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2025-02-26 09:24:49 +08:00
wangxiaoshuang 3192ec7516 用户编辑保存按钮国际化 2025-02-26 09:24:42 +08:00
caiyiling 5f960348ed 1
continuous-integration/drone/push Build is passing Details
2025-02-25 17:55:17 +08:00
caiyiling d2757c6f9b Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-02-25 17:35:41 +08:00
caiyiling 734d6dc1a5 非dicom图像阅片更改 2025-02-25 17:35:02 +08:00
wangxiaoshuang be95951f40 用户来源问题修复
continuous-integration/drone/push Build is passing Details
2025-02-25 16:58:26 +08:00
wangxiaoshuang f4af0fc157 管理端用户列表角色过滤
continuous-integration/drone/push Build is passing Details
2025-02-25 11:31:56 +08:00
wangxiaoshuang 2090866521 管理端添加账号追溯页面 2025-02-25 11:31:32 +08:00
wangxiaoshuang d61131ed61 文件记录删除添加权限
continuous-integration/drone/push Build is passing Details
2025-02-25 09:52:36 +08:00
wangxiaoshuang 20aee53a3f 管理端添加文件记录列表
continuous-integration/drone/push Build is passing Details
2025-02-24 15:36:58 +08:00
wangxiaoshuang 05c75c32cf 角色与用户问题修复 2025-02-24 15:35:33 +08:00
wangxiaoshuang 2575e27d22 角色添加启用、停用功能
continuous-integration/drone/push Build is passing Details
2025-02-24 14:20:31 +08:00
wangxiaoshuang e7dcdb33c4 上传影像缩略图去除中心目录
continuous-integration/drone/push Build is passing Details
2025-02-24 09:04:59 +08:00
caiyiling d4c1b75423 1
continuous-integration/drone/push Build is passing Details
2025-02-21 17:05:36 +08:00
caiyiling d1159a09b4 图像窗口添加切换访视功能
continuous-integration/drone/push Build is running Details
2025-02-21 17:04:18 +08:00
caiyiling d69d8802cd Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is failing Details
2025-02-21 16:13:45 +08:00
caiyiling 6223eac81a 阅片页面图像预览更改 2025-02-21 16:13:17 +08:00
wangxiaoshuang b453eede31 打包配置修改,pdf预览文件
continuous-integration/drone/push Build is passing Details
2025-02-20 11:49:06 +08:00
wangxiaoshuang e5330765af 重阅审批页面查询条件中心初始化修改
continuous-integration/drone/push Build is passing Details
2025-02-20 10:07:29 +08:00
wangxiaoshuang 493b155678 国际化查询框换行问题
continuous-integration/drone/push Build is passing Details
2025-02-20 09:40:58 +08:00
wangxiaoshuang a2b2fd65af 国际化修改
continuous-integration/drone/push Build is passing Details
2025-02-19 11:25:57 +08:00
caiyiling 551cdf0ed3 工作台跳转中心调研异常bug修复
continuous-integration/drone/push Build is passing Details
2025-02-18 17:22:21 +08:00
caiyiling cadb3e8f7a 配置及样式更改
continuous-integration/drone/push Build is running Details
2025-02-18 17:15:09 +08:00
caiyiling 4da35daa3c cornerstone3D库升级及其他文件调整
continuous-integration/drone/push Build is failing Details
2025-02-18 15:09:25 +08:00
caiyiling 0f50ff6ded Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-02-17 17:18:04 +08:00
caiyiling 2f371f0435 1 2025-02-17 17:17:40 +08:00
wangxiaoshuang 245d4edca7 影像上传列表数据采集显示临床数据
continuous-integration/drone/push Build is passing Details
2025-02-17 14:56:11 +08:00
wangxiaoshuang 42d1c713bd 阅片人简历邮箱更改,admin禁用
continuous-integration/drone/push Build is passing Details
2025-02-17 13:35:47 +08:00
caiyiling 65b81fc633 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-02-17 10:15:49 +08:00
caiyiling 3a1d4ee15d 阅片任务中反馈状态修复 2025-02-17 10:15:19 +08:00
wangxiaoshuang c0eab7e896 Merge branch 'uat'
continuous-integration/drone/push Build is passing Details
2025-02-17 09:46:49 +08:00
wangxiaoshuang 4ba4d7cf00 登录日志详情添加账号状态
continuous-integration/drone/push Build encountered an error Details
2025-02-14 18:08:24 +08:00
caiyiling bfe9817544 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-02-14 17:42:54 +08:00
caiyiling f5fd1252c9 登录日志参数更改
continuous-integration/drone/push Build encountered an error Details
2025-02-14 17:41:15 +08:00
caiyiling 596ea8f658 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-02-14 17:26:58 +08:00
caiyiling b24548dd8b 登录日志查询条件更改
continuous-integration/drone/push Build encountered an error Details
2025-02-14 17:25:30 +08:00
caiyiling 4a479258f2 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-02-14 17:06:14 +08:00
caiyiling 29d0cc7653 登录日志个更改
continuous-integration/drone/push Build encountered an error Details
2025-02-14 16:56:25 +08:00
caiyiling 6de9cd26a4 影像阅片页面反馈按钮优化
continuous-integration/drone/push Build is passing Details
2025-02-14 16:07:40 +08:00
caiyiling caf3f41465 Merge branch 'uat' into main
continuous-integration/drone/push Build is passing Details
2025-02-14 14:52:03 +08:00
caiyiling 8896737a9e Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-02-14 14:32:57 +08:00
caiyiling 1be46686a3 国际化更改 2025-02-14 14:32:39 +08:00
caiyiling 0cd07b76f8 多帧对齐bug修复
continuous-integration/drone/push Build encountered an error Details
2025-02-14 14:30:55 +08:00
wangxiaoshuang d74c0028f6 版本记录页面国际化
continuous-integration/drone/push Build is passing Details
2025-02-13 15:37:08 +08:00
caiyiling ab5645f28a popper弹出层优化
continuous-integration/drone/push Build encountered an error Details
2025-02-13 13:50:27 +08:00
caiyiling efb88b7ad1 多帧影像质控更改
continuous-integration/drone/push Build encountered an error Details
2025-02-13 11:50:29 +08:00
wangxiaoshuang 129548031c 影像上传页面,临床数据统计
continuous-integration/drone/push Build is passing Details
2025-02-13 10:17:42 +08:00
wangxiaoshuang 5dbddbea57 Merge commit 'dba4466ac26890fcedfd8d20d8c20c9fd45e8850' into uat
continuous-integration/drone/push Build encountered an error Details
2025-02-13 09:28:59 +08:00
caiyiling 689782bf36 后台管理页面部分国际化更改
continuous-integration/drone/push Build is passing Details
2025-02-13 09:25:32 +08:00
wangxiaoshuang 89fe4e4c00 阅片人简历邮箱更改
continuous-integration/drone/push Build is passing Details
2025-02-12 17:20:23 +08:00
wangxiaoshuang a582daf686 il8n页面国际化 2025-02-12 17:20:10 +08:00
wangxiaoshuang 3e680d0033 临床数据上传依赖,排序改为枚举值
continuous-integration/drone/push Build is passing Details
2025-02-11 14:39:01 +08:00
wangxiaoshuang af343d43d8 邮件模板预览样式调整
continuous-integration/drone/push Build is passing Details
2025-02-11 14:17:41 +08:00
wangxiaoshuang 4b9216229c 国际化编辑新增迭代版本、状态
continuous-integration/drone/push Build is passing Details
2025-02-11 13:13:39 +08:00
wangxiaoshuang 2952762ce7 切换角色、项目返回时清除项目路由缓存
continuous-integration/drone/push Build is passing Details
2025-02-10 10:42:10 +08:00
caiyiling 361aed4a0c dicom文件上传批量验证提示更改
continuous-integration/drone/push Build is passing Details
2025-02-10 09:22:44 +08:00
caiyiling 19b419c29e 一致性核查更改
continuous-integration/drone/push Build is passing Details
2025-02-08 15:06:11 +08:00
caiyiling 7e9a9b62f6 样式调整
continuous-integration/drone/push Build is passing Details
2025-02-08 14:10:00 +08:00
caiyiling 3921f369c3 阅片单元样式调整
continuous-integration/drone/push Build is passing Details
2025-02-08 13:07:46 +08:00
caiyiling 0ffe7ff1a7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2025-02-08 11:31:23 +08:00
caiyiling 5ec969c2f9 临床数据补充英文模板及界面样式调整 2025-02-08 11:30:07 +08:00
caiyiling f1dee25987 核医学标准添加融合演示案例
continuous-integration/drone/push Build encountered an error Details
2025-01-02 09:18:20 +08:00
442 changed files with 79382 additions and 36295 deletions

View File

@ -5,7 +5,8 @@ NODE_ENV = 'development'
VUE_APP_BASE_PATH = '/'
VUE_APP_IS_TEST = false
# onlyoffice地址
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
# base api
VUE_APP_BASE_API = 'http://123.56.94.154:7000'

View File

@ -5,6 +5,9 @@ NODE_ENV = 'prod'
# base public path
VUE_APP_BASE_PATH = '/'
# onlyoffice地址
VUE_APP_ONLYOFFICE_URL = "https://office.extimaging.com"
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true

View File

@ -3,6 +3,8 @@ ENV = 'production'
NODE_ENV = 'production'
# base public path
VUE_APP_BASE_PATH = '/'
# onlyoffice地址
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
VUE_APP_IS_TEST = true

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

View File

@ -4,6 +4,9 @@ NODE_ENV = 'production'
# base public path
VUE_APP_BASE_PATH = '/'
# onlyoffice地址
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
# base public path
VUE_APP_BASE_PATH = '/'

View File

@ -1,48 +1,58 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
parser: '@babel/eslint-parser',
sourceType: 'module'
},
globals: {
"zzSessionStorage": true
'zzSessionStorage': true
},
env: {
browser: true,
node: true,
es6: true
},
extends: ["plugin:vue/recommended"],
extends: ['plugin:vue/recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
// it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [
2,
// "rule-name": "off"
// "vue/max-attributes-per-line": [
// 2,
// {
// singleline: 10,
// multiline: {
// max: 1,
// allowFirstLine: false
// }
// }
// ],
'vue/max-attributes-per-line': [
'error',
{
singleline: 10,
multiline: {
max: 1,
allowFirstLine: false
max: 1
}
}
],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
"accessor-pairs": 2,
"arrow-spacing": [
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/name-property-casing': ['error', 'PascalCase'],
'vue/no-v-html': 'off',
'accessor-pairs': 2,
'arrow-spacing': [
2,
{
before: true,
after: true
}
],
"block-spacing": [2, "always"],
"brace-style": [
'block-spacing': [2, 'always'],
'brace-style': [
2,
"1tbs",
'1tbs',
{
allowSingleLine: true
}
@ -50,31 +60,31 @@ module.exports = {
camelcase: [
0,
{
properties: "always"
properties: 'always'
}
],
"comma-dangle": [2, "never"],
"comma-spacing": [
'comma-dangle': [2, 'never'],
'comma-spacing': [
2,
{
before: false,
after: true
}
],
"comma-style": [2, "last"],
"constructor-super": 2,
curly: [2, "multi-line"],
"dot-location": [2, "property"],
"eol-last": 2,
eqeqeq: ["error", "always", { null: "ignore" }],
"generator-star-spacing": [
'comma-style': [2, 'last'],
'constructor-super': 2,
curly: [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
eqeqeq: ['error', 'always', { null: 'ignore' }],
'generator-star-spacing': [
2,
{
before: true,
after: true
}
],
"handle-callback-err": [2, "^(err|error)$"],
'handle-callback-err': [2, '^(err|error)$'],
indent: [
2,
2,
@ -82,197 +92,197 @@ module.exports = {
SwitchCase: 1
}
],
"jsx-quotes": [2, "prefer-single"],
"key-spacing": [
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [
2,
{
beforeColon: false,
afterColon: true
}
],
"keyword-spacing": [
'keyword-spacing': [
2,
{
before: true,
after: true
}
],
"new-cap": [
'new-cap': [
2,
{
newIsCap: true,
capIsNew: false
}
],
"new-parens": 2,
"no-array-constructor": 2,
"no-caller": 2,
"no-console": "off",
"no-class-assign": 2,
"no-cond-assign": 2,
"no-const-assign": 2,
"no-control-regex": 0,
"no-delete-var": 2,
"no-dupe-args": 2,
"no-dupe-class-members": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-empty-pattern": 2,
"no-eval": 2,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-boolean-cast": 2,
"no-extra-parens": [2, "functions"],
"no-fallthrough": 2,
"no-floating-decimal": 2,
"no-func-assign": 2,
"no-implied-eval": 2,
"no-inner-declarations": [2, "functions"],
"no-invalid-regexp": 2,
"no-irregular-whitespace": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": [
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [
2,
{
allowLoop: false,
allowSwitch: false
}
],
"no-lone-blocks": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-multiple-empty-lines": [
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [
2,
{
max: 1
}
],
"no-native-reassign": 2,
"no-negated-in-lhs": 2,
"no-new-object": 2,
"no-new-require": 2,
"no-new-symbol": 2,
"no-new-wrappers": 2,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-path-concat": 2,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-return-assign": [2, "except-parens"],
"no-self-assign": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-shadow-restricted-names": 2,
"no-spaced-func": 2,
"no-sparse-arrays": 2,
"no-this-before-super": 2,
"no-throw-literal": 2,
"no-trailing-spaces": 2,
"no-undef": 2,
"no-undef-init": 2,
"no-unexpected-multiline": 2,
"no-unmodified-loop-condition": 2,
"no-unneeded-ternary": [
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [
2,
{
defaultAssignment: false
}
],
"no-unreachable": 2,
"no-unsafe-finally": 2,
"no-unused-vars": [
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [
2,
{
vars: "all",
args: "none"
vars: 'all',
args: 'none'
}
],
"no-useless-call": 2,
"no-useless-computed-key": 2,
"no-useless-constructor": 2,
"no-useless-escape": 0,
"no-whitespace-before-property": 2,
"no-with": 2,
"one-var": [
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [
2,
{
initialized: "never"
initialized: 'never'
}
],
"operator-linebreak": [
'operator-linebreak': [
2,
"after",
'after',
{
overrides: {
"?": "before",
":": "before"
'?': 'before',
':': 'before'
}
}
],
"padded-blocks": [2, "never"],
'padded-blocks': [2, 'never'],
quotes: [
2,
"single",
'single',
{
avoidEscape: true,
allowTemplateLiterals: true
}
],
semi: [2, "never"],
"semi-spacing": [
semi: [2, 'never'],
'semi-spacing': [
2,
{
before: false,
after: true
}
],
"space-before-blocks": [2, "always"],
"space-before-function-paren": [2, "never"],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-unary-ops": [
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [
2,
{
words: true,
nonwords: false
}
],
"spaced-comment": [
'spaced-comment': [
2,
"always",
'always',
{
markers: [
"global",
"globals",
"eslint",
"eslint-disable",
"*package",
"!",
","
'global',
'globals',
'eslint',
'eslint-disable',
'*package',
'!',
','
]
}
],
"template-curly-spacing": [2, "never"],
"use-isnan": 2,
"valid-typeof": 2,
"wrap-iife": [2, "any"],
"yield-star-spacing": [2, "both"],
yoda: [2, "never"],
"prefer-const": 2,
//"no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
"object-curly-spacing": [
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
yoda: [2, 'never'],
'prefer-const': 2,
// "no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
'object-curly-spacing': [
2,
"always",
'always',
{
objectsInObjects: false
}
],
"array-bracket-spacing": [2, "never"]
'array-bracket-spacing': [2, 'never']
}
};
}

View File

@ -10516,7 +10516,7 @@ class BaseViewer {
const pageNumber = this._currentPageNumber,
state = this.#scrollModePageState,
viewer = this.viewer;
viewmr = this.viewer;
viewer.textContent = "";
state.pages.length = 0;

View File

@ -1,10 +1,12 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
// '@vue/cli-plugin-babel/preset',
// ["@babel/preset-env", { "modules": false }]
'@babel/preset-env'
],
plugins: [
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-nullish-coalescing-operator'
'@vue/babel-plugin-transform-vue-jsx'
// '@babel/plugin-proposal-optional-chaining',
// '@babel/plugin-proposal-nullish-coalescing-operator'
]
}

36989
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,23 +14,20 @@
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.370.0",
"@aws-sdk/client-s3": "^3.701.0",
"@cornerstonejs/adapters": "^2.19.7",
"@cornerstonejs/calculate-suv": "^1.1.0",
"@cornerstonejs/core": "^1.27.4",
"@cornerstonejs/dicom-image-loader": "^1.27.4",
"@cornerstonejs/streaming-image-volume-loader": "1.23.2",
"@cornerstonejs/tools": "^1.27.4",
"@ffmpeg/core": "^0.10.0",
"@ffmpeg/ffmpeg": "^0.10.1",
"@microsoft/signalr": "^6.0.8",
"@riophae/vue-treeselect": "0.4.0",
"@cornerstonejs/core": "^2.19.7",
"@cornerstonejs/dicom-image-loader": "^2.19.7",
"@cornerstonejs/tools": "^2.19.7",
"@icr/polyseg-wasm": "^0.4.0",
"@microsoft/signalr": "^8.0.7",
"@riophae/vue-treeselect": "^0.4.0",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.11",
"@vue/composition-api": "^1.7.2",
"ali-oss": "^6.17.1",
"axios": "0.18.1",
"babel-eslint": "7.2.3",
"copy-webpack-plugin": "^4.5.2",
"axios": "^0.18.1",
"core-js": "^3.8.3",
"cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.10",
@ -41,67 +38,70 @@
"dicom-parser": "^1.8.9",
"dicomedit": "^0.1.0",
"echarts": "^4.8.0",
"element-ui": "^2.15.8",
"exceljs": "^4.1.0",
"element-ui": "^2.15.14",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
"hammerjs": "^2.0.8",
"html2canvas": "^1.4.1",
"js-md5": "^0.7.3",
"js-md5": "^0.8.3",
"jsencrypt": "^3.3.2",
"jszip": "^3.7.1",
"moment": "^2.27.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"node-sass": "^4.14.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"pdfobject": "^2.2.8",
"popper.js": "^1.16.1",
"qrcodejs2": "0.0.2",
"sass-loader": "^8.0.0",
"screenfull": "^4.2.0",
"sortablejs": "^1.15.0",
"jszip": "^3.10.1",
"minio": "^7.1.3",
"moment": "^2.30.1",
"moment-timezone": "^0.5.46",
"node-xlsx": "^0.24.0",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"path-to-regexp": "^0.1.10",
"pdfobject": "^2.3.0",
"prismjs": "^1.30.0",
"qrcodejs2": "^0.0.2",
"screenfull": "^6.0.2",
"sortablejs": "^1.15.5",
"streamsaver": "^2.0.6",
"v-viewer": "^1.6.4",
"svg-sprite-loader": "^4.1.3",
"svgo": "^1.2.2",
"v-viewer": "^1.7.4",
"vcrontab": "^0.3.5",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",
"vue-contextmenujs": "^1.3.13",
"vue": "^2.6.14",
"vue-clipboard2": "^0.3.3",
"vue-contextmenujs": "^1.4.11",
"vue-count-to": "^1.0.13",
"vue-demi": "^0.14.6",
"vue-i18n": "^8.7.0",
"vue-pdf": "^4.3.0",
"vue-demi": "^0.14.10",
"vue-i18n": "^8.28.2",
"vue-prism-editor": "^1.3.0",
"vue-puzzle-vcode": "^1.1.10",
"vue-router": "3.0.6",
"vue-seamless-scroll": "^1.1.21",
"vue-router": "^3.0.6",
"vue-seamless-scroll": "^1.1.23",
"vuedraggable": "^2.24.3",
"vuex": "3.1.0",
"webpack-aliyun-oss": "^0.4.9"
"vuex": "^3.1.0",
"webpack-aliyun-oss": "^0.3.13"
},
"devDependencies": {
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@vue/cli-plugin-babel": "~4.5.4",
"@vue/cli-plugin-eslint": "~4.5.4",
"@vue/cli-service": "~4.5.4",
"autoprefixer": "^9.5.1",
"aws-sdk": "^2.1532.0",
"babel-eslint": "^10.1.0",
"chalk": "2.4.2",
"connect": "3.6.6",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"html-webpack-plugin": "3.2.0",
"minio": "^7.1.3",
"moment-timezone": "^0.5.45",
"node-xlsx": "^0.21.0",
"runjs": "^4.3.2",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"vue-template-compiler": "^2.6.11"
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@babel/plugin-transform-class-static-block": "^7.26.0",
"@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"autoprefixer": "^10.4.20",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^12.0.2",
"css-minimizer-webpack-plugin": "^7.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"html-webpack-plugin": "^5.6.3",
"mini-css-extract-plugin": "^2.9.2",
"node-polyfill-webpack-plugin": "^4.0.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"sass": "^1.63.2",
"sass-loader": "^10.4.1",
"terser-webpack-plugin": "^5.3.10",
"vue-template-compiler": "^2.6.14",
"webpack": "^5.96.1",
"webpack-bundle-analyzer": "^4.10.2"
},
"eslintConfig": {
"root": true,
@ -109,19 +109,19 @@
"node": true
},
"extends": [
"plugin:vue/essential"
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
"parser": "@babel/eslint-parser",
"requireConfigFile": false
},
"rules": {}
},
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions"
"last 2 versions",
"not dead",
"not op_mini all"
]
}

197
public/cease.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,7 @@
direction="rtl"
size="80%"
>
<div style="width: 620px">
<div style="width: 800px">
<el-form
label-width="100px"
@submit.native.prevent
@ -40,7 +40,7 @@
<el-form-item :label="$t('il8n:search:keyword')">
<el-input v-model="key" @input="keyChange" />
</el-form-item>
<el-form-item :label="$t('il8n:search:state')" v-if="il8nExternal">
<el-form-item :label="$t('il8n:search:state')">
<el-select
v-model="State"
clearable
@ -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"
@ -108,7 +118,7 @@
<el-table-column
prop="ValueCN"
:label="$t('il8n:table:state')"
v-if="il8nExternal"
sortable="custom"
>
<template slot-scope="scope">
<el-select
@ -126,12 +136,20 @@
</el-select>
</template>
</el-table-column>
<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">
<el-button size="mini" @click="drawer = false">取消 </el-button>
<el-button size="mini" type="primary" @click="handleSave"
>保存</el-button
>
<el-button size="mini" @click="drawer = false"
>{{ $t('common:button:cancel') }}
</el-button>
<el-button size="mini" type="primary" @click="handleSave">{{
$t('common:button:save')
}}</el-button>
</div>
</el-drawer>
<feedBack v-if="$route.matched.length > 0" />
@ -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
@ -209,9 +239,12 @@ export default {
[],
this.arr.filter(
(v) =>
~v.Code.toLowerCase().indexOf(this.key.toLowerCase()) ||
~v.Value.toLowerCase().indexOf(this.key.toLowerCase()) ||
~v.ValueCN.toLowerCase().indexOf(this.key.toLowerCase())
(v.Code &&
~v.Code.toLowerCase().indexOf(this.key.toLowerCase())) ||
(v.Value &&
~v.Value.toLowerCase().indexOf(this.key.toLowerCase())) ||
(v.ValueCN &&
~v.ValueCN.toLowerCase().indexOf(this.key.toLowerCase()))
)
)
} else {
@ -219,33 +252,39 @@ export default {
}
},
handleSave() {
this.$confirm('确定修改当前页面国际化内容?').then(() => {
batchAddOrUpdateFrontInternationalization(this.tableData).then(
async (res) => {
var zhMessages = {},
enMessages = {}
var Internationalization = await getFrontInternationalizationList()
Vue.prototype.$tl = Internationalization.Result
this.tableData.forEach((v) => {
// zhMessages[v.Description + '_' + v.Code] = v.ValueCN
// enMessages[v.Description + '_' + v.Code] = v.Value
zhMessages[v.Code] = v.ValueCN
enMessages[v.Code] = v.Value
})
i18n.mergeLocaleMessage('zh', zhMessages)
i18n.mergeLocaleMessage('en', enMessages)
this.drawer = false
this.$message.success('国际化修改成功')
if (this.il8nExternal) {
this.$EventBus.$emit('il8nUpdate')
this.$confirm(this.$t("i18n:confirm:updatei18n"))
.then(() => {
batchAddOrUpdateFrontInternationalization(this.tableData).then(
async (res) => {
var zhMessages = {},
enMessages = {}
var Internationalization =
await getFrontInternationalizationList()
Vue.prototype.$tl = Internationalization.Result
this.tableData.forEach((v) => {
// zhMessages[v.Description + '_' + v.Code] = v.ValueCN
// enMessages[v.Description + '_' + v.Code] = v.Value
zhMessages[v.Code] = v.ValueCN
enMessages[v.Code] = v.Value
})
i18n.mergeLocaleMessage('zh', zhMessages)
i18n.mergeLocaleMessage('en', enMessages)
this.drawer = false
this.$message.success(this.$t("i18n:message:updatei18nSuccessfully"))
if (this.il8nExternal) {
this.$EventBus.$emit('il8nUpdate')
}
}
}
)
})
)
})
.catch((err) => {
console.log(err)
})
},
openI18n(ARRAY) {
this.tableData = []
this.il8nExternal = false
this.State = null
this.key = null
this.drawer = true
let arr = []
@ -266,6 +305,8 @@ export default {
Value: item.Value,
ValueCN: item.ValueCN,
State: item.State,
Version: item.Version,
InternationalizationType: item.InternationalizationType,
}
})
this.tableData = Object.assign([], tableData)
@ -296,6 +337,9 @@ export default {
Description: null,
Value: null,
ValueCN: null,
State: 0,
Version: this.$version.Version,
InternationalizationType: 0,
})
}
})

View File

@ -342,3 +342,11 @@ export function addNewUserSendEmail(data) {
data
})
}
// 用户追溯
export function getUserJoinedTrialList(data) {
return request({
url: `/TrialMaintenance/getUserJoinedTrialList`,
method: 'post',
data
})
}

View File

@ -212,7 +212,20 @@ export function getSystemDocumentList(param) {
data: param
})
}
export function publishSystemDocument(param) {
return request({
url: `/SystemDocument/publishSystemDocument`,
method: 'post',
data: param
})
}
export function outLineSystemDocument(param) {
return request({
url: `/SystemDocument/outLineSystemDocument`,
method: 'post',
data: param
})
}
export function addOrUpdateSystemDocument(param) {
return request({
url: `/SystemDocument/addOrUpdateSystemDocument`,
@ -220,6 +233,29 @@ export function addOrUpdateSystemDocument(param) {
data: param
})
}
// 新增/修改通用培训附件
export function addOrUpdateSystemDocumentAttachment(param) {
return request({
url: `/SystemDocument/addOrUpdateSystemDocumentAttachment`,
method: 'post',
data: param
})
}
// 通用培训附件列表
export function getSystemDocumentAttachmentList(param) {
return request({
url: `/SystemDocument/getSystemDocumentAttachmentList`,
method: 'post',
data: param
})
}
// 删除通用培训附件
export function deleteSystemDocumentAttachment(systemDocumentAttachmentId) {
return request({
url: `/SystemDocument/deleteSystemDocumentAttachment/${systemDocumentAttachmentId}`,
method: 'delete',
})
}
export function deleteSystemDocument(id) {
return request({
@ -382,10 +418,11 @@ export function addOrUpdateBasicDic(param) {
})
}
export function getDictionaryChildList(id) {
export function getDictionaryChildList(data) {
return request({
url: `/Dictionary/getChildList/${id}`,
method: 'get'
url: `/Dictionary/getChildList`,
method: 'post',
data
})
}
@ -1070,3 +1107,293 @@ export function batchAddEnrollOrPdEmailConfig(params) {
params
})
}
// 文件记录-系统文件列表
export function getSysFileTypeList(data) {
return request({
url: `/SysFileType/getSysFileTypeList`,
method: 'post',
data
})
}
// 文件记录-新增/编辑系统文件
export function addOrUpdateSysFileType(data) {
return request({
url: `/SysFileType/addOrUpdateSysFileType`,
method: 'post',
data
})
}
// 文件记录-删除系统文件
export function deleteSysFileType(id) {
return request({
url: `/SysFileType/deleteSysFileType/${id}`,
method: 'delete'
})
}
// 项目文档-获取项目菜单
export function getTrialFileTypeData(data) {
return request({
url: `/TrialFileType/getTrialFileTypeData`,
method: 'post',
data
})
}
// 项目文档-修改项目菜单启用
export function setAuthorizedView(data) {
return request({
url: `/TrialFileType/setAuthorizedView`,
method: 'post',
data
})
}
// 项目文档-新增/修改项目菜单
export function addOrUpdateTrialFileType(data) {
return request({
url: `/TrialFileType/addOrUpdateTrialFileType`,
method: 'post',
data
})
}
// 项目文档-删除项目菜单
export function deleteTrialFileType(id) {
return request({
url: `/TrialFileType/deleteTrialFileType/${id}`,
method: 'delete',
})
}
// 项目文档-报告/文档列表
export function getTrialFinalRecordList(data) {
return request({
url: `/TrialFinalRecord/getTrialFinalRecordList`,
method: 'post',
data
})
}
// 项目文档-报告/文档授权
export function authorizedTrialFinalRecord(data) {
return request({
url: `/TrialFinalRecord/authorizedTrialFinalRecord`,
method: 'post',
data
})
}
// 项目文档-报告/文档新增/修改
export function addOrUpdateTrialFinalRecord(data) {
return request({
url: `/TrialFinalRecord/addOrUpdateTrialFinalRecord`,
method: 'post',
data
})
}
// 项目文档-删除报告/文档
export function deleteTrialFinalRecord(id) {
return request({
url: `/TrialFinalRecord/deleteTrialFinalRecord/${id}`,
method: 'delete',
})
}
// 项目文档-一般文件记录列表
export function getTrialNormalRecordList(data) {
return request({
url: `/TrialNormalRecord/getTrialNormalRecordList`,
method: 'post',
data
})
}
// 项目文档-一般文件记录授权
export function authorizedTTrialNormalRecord(data) {
return request({
url: `/TrialNormalRecord/authorizedTTrialNormalRecord`,
method: 'post',
data
})
}
// 项目文档-一般文件记录批量新增
export function batchAddTrialNormalRecord(data) {
return request({
url: `/TrialNormalRecord/batchAddTrialNormalRecord`,
method: 'post',
data
})
}
// 项目文档-一般文件记录新增/修改
export function addOrUpdateTrialNormalRecord(data) {
return request({
url: `/TrialNormalRecord/addOrUpdateTrialNormalRecord`,
method: 'post',
data
})
}
// 项目文档-删除一般文件记录
export function deleteTrialNormalRecord(id) {
return request({
url: `/TrialNormalRecord/deleteTrialNormalRecord/${id}`,
method: 'delete',
})
}
// 项目文档-批量删除一般文件记录
export function deleteTrialNormalRecordList(data) {
return request({
url: `/TrialNormalRecord/deleteTrialNormalRecordList`,
method: 'post',
data
})
}
// 项目文档-培训记录列表
export function getTrialTrianingRecordList(data) {
return request({
url: `/TrialTrianingRecord/getTrialTrianingRecordList`,
method: 'post',
data
})
}
// 项目文档-培训记录新增/修改
export function addOrUpdateTrialTrianingRecord(data) {
return request({
url: `/TrialTrianingRecord/addOrUpdateTrialTrianingRecord`,
method: 'post',
data
})
}
// 项目文档-培训记录批量新增/修改
export function batchAddTrialTrianingRecord(data) {
return request({
url: `/TrialTrianingRecord/batchAddTrialTrianingRecord`,
method: 'post',
data
})
}
// 项目文档-删除培训记录
export function deleteTrialTrianingRecord(id) {
return request({
url: `/TrialTrianingRecord/deleteTrialTrianingRecord/${id}`,
method: 'delete',
})
}
// 项目文档-培训记录授权
export function authorizedTrialTrianingRecord(data) {
return request({
url: `/TrialTrianingRecord/authorizedTrialTrianingRecord`,
method: 'post',
data
})
}
// 项目文档-阅片人简历
export function getTrialDoctorList(data) {
return request({
url: `/DoctorList/getTrialDoctorList`,
method: 'post',
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
})
}
// 项目文档-获取历史记录列表
export function getTrialHistoryRecordFileList(data) {
return request({
url: `/TrialHistoryRecordFile/getTrialHistoryRecordFileList`,
method: 'post',
data
})
}
// 项目文档-新增/修改历史记录
export function addOrUpdateTrialHistoryRecordFile(data) {
return request({
url: `/TrialHistoryRecordFile/addOrUpdateTrialHistoryRecordFile`,
method: 'post',
data
})
}
// 项目文档-批量新增历史记录
export function batchAddTrialHistoryRecordFile(data) {
return request({
url: `/TrialHistoryRecordFile/batchAddTrialHistoryRecordFile`,
method: 'post',
data
})
}
// 项目文档-删除历史记录
export function deleteTrialHistoryRecordFile(id) {
return request({
url: `/TrialHistoryRecordFile/deleteTrialHistoryRecordFile/${id}`,
method: 'delete',
})
}
// 邮件管理-批量修改邮件
export function batchUpdateEmail(data) {
return request({
url: `/EmailNoticeConfig/batchUpdateEmail`,
method: 'post',
data
})
}

View File

@ -45,10 +45,19 @@ export function changeFrontAuditSort(param) {
})
}
export function getModuleTypeDescriptionList(param) {
export function getModuleTypeDescriptionList(params) {
return request({
url: `${param === '' ? '/FrontAuditConfig/getModuleTypeDescriptionList' : '/FrontAuditConfig/getModuleTypeDescriptionList?moduleTypeId=' + param}`,
method: 'get'
url: `/FrontAuditConfig/getModuleTypeDescriptionList`,
method: 'get',
params
})
}
export function getModuleTypeList(data) {
return request({
url: `/FrontAuditConfig/getModuleTypeList`,
method: 'post',
data
})
}

View File

@ -72,7 +72,14 @@ export function getReadingTaskList_Export(param) {
data: param
})
}
export function getTrialVisitImageStatList_Export(param) {
return requestDownload({
url: '/ExcelExport/getTrialVisitImageStatList_Export',
method: 'post',
responseType: 'blob',
data: param
})
}
export function getReReadingTaskList_Export(param) {
return requestDownload({
url: '/ExcelExport/getReReadingTaskList_Export',
@ -178,6 +185,15 @@ export function pMTrainingRecordList_Export(data) {
data
})
}
// 导出系统培训记录
export function getSysDocumentConfirmList_Export(data) {
return requestDownload({
url: `/ExcelExport/getSysDocumentConfirmList_Export`,
responseType: 'blob',
method: 'post',
data
})
}
// 导出影像指控
export function qCVisitList_Export(data) {
return requestDownload({

View File

@ -1035,7 +1035,27 @@ export function getQCVisitList(param) {
data: param
})
}
export function getImageBackList(param) {
return request({
url: `/QCList/getImageBackList`,
method: 'post',
data: param
})
}
export function getImageBackApplyUserList(params) {
return request({
url: `/QCList/getImageBackApplyUserList`,
method: 'get',
params
})
}
export function auditImageBack(params) {
return request({
url: `/QCOperation/auditImageBack`,
method: 'put',
params
})
}
export function getQCChallengeList(param) {
return request({
url: `/QCList/getQCChallengeList`,
@ -1080,6 +1100,19 @@ export function setSeriesStatus(trialId, subjectVisitId, studyId, seriesId, stat
method: 'put'
})
}
export function setNodicomStudyState(params) {
return request({
url: `/QCOperation/setNodicomStudyState`,
method: 'put',
params
})
}
export function setInstanceStatus(trialId, subjectVisitId, seriesId, instanceId, state) {
return request({
url: `/QCOperation/setInstanceState/${trialId}/${subjectVisitId}/${seriesId}/${instanceId}/${state}`,
method: 'put'
})
}
export function getVisitQCStudyAndSeriesList(subjectVisitId) {
return request({
@ -1365,9 +1398,9 @@ export function getForwardList(param) {
})
}
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false, visitTaskId = '') {
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false, visitTaskId = '', IsReading = false) {
return request({
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}&visitTaskId=${visitTaskId}`,
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}&visitTaskId=${visitTaskId}&IsReading=${IsReading}`,
method: 'get'
})
}
@ -1586,6 +1619,13 @@ export function getDocumentConfirmList(param) {
data: param
})
}
export function getSysDocumentConfirmList(param) {
return request({
url: `/TrialDocument/getSysDocumentConfirmList`,
method: 'post',
data: param
})
}
export function getTrialUserSelect(trialId) {
return request({
url: `/TrialDocument/getTrialUserSelect/${trialId}`,
@ -1600,6 +1640,13 @@ export function getTrialDocAndSystemDocType(trialId) {
})
}
export function getSysDocSignUserList() {
return request({
url: `/TrialDocument/getSysDocSignUserList`,
method: 'get'
})
}
export function updateSubjectStatus(param) {
return request({
url: `/Subject/updateSubjectStatus`,
@ -3295,6 +3342,13 @@ export function getReReadingApplyToBeDoneList(param) {
data: param
})
}
export function getPMImageBackToBeDoneList(param) {
return request({
url: `/PersonalWorkstation/getPMImageBackToBeDoneList`,
method: 'post',
data: param
})
}
export function deleteClinicalForm(param) {
return request({
@ -3933,8 +3987,6 @@ export function updateTrialUserRole(data) {
})
}
// 获取报表配置
export function getTrialQuestionExportResult(data) {
return request({
@ -3959,3 +4011,190 @@ export function trialUserSendJoinEmail(data) {
data
})
}
// 获取非Dicom标记
export function getNoneDicomMarkListOutDto(data) {
return request({
url: `/ReadingImageTask/getNoneDicomMarkListOutDto`,
method: 'post',
data
})
}
// 添加非Dicom标记
export function addNoneDicomMark(data) {
return request({
url: `/ReadingImageTask/addNoneDicomMark`,
method: 'post',
data
})
}
// 删除非Dicom标记
export function deleteTrialFileType(id) {
return request({
url: `/ReadingImageTask/deleteTrialFileType/${id}`,
method: 'post'
})
}
// 工作台-获取稽查文档
export function getAuditDocumentData(data) {
return request({
url: `/AuditDocument/getAuditDocumentData`,
method: 'post',
data
})
}
// 工作台-新增稽查文档
export function addAuditDocument(data) {
return request({
url: `/AuditDocument/addAuditDocument`,
method: 'post',
data
})
}
// 工作台-获取当前目录层级
export function getBreadcrumbData(data) {
return request({
url: `/AuditDocument/getBreadcrumbData`,
method: 'post',
data
})
}
// 工作台-修改稽查文档
export function updateAuditDocument(data) {
return request({
url: `/AuditDocument/updateAuditDocument`,
method: 'post',
data
})
}
// 工作台-删除稽查文档
export function deleteAuditDocument(data) {
return request({
url: `/AuditDocument/deleteAuditDocument`,
method: 'post',
data
})
}
// 工作台-稽查文档获取历史版本
export function getHistoricalVersion(data) {
return request({
url: `/AuditDocument/getHistoricalVersion`,
method: 'post',
data
})
}
// 工作台-稽查文档设置当前版本
export function setCurrentVersion(data) {
return request({
url: `/AuditDocument/setCurrentVersion`,
method: 'post',
data
})
}
// 工作台-稽查文档移动
export function movieFileOrFolder(data) {
return request({
url: `/AuditDocument/movieFileOrFolder`,
method: 'post',
data
})
}
// 工作台-稽查文档复制
export function copyFileOrFolder(data) {
return request({
url: `/AuditDocument/copyFileOrFolder`,
method: 'post',
data
})
}
// 工作台-稽查文档授权
export function setIsAuthorization(data) {
return request({
url: `/AuditDocument/setIsAuthorization`,
method: 'post',
data
})
}
// 工作台-稽查文档新增文件夹
export function addFolder(data) {
return request({
url: `/AuditDocument/addFolder`,
method: 'post',
data
})
}
// 配置-项目文档发布
export function publishTrialDocument(data) {
return request({
url: `/TrialDocument/publishTrialDocument`,
method: 'post',
data
})
}
// 配置-获取项目文档附件列表
export function getTrialDocumentAttachmentList(data) {
return request({
url: `/TrialDocument/getTrialDocumentAttachmentList`,
method: 'post',
data
})
}
// 配置-新增或修改项目文档附件
export function addOrUpdateTrialDocumentAttachment(data) {
return request({
url: `/TrialDocument/addOrUpdateTrialDocumentAttachment`,
method: 'post',
data
})
}
// 配置-删除项目文档附件
export function deleteTrialDocumentAttachment(data) {
return request({
url: `/TrialDocument/deleteTrialDocumentAttachment/${data}`,
method: 'delete',
})
}
// 配置-获取稽查管理列表
export function getTrialShowInspection(data) {
return request({
url: `/Inspection/getTrialShowInspection`,
method: 'post',
data
})
}
// 配置-设置稽查管理配置
export function setTrialShowInspection(data) {
return request({
url: `/Inspection/setTrialShowInspection`,
method: 'post',
data
})
}
// 影像汇总-获取列表
export function getTrialVisitImageStatList(data) {
return request({
url: `/DownloadAndUpload/getTrialVisitImageStatList`,
method: 'post',
data
})
}
// 影像汇总-获取统计
export function getTrialVisitImageStatInfo(params) {
return request({
url: `/DownloadAndUpload/getTrialVisitImageStatInfo`,
method: 'get',
params
})
}
// 影像汇总-影像下载
export function getExportSubjectVisitImageList(data) {
return request({
url: `/DownloadAndUpload/getExportSubjectVisitImageList`,
method: 'post',
data
})
}

View File

@ -346,9 +346,9 @@ export function getReReadingOrBackInfluenceTaskList(taskId, isReReading, applyId
})
}
export function PMSetTaskBack(trialId, taskId) {
export function PMSetTaskBack(trialId, taskId, pmBackReason) {
return request({
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}`,
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}/${pmBackReason}`,
method: 'put'
})
}
@ -459,9 +459,9 @@ export function setMedicalReviewInvalid(params) {
})
}
export function getTrialCriterionList(trialId) {
export function getTrialCriterionList(trialId, isRandom = false) {
return request({
url: `/VisitTask/getTrialCriterionList?TrialId=${trialId}`,
url: `/VisitTask/getTrialCriterionList?TrialId=${trialId}&isRandom=${isRandom}`,
method: 'get'
})
}
@ -480,3 +480,11 @@ export function resetReadingRestTime() {
method: 'post'
})
}
// 设置随机排序
export function setRandomTaskOrder(data) {
return request({
url: `/VisitTask/setRandomTaskOrder`,
method: 'post',
data
})
}

View File

@ -110,4 +110,12 @@ export function addOrUpdateTrialBodyPart(data) {
data
})
}
// 修改检查名称列表
export function updateTrialStudyNameList(data) {
return request({
url: `/TrialConfig/updateTrialStudyNameList`,
method: 'post',
data
})
}

View File

@ -287,4 +287,12 @@ export function forwardSVDicomImage(param) {
data: param
})
}
// crc、iqc申请影像退回
export function requestImageBack(params) {
return request({
url: `/QCOperation/requestImageBack`,
method: 'put',
params
})
}

View File

@ -209,3 +209,11 @@ export function loginSelectUserRole(params) {
params,
})
}
// 忽略异地登录
export function setIsIgnoreUncommonly(data) {
return request({
url: `/User/setIsIgnoreUncommonly`,
method: 'post',
data,
})
}

BIN
src/assets/0.file-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
src/assets/color-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

BIN
src/assets/menu_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
src/assets/pdf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
src/assets/stickup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src/assets/zip.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -4,6 +4,7 @@
<el-col :span="24">
<div class="box">
<div class="box-body">
<slot name="title-container" />
<div class="search">
<slot name="search-container" />
</div>
@ -24,42 +25,42 @@ export default {
props: {
noTitle: {
type: Boolean,
default: false
}
default: false,
},
},
computed: {
contentClass() {
return this.noTitle ? 'content-notitle' : 'content'
}
}
},
},
}
</script>
<style lang="scss">
.box-body{
padding: 0px;
background-color: #fff;
.el-card__body {
padding: 0px;
}
.search{
display: flex;
padding: 5px;
.box-body {
padding: 0px;
background-color: #fff;
.el-card__body {
padding: 0px;
}
.search {
display: flex;
padding: 5px;
.mr5{
margin-right:5px;
}
.el-form-item{
margin-bottom: 10px;
}
.mr5 {
margin-right: 5px;
}
.page{
text-align: right;
padding-top: 3px;
}
.el-button.is-circle {
padding: 9px;
font-weight: bold;
font-size: 14px;
.el-form-item {
margin-bottom: 10px;
}
}
.page {
text-align: right;
padding-top: 3px;
}
.el-button.is-circle {
padding: 9px;
font-weight: bold;
font-size: 14px;
}
}
</style>

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"
@ -146,17 +146,18 @@
<!-- 具名slot -->
<slot v-if="item.type === 'Custom'" :name="item.slot" />
</el-form-item>
<el-form-item v-for="item in searchHandle" :key="item.label">
<slot v-if="item.slot" :name="item.slot" />
<el-button
v-else
:type="item.type"
:size="item.size || size"
:icon="item.icon || ''"
@click="handleClick(item.emitKey)"
>{{ item.label }}</el-button
>
</el-form-item>
<div style="display: inline-block;width: fit-content;">
<el-form-item v-for="item in searchHandle" :key="item.label">
<slot v-if="item.slot" :name="item.slot" />
<el-button
v-else
:type="item.type"
:icon="item.icon || ''"
@click="handleClick(item.emitKey)"
>{{ item.label }}</el-button
>
</el-form-item>
</div>
</el-form>
</div>
</template>
@ -174,11 +175,11 @@ export default {
},
labelWidth: {
type: String,
default: "",
default: '',
},
size: {
type: String,
default: "mini",
default: 'mini',
},
searchForm: {
type: Array,
@ -196,10 +197,10 @@ export default {
methods: {
handleClick(emitKey) {
// emit
this.$emit(`${emitKey}`);
this.$emit(`${emitKey}`)
},
},
};
}
</script>
<style lang="scss">
.base-search-form {

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]) ||

View File

@ -1,15 +1,7 @@
<template>
<div
id="canvas"
ref="canvas"
v-loading="loading"
element-loading-text="Loading..."
element-loading-background="rgba(0, 0, 0, 0.8)"
style="width:100%;height:100%;position:relative;"
class="cornerstone-element"
@contextmenu.prevent="onContextmenu"
@mouseup="sliderMouseup"
>
<div id="canvas" ref="canvas" v-loading="loading" element-loading-text="Loading..."
element-loading-background="rgba(0, 0, 0, 0.8)" style="width:100%;height:100%;position:relative;"
class="cornerstone-element" @contextmenu.prevent="onContextmenu" @mouseup="sliderMouseup">
<div v-show="dicomInfo.series" class="info-series">
<div>Series #{{ dicomInfo.series }}</div>
<div>Image #{{ dicomInfo.frame }}</div>
@ -26,9 +18,11 @@
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div> -->
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
<div v-show="mousePosition.mo">
Pos: {{ mousePosition.x?mousePosition.x.toFixed(0):'' }}, {{ mousePosition.y?mousePosition.y.toFixed(0):'' }}
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
'' }}
</div>
<div v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
<div
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
HU: {{ mousePosition.mo }}
</div>
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
@ -53,8 +47,12 @@
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> -->
</div>
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer" @click.stop="goViewer($event)">
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @mousedown="sliderMousedown($event)" />
<div ref="sliderBox" class="my_slider_box"
style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer"
@click.stop="goViewer($event)">
<div :style="{ top: height + '%' }"
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
@mousedown="sliderMousedown($event)" />
</div>
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
{{ markers.top }}
@ -81,16 +79,9 @@
<!-- <div v-show="stack.firstImageLoading" class="load-indicator">
Loading Series #{{ stack.seriesNumber }}...
</div>-->
<el-dialog
v-if="dcmTag.visible"
:visible.sync="dcmTag.visible"
:close-on-click-modal="false"
:title="dcmTag.title"
width="1000px"
custom-class="base-dialog-wrapper"
append-to-body
>
<DicomTags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
<el-dialog v-if="dcmTag.visible" :visible.sync="dcmTag.visible" :close-on-click-modal="false" :title="dcmTag.title"
width="1000px" custom-class="base-dialog-wrapper" append-to-body>
<dicom-tags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
</el-dialog>
</div>
</template>
@ -217,10 +208,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)
@ -263,9 +254,9 @@ export default {
)
if (!toolAlreadyAddedToElement) {
if (toolName === 'RectangleRoi') {
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true}})
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true } })
} else if (toolName === 'EllipticalRoi') {
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true}})
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true } })
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
@ -346,9 +337,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()
},
@ -368,9 +359,8 @@ export default {
data.string('x00080030')
)
this.dicomInfo.series = data.string('x00200011')
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
this.stack.imageIds.length
}`
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${this.stack.imageIds.length
}`
this.dicomInfo.size = `${data.uint16('x00280011')}x${data.uint16(
'x00280010'
)}`
@ -415,15 +405,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
@ -432,6 +423,9 @@ export default {
this.dicomInfo.zoom = viewport.scale.toFixed(4)
var data = e.detail.image.data
const position = data.string('x00201041')
const windowCenter = data.string('x00281050')
const windowWidth = data.string('x00281051')
this.setWwwc(windowWidth, windowCenter)
this.dicomInfo.location = position
},
getOrientationMarker(element) {
@ -677,7 +671,7 @@ export default {
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
).data[0].loop = true
},
setFps(fps) {
this.dicomInfo.fps = fps
@ -1135,6 +1129,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-image {
position: absolute;
left: 10px;
@ -1154,6 +1149,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-instance {
position: absolute;
right: 15px;
@ -1186,6 +1182,7 @@ export default {
margin: 10px;
cursor: default;
}
.menu__item:hover {
color: #ff0000;
}
@ -1205,7 +1202,8 @@ li:hover {
background-color: #e0e0e2;
color: white;
}
.my_slider_box:after{
.my_slider_box:after {
content: '';
position: absolute;
bottom: -20px;

View File

@ -1,28 +1,30 @@
<template>
<div class="preview-wrapper">
<iframe
v-if="fileType.indexOf('jpg') !== -1 || fileType.indexOf('png') !== -1"
frameborder="0"
:src="filePath"
width="100%"
height="100%"
/>
<iframe v-if="fileType.indexOf('jpg') !== -1 || fileType.indexOf('png') !== -1" frameborder="0" :src="filePath"
width="100%" height="100%" />
<!-- <embed v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" style="width: 100%; height: 100%"> -->
<!-- <iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" width="100%" height="100%" frameborder="0" /> -->
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
<iframe v-else-if="fileType.indexOf('pdf') !== -1"
:src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`"
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
<!-- <pdf-->
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
<!-- </pdf>-->
<div v-else>
<video :src="`${OSSclientConfig.basePath}${filePath}`" style="width: 100%;height: 99%;" autoplay controls
controlsList="nodownload" v-else-if="fileType.indexOf('mp4') !== -1"></video>
<iframe v-else
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${filePath}?onlyOffice_url=${onlyOffice_url}&type=${fileType}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
<!-- <div v-else>
{{ $t('common:message:downloadFile') }}
<el-link type="primary" @click="downLoadFile">{{ $t('common:button:download') }}</el-link>
</div>
</div> -->
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import DOCUMENTTYPE from "@/utils/onlyOffice_type.js"
export default {
name: 'PreviewFile',
computed: {
@ -36,12 +38,22 @@ export default {
fileType: {
type: String,
required: true
}
},
title: {
type: String,
default: ''
},
},
data() {
return {
currentUser: zzSessionStorage.getItem('userName'),
COMPANY:process.env.VUE_APP_COMPANY_NAME
COMPANY: process.env.VUE_APP_COMPANY_NAME,
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
}
},
computed: {
documentType() {
return DOCUMENTTYPE[`.${this.fileType}`]
}
},
mounted() {
@ -62,14 +74,16 @@ export default {
}
</script>
<style lang="scss">
.preview-wrapper{
.preview-wrapper {
height: 100%;
width:100%;
width: 100%;
padding: 10px;
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;

View File

@ -0,0 +1,23 @@
import Vue from "vue";
import OnlyOffice from "./index.vue";
const PreviewConstructor = Vue.extend(OnlyOffice);
const onlyOffice = options => {
const { path, type, title } = options;
if (!path) throw `path is requred.but ${path}`
const id = `OnlyOffice_${new Date().getTime()}`;
const instance = new PreviewConstructor();
instance.id = id;
instance.vm = instance.$mount();
if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el);
instance.vm.open(path, type, title);
instance.vm.$on("closed", () => {
instance.vm.docEditor = null
document.body.removeChild(instance.vm.$el);
instance.vm.$destroy();
});
return instance.vm;
}
export default onlyOffice;

View File

@ -0,0 +1,7 @@
import OnlyOffice from "./index.vue";
import onlyOffice from "./fun";
export default Vue => {
Vue.component(OnlyOffice.name, OnlyOffice);
Vue.prototype.$onlyOffice = onlyOffice;
};

View File

@ -0,0 +1,46 @@
<template>
<el-dialog v-if="visible" :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
custom-class="base-dialog-wrapper" @close="handleClose">
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
<iframe v-if="visible"
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${path}?onlyOffice_url=${onlyOffice_url}&type=${type}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
width="100%" height="99%" frameborder="0" crossorigin="anonymous" />
</div>
</el-dialog>
</template>
<script>
import DOCUMENTTYPE from "@/utils/onlyOffice_type.js"
export default {
name: "OnlyOffice",
data() {
return {
visible: false,
path: null,
type: null,
title: null,
documentType: null,
currentUser: zzSessionStorage.getItem('userName'),
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
};
},
methods: {
open(path, type, title) {
this.path = path;
this.type = type.toLowerCase();
this.documentType = DOCUMENTTYPE[`.${this.type}`]
this.title = title;
this.visible = true;
},
handleClose() {
this.$emit("closed");
},
},
};
</script>
<style lang="scss" scoped>
#placeholder {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,23 @@
import Vue from "vue";
import Video from "./index.vue";
const PreviewConstructor = Vue.extend(Video);
const video = options => {
const { path, type, title } = options;
if (!path) throw `path is requred.but ${path}`
const id = `OnlyOffice_${new Date().getTime()}`;
const instance = new PreviewConstructor();
instance.id = id;
instance.vm = instance.$mount();
if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el);
instance.vm.open(path, type, title);
instance.vm.$on("closed", () => {
instance.vm.docEditor = null
document.body.removeChild(instance.vm.$el);
instance.vm.$destroy();
});
return instance.vm;
}
export default video;

View File

@ -0,0 +1,7 @@
import Video from "./index.vue";
import video from "./fun";
export default Vue => {
Vue.component(Video.name, Video);
Vue.prototype.$video = video;
};

View File

@ -0,0 +1,38 @@
<template>
<el-dialog v-if="visible" :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
custom-class="base-dialog-wrapper" @close="handleClose">
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
<video :src="path" style="width: 100%;height: 99%;" autoplay controls controlsList="nodownload"></video>
</div>
</el-dialog>
</template>
<script>
export default {
name: "Video",
data() {
return {
visible: false,
path: null,
type: null,
title: null,
};
},
methods: {
open(path, type, title) {
this.path = this.OSSclientConfig.basePath + path;
this.title = title;
this.visible = true;
},
handleClose() {
this.$emit("closed");
},
},
};
</script>
<style lang="scss" scoped>
#placeholder {
width: 100%;
height: 100%;
}
</style>

View File

@ -149,6 +149,7 @@ export default {
return isShow
},
goBack() {
zzSessionStorage.removeItem('lastWorkbench')
this.$router.push({ path: '/trials/trials-list' })
},
selectTrials(v) {

View File

@ -1,21 +1,16 @@
<template>
<div class="criterion-form-item">
<div
v-if="!!question.QuestionName && question.ClinicalQuestionType==='group'"
style="font-weight: bold;font-size: 16px;margin: 5px 0px;margin-bottom: 10px"
>
{{ language==='en'?question.QuestionEnName:question.QuestionName }}
<div v-if="!!question.QuestionName && question.ClinicalQuestionType === 'group'"
style="font-weight: bold;font-size: 16px;margin: 5px 0px;margin-bottom: 10px">
{{ language === 'en' ? question.QuestionEnName : question.QuestionName }}
</div>
<div v-else-if="question.ClinicalQuestionType === 'summary'"
style="background:#f3f3f3;border-radius:4px;font-size: 12px;margin: 5px 0px;margin-bottom: 10px;font-size: 12px;padding: 10px">
{{ language === 'en' ? question.QuestionEnName : question.QuestionName }}
</div>
<div
v-else-if="question.ClinicalQuestionType==='summary'"
style="background:#f3f3f3;border-radius:4px;font-size: 12px;margin: 5px 0px;margin-bottom: 10px;font-size: 12px;padding: 10px"
>
{{ language==='en'?question.QuestionEnName:question.QuestionName }}
</div>
<div
v-else-if="question.ClinicalQuestionType==='table' && ((question.ClinicalQuestionShowEnum===1 && question.ParentTriggerValue === questionForm[question.ParentId].toString()) || question.ClinicalQuestionShowEnum===0)"
style="font-weight: bold;font-size: 14px;margin: 5px 0px;"
>
v-else-if="question.ClinicalQuestionType === 'table' && ((question.ClinicalQuestionShowEnum === 1 && question.ParentTriggerValue === questionForm[question.ParentId].toString()) || question.ClinicalQuestionShowEnum === 0)"
style="font-weight: bold;font-size: 14px;margin: 5px 0px;">
<div style="display: flex;justify-content: space-between;">
<span>
{{ question.QuestionName }}
@ -25,27 +20,17 @@
{{ $t('trials:readingUnit:qsList:title:add') }}
</el-button>
</div>
<el-table
:data="questionForm[question.Id]"
>
<el-table-column
v-for="item of question.TableQuestions"
:key="item.Id"
:prop="item.Id"
:label="item.QuestionName"
min-width="100"
show-overflow-tooltip
/>
<el-table-column
:label="$t('common:action:action')"
min-width="100"
show-overflow-tooltip
>
<el-table :data="questionForm[question.Id]">
<el-table-column v-for="item of question.TableQuestions" :key="item.Id" :prop="item.Id"
:label="item.QuestionName" min-width="100" show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" min-width="100" show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openAddTableCol(question, scope.$index)">
{{ $t('common:button:edit') }}
</el-button>
<el-button type="text" size="mini" v-if="scope.row.IsCurrentTaskAdd === 'True' || !question.IsCopyLesions || IsBaseline" @click="deleteTableCol(question, scope.$index)">
<el-button type="text" size="mini"
v-if="scope.row.IsCurrentTaskAdd === 'True' || !question.IsCopyLesions || IsBaseline"
@click="deleteTableCol(question, scope.$index)">
{{ $t('common:button:delete') }}
</el-button>
</template>
@ -54,187 +39,109 @@
</div>
<el-col v-else :span="12">
<el-form-item
v-if="(question.ClinicalQuestionShowEnum===1 && question.ParentTriggerValue === questionForm[question.ParentId].toString()) || question.ClinicalQuestionShowEnum===0"
:label="`${question.QuestionName}`"
:prop="question.Id"
:rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (question.RelevanceValue === questionForm[question.RelevanceId].toString()))) && question.ClinicalQuestionType !== 'summary' && question.ClinicalQuestionType!=='group' && question.ClinicalQuestionType!=='table',
message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']}
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
>
v-if="(question.ClinicalQuestionShowEnum === 1 && question.ParentTriggerValue === questionForm[question.ParentId].toString()) || question.ClinicalQuestionShowEnum === 0"
:label="`${question.QuestionName}`" :prop="question.Id" :rules="[
{
required: (question.IsRequired === 0 || (question.IsRequired === 1 && question.RelevanceId && (question.RelevanceValue === questionForm[question.RelevanceId].toString()))) && question.ClinicalQuestionType !== 'summary' && question.ClinicalQuestionType !== 'group' && question.ClinicalQuestionType !== 'table',
message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
}
]" :class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' ? 'uploadWrapper' : '']">
<!-- 输入框 -->
<el-input
v-if="question.ClinicalQuestionType==='input'"
v-model="questionForm[question.Id]"
<el-input v-if="question.ClinicalQuestionType === 'input'" v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2"
:max-length="question.MaxAnswerLength ? question.MaxAnswerLength : 200"
/>
:max-length="question.MaxAnswerLength ? question.MaxAnswerLength : 200" />
<!-- 多行文本输入框 -->
<el-input
v-if="question.ClinicalQuestionType==='textarea'"
v-model="questionForm[question.Id]"
type="textarea"
:max-length="question.MaxAnswerLength ? question.MaxAnswerLength : 200"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-input v-if="question.ClinicalQuestionType === 'textarea'" v-model="questionForm[question.Id]"
type="textarea" :max-length="question.MaxAnswerLength ? question.MaxAnswerLength : 200"
:autosize="{ minRows: 2, maxRows: 4 }" />
<!-- 下拉框 -->
<el-select
v-if="question.ClinicalQuestionType==='select'"
v-model="questionForm[question.Id]"
clearable
<el-select v-if="question.ClinicalQuestionType === 'select'" v-model="questionForm[question.Id]" clearable
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode"
@change="((val)=>{formItemChange(val, question)})"
>
@change="((val) => { formItemChange(val, question) })">
<template v-if="question.TableQuestionType === 1">
<el-option
v-for="item in organList"
:key="item.Id"
:label="item[question.DataTableColumn]"
:value="item[question.DataTableColumn]"
/>
<el-option v-for="item in organList" :key="item.Id" :label="item[question.DataTableColumn]"
:value="item[question.DataTableColumn]" />
</template>
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="item.value"
:label="item.label" />
</template>
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
<template
v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="item.value"
:label="item.label" />
</template>
<template v-else>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val.trim()"
/>
<el-option v-for="val in question.TypeValue.split('|')" :key="val" :label="val" :value="val.trim()" />
</template>
</el-select>
<!-- 日期 -->
<el-date-picker v-if="question.ClinicalQuestionType === 'time'" v-model="questionForm[question.Id]"
style="width: 200px" align="right" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" />
<!-- 单选 -->
<el-date-picker
v-if="question.ClinicalQuestionType === 'time'"
v-model="questionForm[question.Id]"
style="width: 200px"
align="right"
type="date"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
/>
<!-- 单选 -->
<el-radio-group
v-if="question.ClinicalQuestionType==='radio'"
v-model="questionForm[question.Id]"
@change="((val)=>{formItemChange(val, question)})"
>
<el-radio-group v-if="question.ClinicalQuestionType === 'radio'" v-model="questionForm[question.Id]"
@change="((val) => { formItemChange(val, question) })">
<template v-if="question.DictionaryCode">
<el-radio
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:label="item.value"
>
<el-radio v-for="item of $d[question.DictionaryCode]" :key="item.id" :label="item.value">
{{ item.label }}
</el-radio>
</template>
<template v-if="question.TypeValue">
<el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
<el-radio v-for="val in question.TypeValue.split('|')" :key="val" :label="val">
{{ val }}
</el-radio>
</template>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="question.ClinicalQuestionType==='checkbox' && questionForm[question.Id] !== ''"
v-model="questionForm[question.Id]"
>
<el-checkbox
v-for="val of question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
>
<el-checkbox-group v-if="question.ClinicalQuestionType === 'checkbox' && questionForm[question.Id] !== ''"
v-model="questionForm[question.Id]">
<el-checkbox v-for="val of question.TypeValue.split('|')" :key="val" :label="val" :value="val">
{{ val }}
</el-checkbox>
</el-checkbox-group>
<el-input
v-if="question.ClinicalQuestionType === 'number'"
:ref="question.Id"
v-model="questionForm[question.Id]"
type="number"
style="width: 200px"
:disabled="question.CustomCalculateMark > 0"
@input="limitInput($event, questionForm, question)"
>
<el-input v-if="question.ClinicalQuestionType === 'number'" :ref="question.Id"
v-model="questionForm[question.Id]" type="number" style="width: 200px"
:disabled="question.CustomCalculateMark > 0" @input="limitInput($event, questionForm, question)">
<template v-if="question.Unit" slot="append">{{ question.Unit }}</template>
</el-input>
<span v-if="question.CustomCalculateMark === 11 && question.ClinicalQuestionType === 'number'" v-show="questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] <= questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId]" style="margin-left: 10px">
{{ questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] }}~{{ questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId] }}
<span v-if="question.CustomCalculateMark === 11 && question.ClinicalQuestionType === 'number'"
v-show="questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] <= questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId]"
style="margin-left: 10px">
{{ questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] }}~{{
questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId] }}
</span>
<span v-if="question.CustomCalculateMark === 10 && question.ClinicalQuestionType === 'number' && questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId]" style="margin-left: 10px">
{{ questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] }}~{{ questionForm.CreateTime ? questionForm.CreateTime : parseTime(new Date(), '{y}-{m}-{d}') }}
<span
v-if="question.CustomCalculateMark === 10 && question.ClinicalQuestionType === 'number' && questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId]"
style="margin-left: 10px">
{{ questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] }}~{{ questionForm.CreateTime ?
questionForm.CreateTime : parseTime(new Date(), '{y}-{m}-{d}') }}
</span>
<!-- 生日不能大于截止日期 -->
<span v-if="question.CustomCalculateMark === 11 && question.ClinicalQuestionType === 'number'" v-show="questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] > questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId]" style="margin-left: 10px;font-size: 12px;color:#f66">
<span v-if="question.CustomCalculateMark === 11 && question.ClinicalQuestionType === 'number'"
v-show="questionForm[JSON.parse(question.CalculateQuestions)[0].TableQuestionId] > questionForm[JSON.parse(question.CalculateQuestions)[0].QuestionId]"
style="margin-left: 10px;font-size: 12px;color:#f66">
{{ $t('trials:components:clinicalDataQS:msg:birthDay') }}
</span>
</el-form-item>
</el-col>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<!-- eslint-disable vue/valid-v-for -->
<el-col v-for="(item) in question.Childrens" v-if="question.Childrens && question.Childrens.length>0 && question.ClinicalQuestionType !== 'table'" :span="['group', 'summary', 'table'].includes(item.ClinicalQuestionType) || item.Childrens.length > 0 ? 24 : 12">
<QuestionFormItem
:key="item.Id"
:question="item"
:question-form="questionForm"
:trial-clinical-id="trialClinicalId"
@formItemNumberChange="formItemNumberChange"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
<el-col v-for="(item) in question.Childrens" :key="item.Id"
v-if="question.Childrens && question.Childrens.length > 0 && question.ClinicalQuestionType !== 'table'"
:span="['group', 'summary', 'table'].includes(item.ClinicalQuestionType) || item.Childrens.length > 0 ? 24 : 12">
<QuestionFormItem :key="item.Id" :question="item" :question-form="questionForm"
:trial-clinical-id="trialClinicalId" @formItemNumberChange="formItemNumberChange"
@setFormItemData="setFormItemData" @resetFormItemData="resetFormItemData" />
</el-col>
<el-dialog
v-if="addOrEdit.visible"
class="my_dialog"
:visible.sync="addOrEdit.visible"
:close-on-click-modal="false"
:title="addOrEdit.title"
width="400px"
append-to-body
>
<el-form
ref="tableQsForm"
v-loading="loading"
size="small"
:model="QuestionsForm"
>
<QuestionTableFormItem
v-for="(item) in QuestionsList"
:key="item.Id"
:question="item"
:question-form="QuestionsForm"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
<el-dialog v-if="addOrEdit.visible" class="my_dialog" :visible.sync="addOrEdit.visible"
:close-on-click-modal="false" :title="addOrEdit.title" width="400px" append-to-body>
<el-form ref="tableQsForm" v-loading="loading" size="small" :model="QuestionsForm">
<QuestionTableFormItem v-for="(item) in QuestionsList" :key="item.Id" :question="item"
:question-form="QuestionsForm" @setFormItemData="setFormItemData" @resetFormItemData="resetFormItemData" />
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
<el-form-item>
<!-- 取消 -->
<el-button
size="small"
type="primary"
@click="addOrEdit.visible = false"
>
<el-button size="small" type="primary" @click="addOrEdit.visible = false">
{{ $t('common:button:cancel') }}
</el-button>
<!-- 保存 -->
@ -282,7 +189,7 @@ export default {
},
data() {
return {
addOrEdit: { visible: false, title: '', id: null, index: 0},
addOrEdit: { visible: false, title: '', id: null, index: 0 },
fileList: [],
accept: '.png,.jpg,.jpeg',
imgVisible: false,
@ -406,8 +313,6 @@ export default {
})
break
case 6:
console.log(this.questionForm[o.QuestionId])
console.log(this.questionForm)
this.questionForm[o.QuestionId].forEach((q, qi) => {
if (qi === 0) {
num = parseFloat(q[o.TableQuestionId])
@ -450,11 +355,16 @@ export default {
}
break
case 11:
if (parseFloat(this.getCurrentAgeByBirthDate2(this.questionForm[o.TableQuestionId], this.questionForm[o.QuestionId])) > 0) {
num = parseFloat(this.getCurrentAgeByBirthDate2(this.questionForm[o.TableQuestionId], this.questionForm[o.QuestionId]))
if (parseFloat(this.getCurrentAgeByBirthDate(this.questionForm[o.TableQuestionId])) > 0) {
num = parseFloat(this.getCurrentAgeByBirthDate(this.questionForm[o.TableQuestionId]))
} else {
num = 0
}
// if (parseFloat(this.getCurrentAgeByBirthDate2(this.questionForm[o.TableQuestionId], this.questionForm[o.QuestionId])) > 0) {
// num = parseFloat(this.getCurrentAgeByBirthDate2(this.questionForm[o.TableQuestionId], this.questionForm[o.QuestionId]))
// } else {
// num = 0
// }
break
}
} else {
@ -501,12 +411,10 @@ export default {
try {
if (isTable) {
this.calculationList.forEach((v, i) => {
console.log(v, i)
var find = v.CalculateQuestionList.filter(o => {
return o.QuestionId === questionId
})
// findnumber
console.log('find', find)
if (find) {
var num = this.logic(v)
if (num !== false) {
@ -520,7 +428,6 @@ export default {
return o.TableQuestionId === questionId
})
// findnumber
console.log('find', find)
// findnumber
if (find) {
var num = this.logic(v)
@ -591,40 +498,47 @@ export default {
}
</script>
<style lang="scss" scoped>
.my_dialog{
.criterion-form-item{
>>>.el-form-item__content{
.my_dialog {
.criterion-form-item {
::v-deep .el-form-item__content {
width: auto;
}
}
}
.el-col-12 .el-col-12{
.el-col-12 .el-col-12 {
width: 100%;
}
.criterion-form-item{
.el-form-item{
.criterion-form-item {
.el-form-item {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.el-input{
width:100%;
.el-input {
width: 100%;
}
.mb{
.mb {
margin-bottom: 0px;
}
.disabled{
>>>.el-upload--picture-card {
.disabled {
::v-deep .el-upload--picture-card {
display: none;
}
}
.uploadWrapper{
.uploadWrapper {
display: flex;
flex-direction: column;
align-items: flex-start;
}
}
.clearfix:after{
.clearfix:after {
content: '';
display: table;
clear: both;

View File

@ -222,7 +222,7 @@ export default {
<style lang="scss" scoped>
.my_dialog{
.criterion-form-item{
>>>.el-form-item__content{
::v-deep .el-form-item__content{
width: auto;
}
}
@ -233,7 +233,7 @@ export default {
flex-direction: row;
align-items: flex-start;
}
>>>.el-form-item__content{
::v-deep .el-form-item__content{
width: 500px;
}
.el-input{
@ -243,7 +243,7 @@ export default {
margin-bottom: 0px;
}
.disabled{
>>>.el-upload--picture-card {
::v-deep .el-upload--picture-card {
display: none;
}
}

View File

@ -1,42 +1,28 @@
<template>
<div v-loading="loading">
<QuestionsForm
v-if="clinicalUploadType === 2"
:data="data"
:trial-clinical-id="trialClinicalId"
:is-viewer="isViewer"
:visit-id="visitId"
:subject-id="subjectId"
:open-type="openType"
:system-clinical-id="systemClinicalId"
:trial-id="trialId"
:reading-id="readingId"
:clinical-form-id="clinicalFormId"
:clinical-data-level="clinicalDataLevel"
@close="close"
></QuestionsForm>
<uploadClinicalData v-else :subject-visit-id="subjectVisitId" :data="data" :enum-type="0" :allow-add-or-edit="true" @getList="() => {}">
<QuestionsForm v-if="clinicalUploadType === 2" :data="data" :trial-clinical-id="trialClinicalId"
:is-viewer="isViewer" :visit-id="visitId" :subject-id="subjectId" :open-type="openType"
:system-clinical-id="systemClinicalId" :trial-id="trialId" :reading-id="readingId"
:clinical-form-id="clinicalFormId" :clinical-data-level="clinicalDataLevel" @close="close"></QuestionsForm>
<uploadClinicalData v-else :subject-visit-id="subjectVisitId" :data="data" :enum-type="0" :allow-add-or-edit="true"
@getList="() => { }">
</uploadClinicalData>
<div class="base-dialog-footer" v-if="!isViewer && openType !== 'look' && [0, 1].includes(clinicalDataLevel)" style="text-align:right;margin-top:10px;">
<div class="base-dialog-footer" v-if="!isViewer && openType !== 'look' && [0, 1].includes(clinicalDataLevel)"
style="text-align:right;margin-top:10px;">
<!-- 保存 -->
<el-button size="small" type="primary" @click="submitClinicalForm">
{{ $t('common:button:submit') }}
</el-button>
</div>
<!-- 临床数据签名框 -->
<el-dialog
v-if="signVisible"
:visible.sync="signVisible"
:close-on-click-modal="false"
width="600px"
append-to-body
custom-class="base-dialog-wrapper"
>
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px" append-to-body
custom-class="base-dialog-wrapper">
<div slot="title">
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${currentUser})` }}</span>
</div>
<SignForm ref="signForm" :sign-code-enum="signCode" :subject-visit-id="subjectVisitId" @closeDialog="closeSignDialog" />
<SignForm ref="signForm" :sign-code-enum="signCode" :subject-visit-id="subjectVisitId"
@closeDialog="closeSignDialog" />
</el-dialog>
</div>
</template>
@ -49,7 +35,7 @@ import uploadClinicalData from './components/uploadClinicalData'
import const_ from '@/const/sign-code'
export default {
name: "index",
name: "index",
components: { QuestionsForm, uploadClinicalData, SignForm },
methods: {
submitClinicalForm() {
@ -83,7 +69,7 @@ name: "index",
this.close()
}).catch((res) => {
this.$refs['signForm'].btnLoading = false
})
})
},
},
data() {
@ -148,7 +134,7 @@ name: "index",
},
data: {
type: Object,
default: () => {}
default: () => { }
},
trialClinicalId: {
type: String,
@ -166,6 +152,4 @@ name: "index",
}
</script>
<style scoped>
</style>
<style scoped></style>

View File

@ -1,39 +1,19 @@
<template>
<el-dialog
:visible.sync="visible"
:fullscreen="true"
:close-on-click-modal="false"
:before-close="beforeClose"
:append-to-body="true"
v-loading="btnLoading"
class="downloadDicomAndNonedicom"
>
<el-dialog :visible.sync="visible" :fullscreen="true" :close-on-click-modal="false" :before-close="beforeClose"
:append-to-body="true" v-loading="btnLoading" class="downloadDicomAndNonedicom">
<span slot="title">{{ title }}</span>
<div class="top">
<span>{{ $t('download:top:title') }}</span>
<div class="btnBox">
<el-button
type="primary"
size="mini"
v-if="hasDicom"
@click.stop="getIRReadingDownloadStudyInfo('dicom')"
>
<el-button type="primary" size="mini" v-if="hasDicom" @click.stop="getIRReadingDownloadStudyInfo('dicom')">
{{ $t('download:button:downloadDicom') }}
</el-button>
<el-button
type="primary"
size="mini"
v-if="hasNonedicom"
@click.stop="getIRReadingDownloadStudyInfo('noneDicom')"
>
<el-button type="primary" size="mini" v-if="hasNonedicom"
@click.stop="getIRReadingDownloadStudyInfo('noneDicom')">
{{ $t('download:button:downloadNonedicom') }}
</el-button>
<el-button
type="primary"
size="mini"
v-if="hasDicom || hasNonedicom"
@click.stop="getIRReadingDownloadStudyInfo('all')"
>
<el-button type="primary" size="mini" v-if="hasDicom || hasNonedicom"
@click.stop="getIRReadingDownloadStudyInfo('all')">
{{ $t('download:button:downloadAll') }}
</el-button>
</div>
@ -43,16 +23,9 @@
<div v-html="$t('download:tip:message')"></div>
</div>
<!--上传列表@selection-change="handleSelectionChange"-->
<el-table
ref="dicomFilesTable"
v-adaptive="{ bottomOffset: 85 }"
height="100"
:data="list"
:loading="loading"
class="dicomFiles-table"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
>
<el-table ref="dicomFilesTable" v-adaptive="{ bottomOffset: 85 }" height="100" :data="list" :loading="loading"
class="dicomFiles-table" @sort-change="handleSortByColumn"
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
<!-- <el-table-column
type="selection"
width="55"
@ -60,50 +33,28 @@
/> -->
<el-table-column type="index" width="40" />
<!--受试者-->
<el-table-column
:label="$t('download:table:subjectCode')"
min-width="130"
prop="SubjectCode"
show-overflow-tooltip
/>
<el-table-column :label="$t('download:table:subjectCode')" min-width="130" prop="SubjectCode"
show-overflow-tooltip />
<!--任务名称-->
<el-table-column
:label="$t('download:table:taskName')"
min-width="130"
show-overflow-tooltip
prop="TaskBlindName"
sortable="custom"
/>
<el-table-column :label="$t('download:table:taskName')" min-width="130" show-overflow-tooltip prop="TaskBlindName"
sortable="custom" />
<!--检查类型-->
<el-table-column
:label="$t('download:table:studyType')"
min-width="130"
show-overflow-tooltip
prop="IsDicom"
sortable="custom"
>
<el-table-column :label="$t('download:table:studyType')" min-width="130" show-overflow-tooltip prop="IsDicom"
sortable="custom">
<template slot-scope="scope">
<span>{{ $fd('IsDicom', scope.row.IsDicom) }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('download:table:orginalStudyListNum')"
min-width="150"
show-overflow-tooltip
>
<el-table-column :label="$t('download:table:orginalStudyListNum')" min-width="150" show-overflow-tooltip>
<template slot-scope="scope">
<el-button
v-if="
(scope.row.IsDicom &&
scope.row.DicomStudyList &&
scope.row.DicomStudyList.length >= 1) ||
(!scope.row.IsDicom &&
scope.row.NoneDicomStudyList &&
scope.row.NoneDicomStudyList.length >= 1)
"
type="text"
@click="handleOpenDialog(scope.row)"
>
<el-button v-if="
(scope.row.IsDicom &&
scope.row.DicomStudyList &&
scope.row.DicomStudyList.length >= 1) ||
(!scope.row.IsDicom &&
scope.row.NoneDicomStudyList &&
scope.row.NoneDicomStudyList.length >= 1)
" type="text" @click="handleOpenDialog(scope.row)">
<span>{{
scope.row.IsDicom
? scope.row.DicomStudyList.length
@ -113,37 +64,19 @@
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
fixed="right"
width="150"
>
<el-table-column :label="$t('common:action:action')" fixed="right" width="150">
<template slot-scope="scope">
<!--预览--->
<el-button
circle
icon="el-icon-view"
:title="$t('download:button:preview')"
@click.stop="preview(scope.row)"
/>
<el-button circle icon="el-icon-view" :title="$t('download:button:preview')"
@click.stop="preview(scope.row)" />
<!--下载--->
<el-button
circle
icon="el-icon-download"
:title="$t('download:button:download')"
@click.stop="getIRReadingDownloadStudyInfo('one', scope.row)"
/>
<el-button circle icon="el-icon-download" :title="$t('download:button:download')"
@click.stop="getIRReadingDownloadStudyInfo('one', scope.row)" />
</template>
</el-table-column>
</el-table>
<study-view
v-if="model_cfg.visible"
:model_cfg="model_cfg"
:modelList="modelList"
:bodyPart="bodyPart"
:IsDicom="IsDicom"
:visitTaskId="modelTaskId"
/>
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :modelList="modelList" :bodyPart="bodyPart"
:IsDicom="IsDicom" :visitTaskId="modelTaskId" />
</el-dialog>
</template>
<script>
@ -358,7 +291,8 @@ export default {
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
}
if (this.IsReadingTaskViewInOrder === 0) {
name = `${list[0].TaskBlindName}.zip`
// name = `${list[0].TaskBlindName}.zip`
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
}
list.forEach((data) => {
if (data.StudyList && data.StudyList.length > 0) {
@ -370,11 +304,9 @@ export default {
series.InstancePathList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}/${
data.TaskBlindName
}/${this.$fd('IsDicom', true)}/${
study.StudyCode
}/${fileName}`,
name: `${data.SubjectCode}/${data.TaskBlindName
}/${this.$fd('IsDicom', true)}/${study.StudyCode
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
if (this.IsReadingTaskViewInOrder === 0) {
@ -500,10 +432,12 @@ export default {
justify-content: space-between;
margin: 10px 0;
}
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}

View File

@ -92,6 +92,7 @@ export default {
try {
if (!this.form.userRoleId)
return this.$message.warning(this.$t('toggleRole:ruleMessage:select'))
zzSessionStorage.removeItem('lastWorkbench')
this.$emit('save', this.form.userRoleId)
} catch (err) {
console.log(err)
@ -111,11 +112,11 @@ export default {
margin: auto;
}
/deep/ .el-radio__original {
::v-deep .el-radio__original {
display: none !important; /* 隐藏原生 radio 输入,但仍然允许交互 */
}
/deep/.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled)
::v-deep.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled)
.el-radio__inner {
box-shadow: none !important;
}

View File

@ -4,123 +4,63 @@
<span>{{ $t('upload:dicom:title') }}</span>
<div class="tip">
<i class="el-icon-warning-outline"></i>
<div
v-html="$t(`upload:dicom:tip:message${isReadingTaskViewInOrder}`)"
></div>
<div v-html="$t(`upload:dicom:tip:message${isReadingTaskViewInOrder}`)"></div>
</div>
</div>
<!--检查列表-->
<el-table :data="list" style="width: 100%" height="300" :loading="loading">
<!--受试者-->
<el-table-column
prop="SubjectCode"
:label="$t('upload:dicom:table:subjectCode')"
/>
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" />
<!--任务名称-->
<el-table-column
prop="TaskBlindName"
:label="$t('upload:dicom:table:taskBlindName')"
/>
<el-table-column prop="TaskBlindName" :label="$t('upload:dicom:table:taskBlindName')" />
<!--原始检查数-->
<el-table-column
prop="OrginalStudyList"
:label="$t('upload:dicom:table:orginalStudyListNum')"
>
<el-table-column prop="OrginalStudyList" :label="$t('upload:dicom:table:orginalStudyListNum')">
<template slot-scope="scope">
<el-button
v-if="
scope.row.OrginalStudyList &&
scope.row.OrginalStudyList.length >= 1
"
type="text"
@click="handleOpenDialog(scope.row, 'OrginalStudyList')"
>
<el-button v-if="
scope.row.OrginalStudyList &&
scope.row.OrginalStudyList.length >= 1
" type="text" @click="handleOpenDialog(scope.row, 'OrginalStudyList')">
<span>{{ scope.row.OrginalStudyList.length }}</span>
</el-button>
<span v-else>0</span>
</template>
</el-table-column>
<!--后处理检查数-->
<el-table-column
prop="UploadStudyList"
:label="$t('upload:dicom:table:uploadStudyListNum')"
>
<el-table-column prop="UploadStudyList" :label="$t('upload:dicom:table:uploadStudyListNum')">
<template slot-scope="scope">
<el-button
v-if="
scope.row.UploadStudyList && scope.row.UploadStudyList.length >= 1
"
type="text"
@click="handleOpenDialog(scope.row, 'UploadStudyList', true)"
>
<el-button v-if="
scope.row.UploadStudyList && scope.row.UploadStudyList.length >= 1
" type="text" @click="handleOpenDialog(scope.row, 'UploadStudyList', true)">
<span>{{ scope.row.UploadStudyList.length }}</span>
</el-button>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
fixed="right"
width="180"
>
<el-table-column :label="$t('common:action:action')" fixed="right" width="180">
<template slot-scope="scope">
<div class="btnBox">
<!--上传--->
<form
id="inputForm"
:ref="`uploadForm_${scope.row.Id}`"
enctype="multipart/form-data"
>
<form id="inputForm" :ref="`uploadForm_${scope.row.Id}`" enctype="multipart/form-data">
<div class="form-group" style="margin-right: 10px">
<div
:id="`directoryInputWrapper_${scope.row.Id}`"
class="btn btn-link file-input"
>
<el-button
circle
icon="el-icon-upload2"
:disabled="btnLoading"
:loading="btnLoading"
:title="$t('upload:dicom:button:upload')"
/>
<input
:title="$t('upload:dicom:button:upload')"
type="file"
:name="`file_${scope.row.VisitTaskId}`"
:ref="`pathClear_${scope.row.VisitTaskId}`"
:disabled="btnLoading"
webkitdirectory
multiple
@change="
<div :id="`directoryInputWrapper_${scope.row.Id}`" class="btn btn-link file-input">
<el-button circle icon="el-icon-upload2" :disabled="btnLoading" :loading="btnLoading"
:title="$t('upload:dicom:button:upload')" />
<input :title="$t('upload:dicom:button:upload')" type="file" :name="`file_${scope.row.VisitTaskId}`"
:ref="`pathClear_${scope.row.VisitTaskId}`" :disabled="btnLoading" webkitdirectory multiple @change="
($event) => beginScanFiles($event, scope.row.VisitTaskId)
"
/>
" />
</div>
</div>
</form>
<!--预览--->
<el-button
circle
icon="el-icon-view"
:disabled="
!scope.row.UploadStudyList ||
scope.row.UploadStudyList.length <= 0
"
@click.stop="handleViewReadingImages(scope.row)"
:title="$t('upload:dicom:button:preview')"
/>
<el-button circle icon="el-icon-view" :disabled="!scope.row.UploadStudyList ||
scope.row.UploadStudyList.length <= 0
" @click.stop="handleViewReadingImages(scope.row)" :title="$t('upload:dicom:button:preview')" />
<!--删除--->
<el-button
circle
:disabled="
!scope.row.UploadStudyList ||
scope.row.UploadStudyList.length <= 0 ||
scope.row.ReadingTaskState === 2
"
icon="el-icon-delete"
:title="$t('upload:dicom:button:delete')"
@click.stop="remove(scope.row)"
/>
<el-button circle :disabled="!scope.row.UploadStudyList ||
scope.row.UploadStudyList.length <= 0 ||
scope.row.ReadingTaskState === 2
" icon="el-icon-delete" :title="$t('upload:dicom:button:delete')" @click.stop="remove(scope.row)" />
</div>
</template>
</el-table-column>
@ -134,38 +74,19 @@
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
<div class="form-group">
<div id="directoryInputWrapper" class="btn btn-link file-input">
<el-button
type="primary"
:disabled="btnLoading"
:loading="btnLoading"
size="mini"
>
<el-button type="primary" :disabled="btnLoading" :loading="btnLoading" size="mini">
{{ $t('upload:dicom:button:batchUpload') }}
</el-button>
<input
type="file"
name="file"
ref="pathClear"
:disabled="btnLoading"
webkitdirectory
multiple
title=""
@change="beginScanFiles($event)"
/>
<input type="file" name="file" ref="pathClear" :disabled="btnLoading" webkitdirectory multiple title=""
@change="beginScanFiles($event)" />
</div>
</div>
</form>
</div>
</div>
<!--上传列表-->
<el-table
ref="dicomFilesTable"
v-adaptive="{ bottomOffset: 80 }"
height="100"
:data="uploadQueues"
class="dicomFiles-table"
@selection-change="handleSelectionChange"
>
<el-table ref="dicomFilesTable" v-adaptive="{ bottomOffset: 80 }" height="100" :data="uploadQueues"
class="dicomFiles-table" @selection-change="handleSelectionChange">
<el-table-column type="index" width="40" />
<el-table-column min-width="200" show-overflow-tooltip>
<template slot="header">
@ -182,28 +103,21 @@
<div style="line-height: 15px">
<div>
<div>
<span v-if="scope.row.dicomInfo.accNumber"
><span style="font-weight: 500">Acc:</span>
{{ scope.row.dicomInfo.accNumber }}</span
>
<span v-if="scope.row.dicomInfo.accNumber"><span style="font-weight: 500">Acc:</span>
{{ scope.row.dicomInfo.accNumber }}</span>
<span v-else style="color: #f44336">N/A</span>
</div>
<div style="display: inline-block; margin-right: 2px">
<span v-if="scope.row.dicomInfo.modality.length > 0">
{{ scope.row.dicomInfo.modality.join('、') }},</span
>
{{ scope.row.dicomInfo.modality.join('、') }},</span>
<span v-else style="color: #f44336">N/A,</span>
</div>
<div style="display: inline-block; margin-right: 2px">
<span v-if="scope.row.seriesList.length"
>{{ scope.row.seriesList.length }} Series,</span
>
<span v-if="scope.row.seriesList.length">{{ scope.row.seriesList.length }} Series,</span>
<span v-else style="color: #f44336">N/A,</span>
</div>
<div style="display: inline-block">
<span v-if="scope.row.fileList.length"
>{{ scope.row.fileList.length }} Instances</span
>
<span v-if="scope.row.fileList.length">{{ scope.row.fileList.length }} Instances</span>
<span v-else style="color: #f44336">N/A</span>
</div>
</div>
@ -217,8 +131,7 @@
</div>
<div style="display: inline-block">
<span v-if="scope.row.dicomInfo.description">
{{ scope.row.dicomInfo.description }}</span
>
{{ scope.row.dicomInfo.description }}</span>
<span v-else style="color: #f44336">N/A</span>
</div>
</div>
@ -242,16 +155,12 @@
<template slot-scope="scope">
<div style="line-height: 15px">
<div>
<span v-if="scope.row.dicomInfo.patientId"
><span style="font-weight: 500">PID: </span
>{{ scope.row.dicomInfo.patientId }}</span
>
<span v-if="scope.row.dicomInfo.patientId"><span style="font-weight: 500">PID: </span>{{
scope.row.dicomInfo.patientId }}</span>
<span v-else style="color: #f44336">N/A</span>
</div>
<div>
<span
:class="[scope.row.dicomInfo.patientName ? '' : 'colorOfRed']"
>
<span :class="[scope.row.dicomInfo.patientName ? '' : 'colorOfRed']">
{{
scope.row.dicomInfo.patientName
? scope.row.dicomInfo.patientName
@ -260,9 +169,7 @@
</span>
</div>
<div>
<span
:class="[scope.row.dicomInfo.patientSex ? '' : 'colorOfRed']"
>
<span :class="[scope.row.dicomInfo.patientSex ? '' : 'colorOfRed']">
{{
scope.row.dicomInfo.patientSex
? scope.row.dicomInfo.patientSex
@ -270,9 +177,7 @@
}},
</span>
<span
:class="[scope.row.dicomInfo.patientAge ? '' : 'colorOfRed']"
>
<span :class="[scope.row.dicomInfo.patientAge ? '' : 'colorOfRed']">
{{
scope.row.dicomInfo.patientAge
? scope.row.dicomInfo.patientAge
@ -280,11 +185,9 @@
}},
</span>
<span
:class="[
scope.row.dicomInfo.patientBirthDate ? '' : 'colorOfRed',
]"
>
<span :class="[
scope.row.dicomInfo.patientBirthDate ? '' : 'colorOfRed',
]">
{{
scope.row.dicomInfo.patientBirthDate
? scope.row.dicomInfo.patientBirthDate
@ -295,114 +198,74 @@
</div>
</template>
</el-table-column>
<el-table-column
:label="$t('trials:uploadDicomList:table:failedFileCount')"
min-width="150"
show-overflow-tooltip
>
<el-table-column :label="$t('trials:uploadDicomList:table:failedFileCount')" min-width="150"
show-overflow-tooltip>
<template slot-scope="scope">
<el-progress
color="#409eff"
:percentage="
(
(scope.row.dicomInfo.uploadFileSize * 100) /
scope.row.dicomInfo.fileSize
).toFixed(2) * 1
"
/>
<el-progress color="#409eff" :percentage="(
(scope.row.dicomInfo.uploadFileSize * 100) /
(scope.row.dicomInfo.fileSize ? scope.row.dicomInfo.fileSize : 1)
).toFixed(2) * 1
" />
<span>
{{ $t('trials:uploadDicomList:table:uploadNow')
}}{{ scope.row.dicomInfo.failedFileCount }}/{{
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>
</el-table-column>
<el-table-column
:label="$t('trials:uploadDicomList:table:status')"
min-width="140"
show-overflow-tooltip
>
<el-table-column :label="$t('trials:uploadDicomList:table:status')" min-width="140" show-overflow-tooltip>
<template slot-scope="scope">
<span
v-if="
!scope.row.dicomInfo.failedFileCount &&
!scope.row.dicomInfo.isInit
"
>
{{ $t('trials:uploadDicomList:table:status1') }}</span
>
<span
style="color: #409eff"
v-else-if="
!scope.row.dicomInfo.failedFileCount &&
scope.row.dicomInfo.isInit &&
btnLoading
"
>{{ $t('trials:uploadDicomList:table:status2') }}</span
>
<span
style="color: #409eff"
v-else-if="
scope.row.dicomInfo.failedFileCount <
scope.row.dicomInfo.fileCount && !scope.row.uploadState.record
"
>{{ $t('trials:uploadDicomList:table:status2') }}</span
>
<span
style="color: #2cc368"
v-else-if="
scope.row.dicomInfo.failedFileCount ===
scope.row.dicomInfo.fileCount
"
>{{ $t('trials:uploadDicomList:table:status3') }}</span
>
<span
style="color: #f66"
v-else-if="
scope.row.uploadState.record &&
scope.row.uploadState.record.fileCount === 0
"
>{{ $t('trials:uploadDicomList:table:status5') }}</span
>
<span v-if="
!scope.row.dicomInfo.failedFileCount &&
!scope.row.dicomInfo.isInit
">
{{ $t('trials:uploadDicomList:table:status1') }}</span>
<span style="color: #409eff" v-else-if="
!scope.row.dicomInfo.failedFileCount &&
scope.row.dicomInfo.isInit &&
btnLoading
">{{ $t('trials:uploadDicomList:table:status2') }}</span>
<span style="color: #409eff" v-else-if="
scope.row.dicomInfo.failedFileCount <
scope.row.dicomInfo.fileCount && !scope.row.uploadState.record
">{{ $t('trials:uploadDicomList:table:status2') }}</span>
<span style="color: #2cc368" v-else-if="
scope.row.dicomInfo.failedFileCount ===
scope.row.dicomInfo.fileCount
">{{ $t('trials:uploadDicomList:table:status3') }}</span>
<span style="color: #f66" v-else-if="
scope.row.uploadState.record &&
scope.row.uploadState.record.fileCount === 0
">{{ $t('trials:uploadDicomList:table:status5') }}</span>
<span style="color: #f66" v-else>{{
$t('trials:uploadDicomList:table:Failed')
}}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('trials:uploadDicomList:table:record')"
min-width="140"
show-overflow-tooltip
>
<el-table-column :label="$t('trials:uploadDicomList:table:record')" min-width="140" show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip placement="top" v-if="scope.row.uploadState.record">
<div slot="content">
<div style="max-height: 500px; overflow-y: auto">
{{ $t('trials:uploadDicomList:table:Existed') }}:
<div v-if="scope.row.uploadState.record.Existed.length">
<div
v-for="item of scope.row.uploadState.record.Existed"
:key="item"
style="font-size: 12px; color: #baa72a"
>
<div v-for="item of scope.row.uploadState.record.Existed" :key="item"
style="font-size: 12px; color: #baa72a">
{{ item }}
</div>
</div>
<div v-else>&nbsp;</div>
{{ $t('trials:uploadDicomList:table:Uploaded') }}:
<div v-if="scope.row.uploadState.record.Uploaded.length">
<div
v-for="item of scope.row.uploadState.record.Uploaded"
:key="item"
style="font-size: 12px; color: #24b837"
>
<div v-for="item of scope.row.uploadState.record.Uploaded" :key="item"
style="font-size: 12px; color: #24b837">
{{ item }}
</div>
</div>
@ -410,11 +273,8 @@
<br />
{{ $t('trials:uploadDicomList:table:Failed') }}:
<div v-if="scope.row.uploadState.record.Failed.length">
<div
v-for="item of scope.row.uploadState.record.Failed"
:key="item"
style="font-size: 12px; color: #f66"
>
<div v-for="item of scope.row.uploadState.record.Failed" :key="item"
style="font-size: 12px; color: #f66">
{{ item }}
</div>
</div>
@ -438,16 +298,8 @@
</template>
</el-table-column>
</el-table>
<study-view
v-if="model_cfg.visible"
:model_cfg="model_cfg"
:IsDicom="true"
:bodyPart="bodyPart"
:modelList="modelList"
:isUpload="openIsUpload"
:TrialModality="TrialModality"
@getList="getList"
/>
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :IsDicom="true" :bodyPart="bodyPart"
:modelList="modelList" :isUpload="openIsUpload" :TrialModality="TrialModality" @getList="getList" />
</div>
</template>
<script>
@ -795,7 +647,7 @@ export default {
})
var validFilesCount = 0
for (var i = 0; i < checkFiles.length; ++i) {
;(function (index) {
; (function (index) {
p = p.then(function () {
if (
checkFiles[index].name.toUpperCase().indexOf('DICOMDIR') === -1
@ -834,6 +686,7 @@ export default {
var studyUid = data.string('x0020000d')
if (!studyUid) return resolve()
var pixelDataElement = data.elements.x7fe00010
if (!pixelDataElement && modality !== 'SR') return resolve()
var studyIndex = 0
while (
studyIndex < scope.uploadQueues.length &&
@ -936,19 +789,19 @@ export default {
) {
++instanceIndex
}
if (instanceIndex >= fileList.length) {
fileList.push({
instanceUid: instanceUid,
file: file,
})
}
scope.uploadQueues[studyIndex].dicomInfo.fileCount = fileList.length
scope.uploadQueues[studyIndex].dicomInfo.fileSize = fileList.reduce(
(prev, next) => {
return prev + next.file.size
},
0
)
// if (instanceIndex >= fileList.length) {
// fileList.push({
// instanceUid: instanceUid,
// file: file,
// })
// }
// scope.uploadQueues[studyIndex].dicomInfo.fileCount = fileList.length
// scope.uploadQueues[studyIndex].dicomInfo.fileSize = fileList.reduce(
// (prev, next) => {
// return prev + next.file.size
// },
// 0
// )
var seriesUid = data.string('x0020000e')
var seriesList = scope.uploadQueues[studyIndex].seriesList
@ -1046,6 +899,19 @@ export default {
}
instanceList.push(instanceItem)
}
if (instanceIndex >= fileList.length) {
fileList.push({
instanceUid: instanceUid,
file: file,
})
}
scope.uploadQueues[studyIndex].dicomInfo.fileCount = fileList.length
scope.uploadQueues[studyIndex].dicomInfo.fileSize = fileList.reduce(
(prev, next) => {
return prev + next.file.size
},
0
)
resolve()
} catch (error) {
console.log(error)
@ -1266,16 +1132,14 @@ export default {
dicomInfo.failedFileCount++
Record.FileCount++
} else {
let path = `/${params.trialId}/Image/${
params.subjectId
}/${params.subjectVisitId}/${
dicomInfo.visitTaskId
}/${scope.getGuid(
dicomInfo.studyUid +
let path = `/${params.trialId}/Image/${params.subjectId
}/${params.subjectVisitId}/${dicomInfo.visitTaskId
}/${scope.getGuid(
dicomInfo.studyUid +
v.seriesUid +
o.instanceUid +
params.trialId
)}`
)}`
if (scope.isClose) return
let res = await dcmUpload(
{
@ -1308,7 +1172,7 @@ export default {
o.imageColumns,
o.imageRows
)
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.png`
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
let OSSclient = scope.OSSclient
let seriesRes = await OSSclient.put(
thumbnailPath,
@ -1421,7 +1285,7 @@ export default {
v.instanceList[0].imageColumns,
v.instanceList[0].imageRows
)
let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.png`
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
let OSSclient = scope.OSSclient
try {
let seriesRes = await OSSclient.put(thumbnailPath, blob)
@ -1499,8 +1363,8 @@ export default {
return new Promise((resolve) => {
cornerstone.loadImage(imageId).then(async (image) => {
let canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
canvas.width = (width * 60) / height
canvas.height = 60
if (image) {
cornerstone.renderToCanvas(canvas, image)
// Canvas PNG
@ -1546,16 +1410,19 @@ export default {
align-items: center;
justify-content: space-between;
}
.btnBox,
.form-group {
display: flex;
align-items: center;
}
#inputForm .file-input {
position: relative;
overflow: hidden;
display: inline-block;
}
#inputForm .file-input input[type='file'] {
position: absolute;
top: 0;
@ -1565,10 +1432,12 @@ export default {
opacity: 0;
cursor: pointer;
}
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}

View File

@ -8,65 +8,29 @@
</div>
</div>
<!--检查列表-->
<el-table
:data="list"
style="width: 100%"
v-adaptive="{ bottomOffset: 60 }"
:loading="loading"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
>
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
<!--受试者-->
<el-table-column
prop="SubjectCode"
:label="$t('upload:nonedicom:table:subject')"
/>
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')" />
<!--任务名称-->
<el-table-column
prop="TaskBlindName"
:label="$t('upload:nonedicom:table:taskName')"
sortable="custom"
/>
<el-table-column prop="TaskBlindName" :label="$t('upload:nonedicom:table:taskName')" sortable="custom" />
<!--检查类型-->
<el-table-column
prop="Modality"
:label="$t('upload:nonedicom:table:molityType')"
sortable="custom"
>
<el-table-column prop="Modality" :label="$t('upload:nonedicom:table:molityType')" sortable="custom">
</el-table-column>
<!--检查部位-->
<el-table-column
prop="BodyPart"
:label="$t('upload:nonedicom:table:bodyPart')"
sortable="custom"
/>
<el-table-column prop="BodyPart" :label="$t('upload:nonedicom:table:bodyPart')" sortable="custom" />
<!--原文件数-->
<el-table-column
prop="FileCount"
:label="$t('upload:nonedicom:table:fileCount')"
>
<el-table-column prop="FileCount" :label="$t('upload:nonedicom:table:fileCount')">
<template slot-scope="scope">
<el-popover
v-if="scope.row.FileCount"
trigger="click"
placement="bottom"
>
<el-popover v-if="scope.row.FileCount" trigger="click" placement="bottom">
<el-table :data="scope.row.FileList" height="300" size="small">
<!-- 文件名称 -->
<el-table-column
prop="FileName"
:label="$t('trials:audit:table:nonDicomsFileName')"
width="200"
/>
<el-table-column
prop="FileSize"
:label="$t('trials:audit:table:nonDicomsFileSize')"
width="100"
>
<el-table-column prop="FileName" :label="$t('trials:audit:table:nonDicomsFileName')" width="200" />
<el-table-column prop="FileSize" :label="$t('trials:audit:table:nonDicomsFileSize')" width="100">
<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>
@ -74,27 +38,13 @@
<el-table-column :label="$t('common:action:action')" width="120">
<template slot-scope="files">
<!-- 预览 -->
<viewer
:ref="files.row.Path"
style="margin: 0 10px"
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
>
<el-button
circle
icon="el-icon-view"
:title="$t('upload:nonedicom:button:preview')"
:disabled="
files.row.FileType &&
files.row.FileType.indexOf('zip') >= 0
"
@click.native.prevent="previewFile(files.row)"
/>
<img
v-show="false"
crossorigin="anonymous"
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
alt="Image"
/>
<viewer :ref="files.row.Path" style="margin: 0 10px"
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]">
<el-button circle icon="el-icon-view" :title="$t('upload:nonedicom:button:preview')" :disabled="files.row.FileType &&
files.row.FileType.indexOf('zip') >= 0
" @click.native.prevent="previewFile(files.row)" />
<img v-show="false" crossorigin="anonymous" :src="`${OSSclientConfig.basePath}${files.row.Path}`"
alt="Image" />
</viewer>
</template>
</el-table-column>
@ -109,36 +59,17 @@
</template>
</el-table-column>
<!--后处理文件数-->
<el-table-column
prop="UploadedFileCount"
:label="$t('upload:nonedicom:table:uploadFileCount')"
>
<el-table-column prop="UploadedFileCount" :label="$t('upload:nonedicom:table:uploadFileCount')">
<template slot-scope="scope">
<el-popover
v-if="scope.row.UploadedFileCount"
trigger="click"
placement="bottom"
>
<el-table
:data="scope.row.UploadedFileList"
height="300"
size="small"
>
<el-popover v-if="scope.row.UploadedFileCount" trigger="click" placement="bottom">
<el-table :data="scope.row.UploadedFileList" height="300" size="small">
<!-- 文件名称 -->
<el-table-column
prop="FileName"
:label="$t('trials:audit:table:nonDicomsFileName')"
width="200"
/>
<el-table-column
prop="FileSize"
:label="$t('trials:audit:table:nonDicomsFileSize')"
width="100"
>
<el-table-column prop="FileName" :label="$t('trials:audit:table:nonDicomsFileName')" width="200" />
<el-table-column prop="FileSize" :label="$t('trials:audit:table:nonDicomsFileSize')" width="100">
<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>
@ -146,27 +77,13 @@
<el-table-column :label="$t('common:action:action')" width="120">
<template slot-scope="files">
<!-- 预览 -->
<viewer
:ref="files.row.Path"
style="margin: 0 10px"
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
>
<el-button
circle
icon="el-icon-view"
:title="$t('upload:nonedicom:button:preview')"
:disabled="
files.row.FileType &&
files.row.FileType.indexOf('zip') >= 0
"
@click.native.prevent="previewFile(files.row)"
/>
<img
v-show="false"
crossorigin="anonymous"
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
alt="Image"
/>
<viewer :ref="files.row.Path" style="margin: 0 10px"
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]">
<el-button circle icon="el-icon-view" :title="$t('upload:nonedicom:button:preview')" :disabled="files.row.FileType &&
files.row.FileType.indexOf('zip') >= 0
" @click.native.prevent="previewFile(files.row)" />
<img v-show="false" crossorigin="anonymous" :src="`${OSSclientConfig.basePath}${files.row.Path}`"
alt="Image" />
</viewer>
</template>
</el-table-column>
@ -180,75 +97,34 @@
<span v-else>{{ scope.row.UploadedFileCount }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
fixed="right"
width="180"
>
<el-table-column :label="$t('common:action:action')" fixed="right" width="180">
<template slot-scope="scope">
<!--预览--->
<el-button
circle
:disabled="scope.row.UploadedFileCount <= 0"
icon="el-icon-view"
:title="$t('upload:nonedicom:button:preview')"
@click.stop="handlePreviewNoneDicomFiles(scope.row)"
/>
<el-button circle :disabled="scope.row.UploadedFileCount <= 0" icon="el-icon-view"
:title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" />
<!--上传--->
<el-button
circle
icon="el-icon-upload2"
:title="$t('upload:nonedicom:button:upload')"
@click.native.prevent="handleUpload(scope.row)"
/>
<el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')"
@click.native.prevent="handleUpload(scope.row)" />
<!--删除--->
<el-button
:disabled="
scope.row.UploadedFileCount <= 0 ||
scope.row.ReadingTaskState === 2
"
circle
icon="el-icon-delete"
:title="$t('upload:nonedicom:button:delete')"
@click.stop="remove(scope.row)"
/>
<el-button :disabled="scope.row.UploadedFileCount <= 0 ||
scope.row.ReadingTaskState === 2
" circle icon="el-icon-delete" :title="$t('upload:nonedicom:button:delete')"
@click.stop="remove(scope.row)" />
</template>
</el-table-column>
</el-table>
<!-- 预览单个图像 -->
<el-dialog
v-if="imgObj.visible"
:visible.sync="imgObj.visible"
:title="$t('upload:nonedicom:dialogTitle:preview')"
append-to-body
width="565px"
>
<div
v-loading="imgObj.loading"
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<el-image
:src="`${OSSclientConfig.basePath}${imgObj.url}`"
crossorigin="anonymous"
fit="fit"
style="height: 500px; width: 500px"
@error="imgObj.loading = false"
@load="imgObj.loading = false"
/>
<el-dialog v-if="imgObj.visible" :visible.sync="imgObj.visible" :title="$t('upload:nonedicom:dialogTitle:preview')"
append-to-body width="565px">
<div v-loading="imgObj.loading" class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
<el-image :src="`${OSSclientConfig.basePath}${imgObj.url}`" crossorigin="anonymous" fit="fit"
style="height: 500px; width: 500px" @error="imgObj.loading = false" @load="imgObj.loading = false" />
</div>
</el-dialog>
<!-- 上传非dicom文件 -->
<el-dialog
v-if="uploadVisible"
:visible.sync="uploadVisible"
:close-on-click-modal="false"
:title="$t('trials:uploadNonDicoms:dialogTitle:upload')"
width="800px"
append-to-body
custom-class="base-dialog-wrapper"
@close="resetFileDiaolg"
>
<el-dialog v-if="uploadVisible" :visible.sync="uploadVisible" :close-on-click-modal="false"
:title="$t('trials:uploadNonDicoms:dialogTitle:upload')" width="800px" append-to-body
custom-class="base-dialog-wrapper" @close="resetFileDiaolg">
<!-- 多文件上传 -->
<form id="inputForm" ref="uploadForm">
<el-divider content-position="left">{{
@ -256,33 +132,15 @@
}}</el-divider>
<div class="form-group">
<div class="upload" style="margin-right: 10px">
<input
multiple="multiple"
webkitdirectory=""
directory
accept="*/*"
type="file"
name="uploadFolder"
class="select-file"
title=""
@change="beginScanFiles($event)"
v-if="!btnLoading"
/>
<input multiple="multiple" webkitdirectory="" directory accept="*/*" type="file" name="uploadFolder"
class="select-file" title="" @change="beginScanFiles($event)" v-if="!btnLoading" />
<div class="btn-select">
{{ $t('trials:uploadNonDicoms:button:selectFolder') }}
</div>
</div>
<div class="upload">
<input
class="select-file"
multiple=""
:accept="faccept.join(',')"
type="file"
name="uploadFile"
title=""
@change="beginScanFiles($event)"
v-if="!btnLoading"
/>
<input class="select-file" multiple="" :accept="faccept.join(',')" type="file" name="uploadFile" title=""
@change="beginScanFiles($event)" v-if="!btnLoading" />
<div class="btn-select">
{{ $t('trials:uploadNonDicoms:button:select') }}
</div>
@ -293,82 +151,46 @@
</div>
</form>
<!-- 文件列表 -->
<el-table
ref="filesTable"
:data="fileList"
class="dicomFiles-table"
height="300"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
:selectable="(row, index) => row.status !== 2 && !btnLoading"
/>
<el-table ref="filesTable" :data="fileList" class="dicomFiles-table" height="300"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="(row, index) => row.status !== 2 && !btnLoading" />
<el-table-column type="index" width="50" />
<!-- 文件名称 -->
<el-table-column
prop="name"
:label="$t('trials:uploadNonDicoms:table:fileName')"
min-width="100"
/>
<el-table-column prop="name" :label="$t('trials:uploadNonDicoms:table:fileName')" min-width="100" />
<!-- 文件大小 -->
<el-table-column
prop="size"
:label="$t('trials:uploadNonDicoms:table:fileSize')"
>
<el-table-column prop="size" :label="$t('trials:uploadNonDicoms:table:fileSize')">
<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`
: '0MB'
}}</span>
</template>
</el-table-column>
<!-- 文件类型 -->
<el-table-column
prop="type"
:label="$t('trials:uploadNonDicoms:table:fileType')"
/>
<el-table-column prop="type" :label="$t('trials:uploadNonDicoms:table:fileType')" />
<!-- 上传状态 -->
<el-table-column
prop="status"
:label="$t('trials:uploadNonDicoms:table:uploadStatus')"
min-width="100"
>
<el-table-column prop="status" :label="$t('trials:uploadNonDicoms:table:uploadStatus')" min-width="100">
<template slot-scope="scope">
<el-tag
:type="['warning', 'info', 'success', 'danger'][scope.row.status]"
v-if="scope.row.status || scope.row.status === 0"
>{{ $fd('NoneDicomUploadStatus', scope.row.status) }}
<el-tag :type="['warning', 'info', 'success', 'danger'][scope.row.status]"
v-if="scope.row.status || scope.row.status === 0">{{ $fd('NoneDicomUploadStatus', scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('trials:uploadNonDicoms:table:failedFileCount')"
min-width="150"
show-overflow-tooltip
>
<el-table-column :label="$t('trials:uploadNonDicoms:table:failedFileCount')" min-width="150"
show-overflow-tooltip>
<template slot-scope="scope">
<el-progress
color="#409eff"
:percentage="
((scope.row.uploadFileSize * 100) / scope.row.size).toFixed(2) *
1
"
/>
<el-progress color="#409eff" :percentage="scope.row.size && scope.row.size > 0 ? ((scope.row.uploadFileSize * 100) / scope.row.size).toFixed(2) *
1
: ((scope.row.uploadFileSize * 100) / 1).toFixed(2) *
1
" />
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')">
<template slot-scope="scope">
<el-button
size="mini"
icon="el-icon-delete"
circle
:disabled="btnLoading"
:title="$t('trials:crcUpload:action:delete')"
@click="handleRemoveFile(scope.row)"
/>
<el-button size="mini" icon="el-icon-delete" circle :disabled="btnLoading"
:title="$t('trials:crcUpload:action:delete')" @click="handleRemoveFile(scope.row)" />
</template>
</el-table-column>
</el-table>
@ -376,13 +198,8 @@
<span style="margin-right: 10px">{{
$store.state.trials.uploadTip
}}</span>
<el-button
size="small"
type="primary"
:disabled="selectArr.length == 0"
:loading="btnLoading"
@click="beginUpload"
>
<el-button size="small" type="primary" :disabled="selectArr.length == 0" :loading="btnLoading"
@click="beginUpload">
{{ $t('trials:uploadNonDicoms:action:upload') }}
</el-button>
</div>
@ -588,7 +405,7 @@ export default {
)
}
})
.catch(() => {})
.catch(() => { })
},
resetUploadForm() {
this.$nextTick(() => {
@ -714,11 +531,10 @@ export default {
if (!this.uploadVisible) return
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
file.status = 1
let path = `/${this.$route.query.trialId}/TaskImage/${
this.currentRow.SubjectId
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
.substring(file.name.lastIndexOf('.'))
.toLocaleLowerCase()}`
let path = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
.substring(file.name.lastIndexOf('.'))
.toLocaleLowerCase()}`
file.curPath = path
const fileData = await this.fileToBlob(file.file)
let res = await this.fileToOss(path, fileData, file)
@ -772,7 +588,7 @@ export default {
(percentage, checkpoint, lastPer) => {
item.uploadFileSize += checkpoint.size * (percentage - lastPer)
if (item.uploadFileSize > file.fileSize) {
item.uploadFileSize = file.fileSize
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
}
}
)
@ -869,6 +685,7 @@ export default {
.top {
margin: 10px 0;
}
.upload {
display: inline-block;
height: 30px;
@ -883,6 +700,7 @@ export default {
background: #428bca;
border-color: #428bca;
color: #fff;
.select-file {
height: 30px;
width: 90px;
@ -893,6 +711,7 @@ export default {
opacity: 0;
font-size: 0;
}
.btn-select {
//
width: 90px;
@ -908,10 +727,12 @@ export default {
pointer-events: none; //pointer-events:none穿
}
}
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}

View File

@ -567,7 +567,7 @@ export default {
for (let i = 0; i < arr.length; i++) {
let dicom = arr[i];
if (dicom.StudyInstanceUid !== StudyInstanceUid) continue;
let thumbnailPath = `/${dicom.params.TrialId}/TaskImage/${dicom.params.SubjectId}/${dicom.params.VisitTaskId}/${dicom.StudyInstanceUid}/${dicom.SeriesInstanceUid}.png`;
let thumbnailPath = `/${dicom.params.TrialId}/TaskImage/${dicom.params.SubjectId}/${dicom.params.VisitTaskId}/${dicom.StudyInstanceUid}/${dicom.SeriesInstanceUid}.jpg`;
if (!studyObj[dicom.StudyId]) {
studyObj[dicom.StudyId] = {
StudyId: dicom.StudyId,

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -22,7 +22,7 @@
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
import variables from '@/styles/variables.module.scss'
export default {
components: { SidebarItem, Logo },

View File

@ -73,7 +73,7 @@ export default {
position: relative;
overflow: hidden;
width: 100%;
/deep/ {
::v-deep {
.el-scrollbar__bar {
bottom: 0px;
}

View File

@ -57,7 +57,7 @@ export default {
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
@import "~@/styles/variables.module.scss";
.app-wrapper {
@include clearfix;

View File

@ -54,6 +54,10 @@ import upload from '@/components/element-ui/upload'
Vue.use(upload)
import Preview from '@/components/Preview/index'
Vue.use(Preview)
import Onlyoffice from '@/components/Preview_onlyoffice/index'
Vue.use(Onlyoffice)
import Video from '@/components/Preview_video/index'
Vue.use(Video)
import MFA from '@/components/MFA/index'
Vue.use(MFA)
import FB from '@/components/feedBack/index'
@ -174,7 +178,7 @@ var _vm
async function VueInit() {
var params
var res
if (~window.location.href.indexOf('/readingDicoms') || ~window.location.href.indexOf('/noneDicomReading') || ~window.location.href.indexOf('/criterionquestions') || ~window.location.href.indexOf('/petct')) {
if (~window.location.href.indexOf('/readingDicoms') || ~window.location.href.indexOf('/noneDicomReading') || ~window.location.href.indexOf('/criterionquestions') || ~window.location.href.indexOf('/petct') || ~window.location.href.indexOf('/fusion')) {
params = $q('TrialReadingCriterionId')
res = await getBasicDataAllSelect(params)
} else if (~window.location.href.indexOf('/ecrfPreview')) {
@ -308,6 +312,11 @@ async function VueInit() {
text = text.replace(test, item.TrialName)
})
}
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
if (CompanyInfo && CompanyInfo.SystemShortName) {
let test = new RegExp('IRC', 'ig')
text = text.replace(test, CompanyInfo.SystemShortName)
}
// return i18n.t(key)
return text;
}
@ -461,8 +470,8 @@ async function VueInit() {
var my_username = zzSessionStorage.getItem('my_username')
var my_password = zzSessionStorage.getItem('my_password')
let my_userid = zzSessionStorage.getItem('userId')
let my_EMail = zzSessionStorage.getItem('my_EMail')
if (md5(_vm.unlock.my_password) === my_password && my_username === _vm.unlock.my_username) {
let my_EMail = zzSessionStorage.getItem('my_EMail') || ''
if (md5(_vm.unlock.my_password) === my_password && (my_username === _vm.unlock.my_username || my_EMail.toUpperCase() === vm.unlock.my_username.toUpperCase())) {
resetReadingRestTime().then(() => {
})
const closeLock = (_vm) => {

View File

@ -7,15 +7,15 @@ import 'nprogress/nprogress.css'
import { getToken, removeToken } from '@/utils/auth'
import Vue from 'vue'
import { OSSclient } from './utils/oss'
import WHITELIST from "./utils/whiteList"
import WHITELIST from './utils/whiteList'
import { getTrialExtralConfig } from '@/api/trials'
// import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false })
const whiteList = WHITELIST
store.state.trials.whiteList = whiteList;
router.beforeEach(async (to, from, next) => {
store.state.trials.whiteList = whiteList
router.beforeEach(async(to, from, next) => {
NProgress.start()
// 设置页面标题
// document.title = getPageTitle(to.meta.title) store.state.trials.whiteList.indexOf(to.path) === -1
@ -27,13 +27,13 @@ router.beforeEach(async (to, from, next) => {
to.query.trialId !==
store.state.trials.config.trialId
) {
let res = await getTrialExtralConfig({
TrialId: to.query.trialId,
const res = await getTrialExtralConfig({
TrialId: to.query.trialId
})
if (res.IsSuccess) {
store.dispatch('trials/setConfig', {
trialId: to.query.trialId,
...res.Result,
...res.Result
})
}
}
@ -45,13 +45,13 @@ router.beforeEach(async (to, from, next) => {
to.query.trialId !==
store.state.trials.config.trialId
) {
let res = await getTrialExtralConfig({
TrialId: to.query.trialId,
const res = await getTrialExtralConfig({
TrialId: to.query.trialId
})
if (res.IsSuccess) {
store.dispatch('trials/setConfig', {
trialId: to.query.trialId,
...res.Result,
...res.Result
})
}
}
@ -72,12 +72,12 @@ router.beforeEach(async (to, from, next) => {
NProgress.done()
} else if (from.path === '/researchForm') {
removeToken()
let lang = to.query.lang || zzSessionStorage.getItem('lang')
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else if (from.path === '/researchDetail_m') {
removeToken()
let lang = to.query.lang || zzSessionStorage.getItem('lang')
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else {
@ -107,7 +107,7 @@ router.beforeEach(async (to, from, next) => {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
if (to.path === '/researchLogin') {
let lang = to.query.lang || zzSessionStorage.getItem('lang')
const lang = to.query.lang || zzSessionStorage.getItem('lang')
const flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
if (flag) {
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
@ -123,11 +123,11 @@ router.beforeEach(async (to, from, next) => {
}
} else {
if (to.path === '/researchForm') {
let lang = to.query.lang || zzSessionStorage.getItem('lang')
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else if (to.path === '/researchDetail_m') {
let lang = to.query.lang || zzSessionStorage.getItem('lang')
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else if (to.path === '/ReviewersResearchForm') {

View File

@ -50,12 +50,23 @@ export const constantRoutes = [
component: () => import('@/views/login/index'),
hidden: true
},
// {
// path: '/test',
// component: () => import('@/views/test/index'),
// hidden: true
// },
{
path: '/resetpassword',
component: () => import('@/views/forgetpassword/index'),
name: 'Resetpassword',
hidden: true
},
{
path: '/trials/trials-panel/reading/readingTracking/ReadOrder',
component: () => import('@/views/trials/trials-panel/reading/read-order/index'),
name: 'ReadOrder',
hidden: true
},
{
path: '/recompose',
component: () => import('@/views/recompose/index'),
@ -139,6 +150,12 @@ export const constantRoutes = [
hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt')
},
{
path: '/fusion',
name: 'fusion',
hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/demo/index')
},
{
path: '/historyScreenshot',

View File

@ -1,7 +1,7 @@
// eslint-disable-next-line no-undef
module.exports = {
title: 'IRCIS',
title: 'IRC Imaging System',
/**
* @type {boolean} true | false

View File

@ -48,6 +48,10 @@ const getters = {
TotalNeedSignSystemDocCount: state => state.user.TotalNeedSignSystemDocCount,
TotalNeedSignTrialDocCount: state => state.user.TotalNeedSignTrialDocCount,
IsFirstSysDocNeedSign: state => state.user.IsFirstSysDocNeedSign,
TrialStatusStr: state => state.user.TrialStatusStr
TrialStatusStr: state => state.user.TrialStatusStr,
lastViewportTaskId: state => state.noneDicomReview.lastViewportTaskId,
currentTaskState: state => state.noneDicomReview.currentTaskState,
operateInfo: state => state.dicom3d.operateInfo,
deleteAnnotationIds: state => state.dicom3d.deleteAnnotationIds
}
export default getters

View File

@ -12,7 +12,8 @@ import trials from './modules/trials'
import financials from './modules/financials'
import reading from './modules/reading'
import lang from './modules/lang'
import noneDicomReview from './modules/noneDicomReview'
import dicom3d from './modules/dicom3d'
Vue.use(Vuex)
const store = new Vuex.Store({
@ -27,7 +28,9 @@ const store = new Vuex.Store({
trials,
financials,
reading,
lang
lang,
noneDicomReview,
dicom3d
},
getters
})

View File

@ -0,0 +1,28 @@
const getDefaultState = () => {
return {
operateInfo: [],
deleteAnnotationIds: []
}
}
const state = getDefaultState
const mutations = {
}
const actions = {
setOperateInfo({ state }, arr) {
state.operateInfo = arr
},
setDeleteAnnotationIds({ state }, arr) {
state.deleteAnnotationIds = arr
},
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@ -0,0 +1,28 @@
const getDefaultState = () => {
return {
lastViewportTaskId: null,
currentTaskState: 0
}
}
const state = getDefaultState
const mutations = {
}
const actions = {
setLastViewportTaskId({ state }, id) {
state.lastViewportTaskId = id
},
setCurrentTaskState({ state }, taskState) {
state.currentTaskState = taskState
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

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

View File

@ -1,4 +1,4 @@
@import "./variables.scss";
@import "./variables.module.scss";
@import "./mixin.scss";
@import "./transition.scss";
@import "./element-ui.scss";
@ -68,6 +68,12 @@ body .el-table th.gutter {
}
}
.text-ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.el-loading-mask {
background-color: rgba(255, 255, 255, 0.5);
}

View File

@ -71,29 +71,49 @@ $sideBarWidth: 200px;
border: none;
height: 100%;
width: 100% !important;
background-color: $menuBg;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
color: $menuText !important;
&:hover {
background-color: $menuHover !important;
color: $menuActiveText !important;
}
}
.is-active>.el-submenu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item {
.el-menu-item {
color: $menuText !important;
}
.el-menu-item:focus,
.el-menu-item:hover {
background-color: $subMenuBg !important;
color: $menuActiveText !important;
}
.el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $subMenuHover !important;
}
}
// &.nest-menu .el-submenu>.el-submenu__title,
// &.el-submenu .el-menu-item {
// min-width: $sideBarWidth !important;
// background-color: $subMenuBg !important;
// &:hover {
// background-color: $subMenuHover !important;
// }
// }
}
.hideSidebar {

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) {

View File

@ -34,7 +34,7 @@ export function parseTime(time, cFormat) {
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
return value.toString().padStart(2, '0')
})
return time_str
@ -51,12 +51,44 @@ export function param2Obj(url) {
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
)
}
export function deepClone(source, map = new WeakMap()) {
// 处理基本类型和函数(直接返回)
if (typeof source !== 'object' || source === null) {
return source;
}
// 处理循环引用
if (map.has(source)) {
return map.get(source);
}
// 创建新容器
const target = Array.isArray(source) ? [] : {};
map.set(source, target); // 记录克隆关系
// 克隆普通键值
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = deepClone(source[key], map);
}
}
// 克隆Symbol键值ES6+
const symbolKeys = Object.getOwnPropertySymbols(source);
for (const symKey of symbolKeys) {
if (source.propertyIsEnumerable(symKey)) {
target[symKey] = deepClone(source[symKey], map);
}
}
return target;
}

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;

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]]

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]]

View File

@ -0,0 +1,66 @@
let TYPES = ['word', 'cell', 'slide', 'pdf']
let DOCUMENTTYPE = {
'.doc': TYPES[0],
'.docm': TYPES[0],
'.docx': TYPES[0],
'.dot': TYPES[0],
'.dotm': TYPES[0],
'.dotx': TYPES[0],
'.epub': TYPES[0],
'.fb2': TYPES[0],
'.fodt': TYPES[0],
'.htm': TYPES[0],
'.html': TYPES[0],
'.mht': TYPES[0],
'.mhtml': TYPES[0],
'.odt': TYPES[0],
'.ott': TYPES[0],
'.pages': TYPES[0],
'.rtf': TYPES[0],
'.stw': TYPES[0],
'.sxw': TYPES[0],
'.txt': TYPES[0],
'.wps': TYPES[0],
'.wpt': TYPES[0],
'.xml': TYPES[0],
'.csv': TYPES[1],
'.et': TYPES[1],
'.ett': TYPES[1],
'.fods': TYPES[1],
'.numbers': TYPES[1],
'.ods': TYPES[1],
'.ots': TYPES[1],
'.sxc': TYPES[1],
'.xls': TYPES[1],
'.xlsb': TYPES[1],
'.xlsm': TYPES[1],
'.xlsx': TYPES[1],
'.xlt': TYPES[1],
'.xltm': TYPES[1],
'.xltx': TYPES[1],
'.xml': TYPES[1],
'.dps': TYPES[2],
'.dpt': TYPES[2],
'.fodp': TYPES[2],
'.key': TYPES[2],
'.odp': TYPES[2],
'.otp': TYPES[2],
'.pot': TYPES[2],
'.potm': TYPES[2],
'.potx': TYPES[2],
'.pps': TYPES[2],
'.ppsm': TYPES[2],
'.ppsx': TYPES[2],
'.ppt': TYPES[2],
'.pptm': TYPES[2],
'.pptx': TYPES[2],
'.sxi': TYPES[2],
'.djvu': TYPES[3],
'.docxf': TYPES[3],
'.oform': TYPES[3],
'.oxps': TYPES[3],
'.pdf': TYPES[3],
'.xps': TYPES[3]
}
export default DOCUMENTTYPE

View File

@ -41,7 +41,13 @@ async function ossGenerateSTS() {
let _vm = router.default.app
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
var objectItem = objectName.split('/')
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
0,
objectItem[objectItem.length - 1].lastIndexOf('.')
)}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring(
objectItem[objectItem.length - 1].lastIndexOf('.')
).toLocaleLowerCase()}`
objectName = objectItem.join('/')
}
let res = await OSSclient.put(objectName, object)
@ -78,7 +84,13 @@ async function ossGenerateSTS() {
let _vm = router.default.app
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
var objectItem = data.path.split('/')
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
0,
objectItem[objectItem.length - 1].lastIndexOf('.')
)}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring(
objectItem[objectItem.length - 1].lastIndexOf('.')
).toLocaleLowerCase()}`
data.path = objectItem.join('/')
}
let res = await customerHttp(OSSclient, data, progress);
@ -185,7 +197,13 @@ function uploadAWS(aws, data, progress) {
let _vm = router.default.app
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
var objectItem = data.path.split('/')
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
0,
objectItem[objectItem.length - 1].lastIndexOf('.')
)}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring(
objectItem[objectItem.length - 1].lastIndexOf('.')
).toLocaleLowerCase()}`
data.path = objectItem.join('/')
}
let bucketName = data.path.split("/")[1] || Vue.prototype.OSSclientConfig.bucket

View File

@ -189,8 +189,8 @@ const dicomToPng = (imageId, width, height) => {
return new Promise((resolve) => {
cornerstone.loadImage(imageId).then(async (image) => {
let canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
canvas.width = (width * 60) / height
canvas.height = 60
if (image) {
cornerstone.renderToCanvas(canvas, image);
// 将 Canvas 图像对象转换为 PNG 格式

View File

@ -50,7 +50,8 @@ service.interceptors.response.use(
const a = document.createElement('a')
// xls类型: application/vnd.ms-excel
// xlsx类型application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
const href = URL.createObjectURL(new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' }))
// const href = URL.createObjectURL(new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' }))
const href = URL.createObjectURL(new Blob([res], { type: response.headers['content-type'] }))
a.download = fileName
a.href = href
a.click()

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
})
@ -20,6 +21,8 @@ service.interceptors.request.use(
async config => {
path = router && router.app && router.app._route && router.app._route.path
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
// config.baseURL = process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api'
config.headers['Self-Referer'] = window.location.href
var language = zzSessionStorage.getItem('lang')
config.headers['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
config.headers['TimeZoneId'] = moment.tz.guess()

View File

@ -20,7 +20,7 @@ function zipFiles(zipName, files) {
ctrl.close();
} else {
let { name, url } = fileInfo.value;
url = decodeUtf8(url);
// url = decodeUtf8(url); // 待定,可能做过特殊处理
return fetch(url).then(res => {
ctrl.enqueue({
name,
@ -58,7 +58,7 @@ async function updateFile(file, name) {
try {
store.dispatch('trials/setUnLock', true)
const fileOutputStream = streamSaver.createWriteStream(name);
file = decodeUtf8(file);
// file = decodeUtf8(file);
let res = await fetch(file);
res.body.pipeTo(fileOutputStream).then(() => {
store.dispatch('trials/setUnLock', true)

View File

@ -17,7 +17,7 @@
</el-form-item>
<el-form-item label="是否内部角色: " prop="IsInternal">
<el-radio-group v-model="form.IsInternal">
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{ item.label }}</el-radio>
<el-radio v-for="item of $d.YesOrNo" :key="`IsInternal${item.value}`" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>

View File

@ -27,7 +27,7 @@ export default {
}
</script>
<style lang="scss" scoped>
/deep/ .el-collapse-item__header{
::v-deep .el-collapse-item__header{
background-color: #e9eef1;
padding: 0 10px;
}

View File

@ -195,7 +195,7 @@ export default {
}
</script>
<style lang="scss" scoped>
/deep/ .el-collapse-item__header{
::v-deep .el-collapse-item__header{
background-color: #e9eef1;
padding: 0 10px;
}

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>

View File

@ -52,10 +52,14 @@
</div>
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
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"
@ -66,11 +70,27 @@
>
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
<div>
{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}
</div>
<div v-if="showDelete">
<span>{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="instance.IsDeleted"
size="mini"
@change="changeInstanceDeleteStatus($event, item, instance)"
/>
<span style="margin-left:10px;">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="instance.IsReading"
size="mini"
@change="changeInstanceReadingStatus($event, item, instance)"
/>
</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" @click="popperClick(seriesList, item)" />
</el-popover>
</div>
</div>
@ -138,13 +158,13 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer'
import { getStudyInfo, getSeriesList } from '@/api/reading'
import { getInstanceList, getPatientSeriesList, setSeriesStatus } from '@/api/trials'
import { getInstanceList, getPatientSeriesList, setSeriesStatus, setInstanceStatus } from '@/api/trials'
import requestPoolManager from '@/utils/request-pool'
import store from '@/store'
import { changeURLStatic } from '@/utils/history.js'
import metaDataProvider from '@/utils/metaDataProvider'
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 })
var config = {
maxWebWorkers: 4,
startWebWorkersOnDemand: true,
@ -296,7 +316,8 @@ export default {
tpCode: this.tpCode,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
isExistMutiFrames: item.IsExistMutiFrames,
isShowPopper: false
})
})
this.seriesList = seriesList
@ -355,7 +376,8 @@ export default {
tpCode: this.tpCode,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
isExistMutiFrames: item.IsExistMutiFrames,
isShowPopper: false
})
})
this.seriesList = seriesList
@ -384,8 +406,8 @@ export default {
if (!res.Result || (res.Result && res.Result.length === 0)) return
var seriesInstanceUid = res.Result[0].SeriesInstanceUid
var sliceThickness = res.Result[0].SliceThickness
var isReading = res.Result[0].IsReading
var isDeleted = res.Result[0].IsDeleted
var isReading = res.OtherInfo.IsReading
var isDeleted = res.OtherInfo.IsDeleted
var seriesList = []
var imageIds = []
let isExistMutiFrames = false
@ -403,7 +425,7 @@ export default {
imageIds.push(path)
imageId = path
}
instanceInfoList.push({ Id: instance.Id, InstanceNumber: instance.InstanceNumber, NumberOfFrames: instance.NumberOfFrames, Path: instance.Path, ImageId: imageId })
instanceInfoList.push({ Id: instance.Id, InstanceNumber: instance.InstanceNumber, NumberOfFrames: instance.NumberOfFrames, Path: instance.Path, ImageId: imageId, IsDeleted: instance.IsDeleted, IsReading: instance.IsReading })
})
seriesList.push({
trialId,
@ -424,7 +446,8 @@ export default {
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: isExistMutiFrames
isExistMutiFrames: isExistMutiFrames,
isShowPopper: false
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
@ -573,7 +596,8 @@ export default {
hasLabel: seriesInfo.HasLabel,
keySeries: seriesInfo.KeySeries,
loadStatus: false,
imageloadedArr: []
imageloadedArr: [],
isShowPopper: false
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
@ -671,6 +695,81 @@ export default {
this.loading = false
}
},
async changeInstanceReadingStatus(callback, series, instance) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading')
instance.IsReading = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
instance.IsReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !instance.IsReading))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = instance.IsReading ? 1 : 2
this.loading = true
try {
const res = await setInstanceStatus(series.trialId, series.subjectVisitId, series.seriesId, instance.Id, state)
this.loading = false
if (res.IsSuccess) {
instance.IsReading = !instance.IsReading
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
this.loading = false
}
},
async changeInstanceDeleteStatus(callback, series, instance) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
instance.IsDeleted = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
instance.IsDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !instance.IsDeleted))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = instance.IsDeleted ? 5 : 4
this.loading = true
try {
const res = await setInstanceStatus(series.trialId, series.subjectVisitId, series.seriesId, instance.Id, state)
this.loading = false
if (res.IsSuccess) {
instance.IsDeleted = !instance.IsDeleted
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
this.loading = false
}
},
popperClick(seriesList, series) {
for (let i = 0; i < seriesList.length; i++) {
if (seriesList[i].isShowPopper) {
seriesList[i].isShowPopper = false
}
}
series.isShowPopper = !series.isShowPopper
},
loadAllImages() {
const seriesIndex = this.seriesList.findIndex(i => i.loadStatus === false)
if (seriesIndex === -1) return
@ -948,8 +1047,8 @@ export default {
background: #d0d0d0;
}
.frame_content{
height: 50px;
padding: 5px;
/* height: 50px; */
padding: 10px;
display: flex;
justify-content: flex-start;
color: #ddd;

View File

@ -59,34 +59,56 @@
<div>#{{ series.seriesNumber }}</div>
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
v-model="series.isShowPopper"
placement="right-start"
trigger="manual"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(index,series, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
<div style="text-align: right;">
<i class="el-icon-circle-close" style="font-size: 20px;cursor: pointer;color:#ddd;" @click="series.isShowPopper = false" />
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
<div class="frame_list">
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(index,series, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>
{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}
</div>
<div v-if="showDelete">
<span>{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="instance.IsDeleted"
size="mini"
@change="changeInstanceDeleteStatus($event, series, instance)"
/>
<span style="margin-left:10px;">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="instance.IsReading"
size="mini"
@change="changeInstanceReadingStatus($event, series, instance)"
/>
</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" @click="popperClick(studyList, series)" />
</el-popover>
</div>
@ -143,7 +165,7 @@
</div>
</div>
</el-tab-pane>
<el-tab-pane :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper" v-if="!visitTaskId">
<el-tab-pane v-if="!visitTaskId" :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper">
<div class="viewerSidethumbinner">
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
<el-collapse-item v-for="(study,studyIndex) in relationStudyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
@ -196,8 +218,8 @@
<div v-else>#{{ seriesItem.seriesNumber }}</div>
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
placement="right-start"
trigger="click"
popper-class="instance_frame_wrapper"
>
<div class="frame_list">
@ -260,13 +282,13 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer'
import { getVisitStudyList, getAllRelationStudyList, getSeriesList } from '@/api/reading'
import { setSeriesStatus } from '@/api/trials'
import { setSeriesStatus, setInstanceStatus } from '@/api/trials'
import { getTaskUploadedDicomStudyList } from '@/api/reading'
import requestPoolManager from '@/utils/request-pool'
import store from '@/store'
import { changeURLStatic } from '@/utils/history.js'
import metaDataProvider from '@/utils/metaDataProvider'
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 })
// import * as cornerstoneTools from 'cornerstone-tools'
var config = {
maxWebWorkers: 4,
@ -348,7 +370,7 @@ export default {
let res = null
if (this.page === 'upload') {
res = await getTaskUploadedDicomStudyList({ visitTaskId: this.visitTaskId })
} else if (this.page === 'download'){
} else if (this.page === 'download') {
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading, this.visitTaskId)
} else {
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading)
@ -399,7 +421,8 @@ export default {
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: series.IsExistMutiFrames
isExistMutiFrames: series.IsExistMutiFrames,
isShowPopper: false
})
})
data.SeriesList = seriesList
@ -595,6 +618,83 @@ export default {
this.loading = false
}
},
async changeInstanceReadingStatus(callback, series, instance) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading')
instance.IsReading = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
instance.IsReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !instance.IsReading))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = instance.IsReading ? 1 : 2
this.loading = true
try {
const res = await setInstanceStatus(series.trialId, series.subjectVisitId, series.seriesId, instance.Id, state)
this.loading = false
if (res.IsSuccess) {
instance.IsReading = !instance.IsReading
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
this.loading = false
}
},
async changeInstanceDeleteStatus(callback, series, instance) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
instance.IsDeleted = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
instance.IsDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !instance.IsDeleted))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = instance.IsDeleted ? 5 : 4
this.loading = true
try {
const res = await setInstanceStatus(series.trialId, series.subjectVisitId, series.seriesId, instance.Id, state)
this.loading = false
if (res.IsSuccess) {
instance.IsDeleted = !instance.IsDeleted
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
this.loading = false
}
},
popperClick(studyList, series) {
for (let i = 0; i < studyList.length; i++) {
for (let j = 0; j < studyList[i].SeriesList.length; j++) {
if (studyList[i].SeriesList[j].isShowPopper) {
studyList[i].SeriesList[j].isShowPopper = false
}
}
}
series.isShowPopper = !series.isShowPopper
},
// Tab
async handleTabClick(tab, event) {
if (tab.name === 'relation-study' && this.relationStudyList.length <= 0) {
@ -671,7 +771,8 @@ export default {
keySeries: item.KeySeries,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
isExistMutiFrames: item.IsExistMutiFrames,
isShowPopper: false
})
})
scope.relationStudyList[index].seriesCount = seriesList.length
@ -978,9 +1079,21 @@ export default {
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: 5px;
/* height: 50px; */
padding: 10px;
display: flex;
justify-content: flex-start;
color: #ddd;

View File

@ -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"
@ -60,7 +60,7 @@
</el-form-item>
<el-form-item v-if="form.Id !== ''" label="是否废除: ">
<el-radio-group v-model="form.IsDeleted">
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{ item.label }}</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 label="描述">

View File

@ -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
},

View File

@ -78,7 +78,7 @@
<el-form-item v-if="form.Id !== ''" label="是否废除: ">
<el-radio-group v-model="form.IsDeleted">
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{ item.label }}</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 label="描述">

View File

@ -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;"
@ -57,14 +59,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,7 +78,7 @@
<el-table-column
prop="Name"
label="文件名称"
:label="$t('dictionary:attachment:label:name')"
show-overflow-tooltip
sortable="custom"
/>
@ -92,12 +94,12 @@
</el-table-column>
<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"
>
@ -108,18 +110,18 @@
</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="$t('common:action:action')">
<template slot-scope="scope">
<el-button
type="text"
@click="handleDownload(scope.row)"
>
下载
{{ $t('common:button:download') }}
</el-button>
<!-- <el-button
type="text"

View File

@ -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

View File

@ -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
},

View File

@ -1,100 +1,45 @@
<template>
<el-form
ref="sysAttachmentFrom"
v-loading="loading"
:model="form"
label-width="190px"
size="small"
:rules="rules"
class="upload-temporary-file"
>
<el-form ref="sysAttachmentFrom" v-loading="loading" :model="form" label-width="190px" size="small" :rules="rules"
class="upload-temporary-file">
<div class="base-dialog-body">
<el-form-item
:label="$t('dictionary:signature:form:FileTypeId')"
prop="FileTypeId"
>
<el-select
v-model="form.FileTypeId"
style="width: 100%"
size="small"
filterable
>
<el-option
v-for="item of dictionaryList.Sys_Document"
:key="item.Id"
:label="item.Value"
:value="item.Id"
/>
<el-form-item :label="$t('dictionary:signature:form:FileTypeId')" prop="FileTypeId">
<el-select v-model="form.FileTypeId" style="width: 100%" size="small" filterable>
<el-option v-for="item of dictionaryList.Sys_Document" :key="item.Id" :label="item.Value" :value="item.Id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('dictionary:signature:form:File')">
<div class="upload-container">
<el-upload
class="upload-demo"
action
accept=".pdf"
:before-upload="beforeUpload"
:http-request="handleUploadFile"
:on-preview="handlePreview"
:on-remove="handleRemoveFile"
:show-file-list="true"
:file-list="fileList"
:limit="1"
:on-exceed="handleExceed"
:disabled="form.Type === ''"
>
<el-button
size="small"
type="primary"
:disabled="form.FileTypeId === ''"
:loading="btnLoading"
>{{ $t('common:button:check') }}</el-button
>
<el-upload class="upload-demo" action accept=".pdf,.mp4" :before-upload="beforeUpload"
:http-request="handleUploadFile" :on-preview="handlePreview" :on-remove="handleRemoveFile"
:show-file-list="true" :file-list="fileList" :limit="1" :on-exceed="handleExceed"
:disabled="form.Type === ''">
<el-button size="small" type="primary" :disabled="form.FileTypeId === ''" :loading="btnLoading">{{
$t('common:button:check') }}</el-button>
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
({{ $t('trials:signature:label:mustBepdf') }})
</span>
</el-upload>
</div>
</el-form-item>
<el-form-item
:label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
prop="NeedConfirmedUserTypeIdList"
>
<el-select
v-model="form.NeedConfirmedUserTypeIdList"
style="width: 100%"
multiple
>
<el-option
v-for="item of userTypeOptions"
:key="item.Id"
:label="item.UserTypeShortName"
:value="item.Id"
/>
<el-form-item :label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
prop="NeedConfirmedUserTypeIdList">
<el-select v-model="form.NeedConfirmedUserTypeIdList" style="width: 100%" multiple>
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName" :value="item.Id" />
</el-select>
</el-form-item>
<el-form-item
:label="$t('dictionary:signature:form:DocUserSignType')"
prop="DocUserSignType"
>
<el-switch
v-model="form.DocUserSignType"
:active-value="1"
:inactive-value="0"
>
<el-form-item :label="$t('dictionary:signature:form:DocUserSignType')" prop="DocUserSignType">
<el-switch v-model="form.DocUserSignType" :active-value="1" :inactive-value="0">
</el-switch>
</el-form-item>
<el-form-item
:label="$t('dictionary:signature:form:SignViewMinimumMinutes')"
prop="SignViewMinimumMinutes"
>
<el-input-number
v-model="form.SignViewMinimumMinutes"
controls-position="right"
:min="1"
:max="50"
/>
<el-form-item :label="$t('dictionary:signature:form:SignViewMinimumMinutes')" prop="SignViewMinimumMinutes">
<el-input-number v-model="form.SignViewMinimumMinutes" controls-position="right" :min="1" :max="50" />
</el-form-item>
<el-form-item :label="$t('dictionary:signature:form:CurrentStaffTrainDays')" prop="CurrentStaffTrainDays">
<el-input-number v-model="form.CurrentStaffTrainDays" controls-position="right" :min="0" :max="1000" />
</el-form-item>
<el-form-item :label="$t('dictionary:signature:form:NewStaffTrainDays')" prop="NewStaffTrainDays">
<el-input-number v-model="form.NewStaffTrainDays" controls-position="right" :min="0" :max="1000" />
</el-form-item>
<!-- <el-form-item v-if="form.Id !== ''" label="是否废除: ">
<el-radio-group v-model="form.IsDeleted">
@ -105,14 +50,8 @@
</div>
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
<el-form-item style="text-align: right">
<el-button
size="small"
type="primary"
:disabled="form.FileTypeId === '' || form.Name === ''"
:loading="saveBtnLoading"
@click="handleSave"
>{{ $t('common:button:save') }}</el-button
>
<el-button size="small" type="primary" :disabled="form.FileTypeId === '' || form.Name === ''"
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
</el-form-item>
</div>
</el-form>
@ -138,9 +77,12 @@ export default {
FileTypeId: '',
Name: '',
Path: '',
IsDeleted: false,
IsPublish: false,
IsDeleted: true,
SignViewMinimumMinutes: null,
DocUserSignType: 0,
CurrentStaffTrainDays: 1,
NewStaffTrainDays: 14,
},
rules: {
FileTypeId: [
@ -196,8 +138,11 @@ export default {
this.form.Name = this.data.Name
this.form.Path = this.data.Path
this.form.IsDeleted = this.data.IsDeleted
this.form.IsPublish = this.data.IsPublish
this.form.SignViewMinimumMinutes = this.data.SignViewMinimumMinutes
this.form.DocUserSignType = this.data.DocUserSignType
this.form.CurrentStaffTrainDays = this.data.CurrentStaffTrainDays
this.form.NewStaffTrainDays = this.data.NewStaffTrainDays
}
this.loading = false
},
@ -207,7 +152,7 @@ export default {
.then((res) => {
this.dictionaryList = { ...res.Result }
})
.catch(() => {})
.catch(() => { })
},
//
getUserType() {
@ -284,7 +229,7 @@ export default {
this.$message.warning(this.$t('upload:rule:maxFile1'))
},
checkFileSuffix(fileName) {
var typeArr = ['pdf']
var typeArr = ['pdf', 'mp4']
var extendName = fileName
.substring(fileName.lastIndexOf('.') + 1)
.toLocaleLowerCase()
@ -305,13 +250,16 @@ export default {
width: 80px;
height: 40px;
}
.upload-container .el-input--small {
margin-bottom: 5px;
}
.upload-container .el-icon-circle-check {
color: #428bca;
font-size: 13px;
}
.account_item_clear {
.el-tag__close {
display: none !important;

View File

@ -0,0 +1,213 @@
<template>
<el-form ref="attachmentFrom" v-loading="loading" :model="form" label-width="190px" size="small" :rules="rules"
class="upload-temporary-file">
<div class="base-dialog-body">
<el-form-item :label="$t('dictionary:signature:form:FileName')" prop="Name">
<el-input v-model="form.Name" clearable></el-input>
</el-form-item>
<el-form-item :label="$t('dictionary:signature:form:OffLine')" prop="OffLine">
<el-switch v-model="form.OffLine" :active-value="true" :inactive-value="false"
:active-text="$fd('YesOrNo', true)" :inactive-text="$fd('YesOrNo', false)">
</el-switch>
</el-form-item>
<el-form-item :label="$t('dictionary:signature:form:File')">
<div class="upload-container">
<el-upload class="upload-demo" action :accept="this.accept.join(',')" :before-upload="beforeUpload"
:http-request="handleUploadFile" :on-preview="handlePreview" :on-remove="handleRemoveFile"
:show-file-list="true" :file-list="fileList" :limit="1" :on-exceed="handleExceed">
<el-button size="small" type="primary" :loading="btnLoading">{{ $t('common:button:check')
}}</el-button>
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
({{ $t('trials:signature:label:type').replace("xxx", this.accept.join(", ")) }})
</span>
</el-upload>
</div>
</el-form-item>
</div>
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
<el-form-item style="text-align: right">
<el-button size="small" type="primary" :disabled="form.FileTypeId === '' || form.Name === ''"
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script>
import { addOrUpdateSystemDocumentAttachment } from '@/api/dictionary'
export default {
props: {
data: {
type: Object,
default() {
return {}
},
},
SystemDocumentId: {
type: String,
default: ''
}
},
data() {
return {
form: {
Id: '',
Name: null,
FileFormat: null,
FileName: null,
FilePath: null,
FileSize: null,
OffLine: false,
SystemDocumentId: null,
},
rules: {
Name: [
{
required: true,
message: this.$t('common:ruleMessage:specify'),
trigger: ['change'],
},
],
},
fileList: [],
btnLoading: false,
saveBtnLoading: false,
loading: false,
accept: ['.jpg',
'.jpeg',
'.png',
'.pdf',
'.ppt',
'.pptx',
'.doc',
'.docx',
'.xls',
'.xlsx',
'.mp4']
}
},
mounted() {
this.initForm()
},
methods: {
async initForm() {
this.loading = true
if (this.data && this.data.Id) {
Object.keys(this.form).forEach(key => {
this.form[key] = this.data[key]
})
this.fileList = [
{
name: this.data.FileName,
url: this.data.FilePath,
path: this.data.FilePath,
},
]
}
this.loading = false
},
beforeUpload(file) {
//
if (this.checkFileSuffix(file.name)) {
this.fileList = []
return true
} else {
this.$alert(this.$t('trials:signature:label:type').replace("xxx", this.accept.join(", ")))
return false
}
},
async handleUploadFile(param) {
this.loading = true
var file = await this.fileToBlob(param.file)
const res = await this.OSSclient.put(
`/System/DocumentToSign/${param.file.name}${new Date().getTime()}`,
file
)
this.fileList.push({
name: param.file.name,
path: this.$getObjectName(res.url),
url: this.$getObjectName(res.url),
})
this.form.Name = param.file.name
this.form.FileName = param.file.name
this.form.FilePath = this.$getObjectName(res.url)
this.form.FileSize = param.file.size
this.form.FileFormat = param.file.name
.substring(param.file.name.lastIndexOf('.'))
.toLocaleLowerCase().split('.')[1]
this.loading = false
},
handleSave() {
this.$refs.attachmentFrom.validate((valid) => {
if (!valid) return false
if (!this.form.FilePath)
return this.$alert(this.$t('trials:signature:message:selectFile'))
this.saveBtnLoading = true
if (this.SystemDocumentId) this.form.SystemDocumentId = this.SystemDocumentId
addOrUpdateSystemDocumentAttachment(this.form)
.then((res) => {
this.saveBtnLoading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success(this.$t('common:message:updatedSuccessfully'))
})
.catch(() => {
this.saveBtnLoading = false
})
})
},
handleRemoveFile() {
this.fileList = []
this.form.FilePath = ''
this.form.FileSize = ''
this.form.FileFormat = ''
this.form.FileName = ''
},
handlePreview(file) {
if (file.fullPath) {
window.open(file.fullPath, '_blank')
}
},
handleExceed(files, fileList) {
this.$message.warning(this.$t('upload:rule:maxFile1'))
},
checkFileSuffix(fileName) {
var typeArr = this.accept.map(item => item.split('.')[1])
var extendName = fileName
.substring(fileName.lastIndexOf('.') + 1)
.toLocaleLowerCase()
if (typeArr.indexOf(extendName) !== -1) {
return true
} else {
return false
}
},
},
}
</script>
<style lang="scss">
.upload-temporary-file {
.upload-container .el-upload--text {
border: none;
width: 80px;
height: 40px;
}
.upload-container .el-input--small {
margin-bottom: 5px;
}
.upload-container .el-icon-circle-check {
color: #428bca;
font-size: 13px;
}
.account_item_clear {
.el-tag__close {
display: none !important;
}
}
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<div v-if="config.visible">
<base-model :config="config">
<template slot="dialog-body">
<el-form ref="form" :model="rowData" label-width="80px" style="width: 80%;display: inline-block;">
<el-form-item :label="`${$t('dictionary:signature:table:Name')}: `">
<span class="name text-ellipsis" :title="rowData.Name">{{ rowData.Name }}</span>
</el-form-item>
</el-form>
<el-button size="mini" type="primary" style="float:right" @click.stop="edit({})" v-if="!isView">
{{ $t('common:button:add') }}</el-button>
<el-table :data="list" style="width: 100%" max-height="300px" v-loading="loading"
@sort-change="handleSortByColumn">
<el-table-column type="index" width="60" />
<el-table-column prop="Name" :label="$t('dictionary:signature:attachmentList:FileName')"
sortable="custom" />
<el-table-column prop="OffLine" :label="$t('dictionary:signature:attachmentList:OffLine')"
sortable="custom" v-if="!isView">
<template slot-scope="scope">
<el-switch v-model="scope.row.OffLine" @change="(val) => OffLine(scope.row, val)"
:active-value="true" :inactive-value="false" :active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)">
</el-switch>
</template>
</el-table-column>
<el-table-column prop="CreateTime" :label="$t('dictionary:signature:attachmentList:CreateTime')"
sortable="custom" />
<el-table-column :label="$t('common:action:action')" min-width="120px">
<template slot-scope="scope">
<el-button size="mini" type="text" @click.stop="preview(scope.row)">
{{ $t('common:button:preview') }}
</el-button>
<el-button size="mini" type="text" @click.stop="edit(scope.row)" v-if="!isView">
{{ $t('common:button:edit') }}
</el-button>
<!-- <el-button size="mini" type="text" @click.stop="OffLine(scope.row, true)"
:disabled="scope.row.OffLine">
{{ $t('dictionary:signature:attachmentList:OffLine') }}
</el-button> -->
<el-button size="mini" type="text" @click.stop="del(scope.row)" v-if="!isView">
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增/编辑附件 -->
<el-dialog :visible.sync="visible" :close-on-click-modal="false" :append-to-body="true" :title="title"
width="800px" custom-class="base-dialog-wrapper">
<attachmentForm v-if="visible" :data="rowDATA" :SystemDocumentId="SystemDocumentId"
@closeDialog="closeDialog" @getList="getAllList" />
</el-dialog>
</template>
</base-model>
<viewer ref="picture_perview2" style="margin: 0 10px"
v-if="rowDATA.FileFormat && ['png', 'jpg', 'jpeg'].includes(rowDATA.FileFormat.toLowerCase())"
:images="[`${OSSclientConfig.basePath}${rowDATA.FilePath}`]" :options="viewerOptions">
<img v-show="false" :src="`${OSSclientConfig.basePath}${rowDATA.FilePath}`" alt="Image" />
</viewer>
<!-- <attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible"
v-if="perview_visible" /> -->
</div>
</template>
<script>
import BaseModel from '@/components/BaseModel'
import attachmentForm from './attachmentForm'
// import attachmentPreview from './attachmentPreview'
import { addOrUpdateSystemDocumentAttachment, getSystemDocumentAttachmentList, deleteSystemDocumentAttachment } from '@/api/dictionary'
const defaultSearchData = () => {
return {
PageIndex: 1,
PageSize: 1000,
Asc: false,
OffLine: null,
SortField: null
}
}
export default {
components: {
BaseModel,
attachmentForm,
// attachmentPreview
},
props: {
config: {
type: Object,
default: () => {
return {
visible: false,
title: this.$t('dictionary:signature:attachmentList:title'),
width: '800px',
}
}
},
isView: {
type: Boolean,
default: false
},
rowData: {
type: Object,
default: () => {
return {}
}
},
SystemDocumentId: {
type: String,
default: ''
}
},
data() {
return {
searchData: defaultSearchData(),
visible: false,
title: null,
list: [],
rowDATA: {},
loading: false,
viewerOptions: {
toolbar: {
zoomIn: true,
zoomOut: true,
reset: true,
prev: false,
next: false,
rotateLeft: true,
rotateRight: true,
flipHorizontal: true,
flipVertical: true,
}
},
// perview_visible: false
}
},
watch: {
SystemDocumentId: {
handler() {
this.getList()
},
immediate: true,
}
},
methods: {
closeDialog() {
this.visible = false
},
getAllList() {
this.getList()
this.$emit("getList")
},
async del(row) {
try {
let confirm = await this.$confirm(this.$t("dictionary:signature:attachmentList:message:del"))
if (!confirm) return false
this.loading = true
let res = await deleteSystemDocumentAttachment(row.Id)
this.loading = false
if (res.IsSuccess) {
this.getAllList()
}
} catch (err) {
console.log(err)
this.loading = false
}
},
edit(row) {
this.title = this.$t('dictionary:signature:attachmentForm:title:update')
if (!row.Id) {
this.title = this.$t('dictionary:signature:attachmentForm:title:add')
}
this.rowDATA = Object.assign({}, row)
this.visible = true
},
async getList() {
try {
if (!this.SystemDocumentId) return false
this.loading = true
this.searchData.SystemDocumentId = this.SystemDocumentId
if (this.isView) {
this.searchData.OffLine = false
}
let res = await getSystemDocumentAttachmentList(this.searchData)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData
}
} catch (err) {
this.loading = false
console.log(err)
}
},
async OffLine(row, val) {
try {
let data = Object.assign({}, row)
data.OffLine = val
this.loading = true
let res = await addOrUpdateSystemDocumentAttachment(data)
this.loading = false
if (res.IsSuccess) {
this.$t('dictionary:signature:attachmentList:updateSuccessfully')
this.getList()
}
} catch (err) {
this.loading = false
row.OffLine = !row.OffLine
console.log(err)
}
},
preview(data) {
// return this.perview_visible = true
this.rowDATA = Object.assign({}, data)
if (['.ppt',
'.pptx',
'.doc',
'.docx',
'.xls',
'.xlsx'].includes(`.${data.FileFormat.toLowerCase()}`)) {
this.$onlyOffice({
path: data.FilePath,
type: data.FileFormat,
title: data.Name
})
}
if (['.jpg',
'.jpeg',
'.png'].includes(`.${data.FileFormat.toLowerCase()}`)) {
this.$nextTick(() => {
this.$refs['picture_perview2'].$viewer.show()
})
}
if (['.pdf'].includes(`.${data.FileFormat.toLowerCase()}`)) {
this.$preview({
path: data.Path || data.FilePath,
type: 'pdf',
title: data.Name,
})
}
if (['.mp4'].includes(`.${data.FileFormat.toLowerCase()}`)) {
this.$video({
path: data.Path || data.FilePath,
type: 'mp4',
title: data.Name,
})
}
},
//
handleSortByColumn(column) {
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false
}
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
}
}
</script>
<style lang="scss" scoped>
.name {
display: block;
width: 90%;
}
</style>

View File

@ -0,0 +1,326 @@
<template>
<el-dialog :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
custom-class="base-dialog-wrapper" :before-close="handleClose">
<div v-loading="loading" class="img-container" v-if="visible">
<el-card class="box-card left">
<div class="title">
{{ $t('dictionary:signature:fileList') }}
</div>
<div class="left-content">
<!-- 检查层级 -->
<div id="imgList" style="height: 100%; overflow: hidden">
<template v-for="(item, index) in list">
<div :id="`img${item.Id}`" :key="item.Id" :class="{
'is-boxActive': item.Id === rowData.Id,
}" class="img-box" @click="selected(item)">
<div class="file-image">
<el-image v-if="
[
'jpeg',
'jpg',
'png',
].includes(item.FileFormat)
" style="width: 100%; height: 100%"
:src="`${OSSclientConfig.basePath}${item.FilePath}?x-oss-process=image/resize,w_50,h_50/format,png`"
fit="contain" crossorigin="anonymous" />
<el-image v-else style="width: 100%; height: 100%" :src="getsrc(item.FileFormat)"
fit="contain" crossorigin="anonymous" />
</div>
<div v-if="item.Name.length < 15" class="img-text">
{{ `${index + 1}. ${item.Name}` }}
</div>
<el-tooltip v-else :content="item.Name" placement="bottom">
<div class="img-text">
{{ `${index + 1}. ${item.Name}` }}
</div>
</el-tooltip>
</div>
</template>
</div>
</div>
</el-card>
<!-- 预览图像 -->
<el-card class="box-card right">
<div style="width: 100%; height: 100%" v-if="[
'jpeg',
'jpg',
'png',
].includes(rowData.FileFormat)">
<imageViewer :rowData="rowData" />
</div>
<div style="width: 100%; height: 100%" v-else>
<PreviewFile v-if='rowData.FilePath' :file-path="rowData.FilePath" :file-type="rowData.FileFormat"
:title="rowData.Name" />
</div>
</el-card>
<!-- <el-card class="box-card" style="width:300px;height:100%;padding: 10px;margin-left:10px;">
<CheckForm />
</el-card> -->
</div>
</el-dialog>
</template>
<script>
import pdf from '@/assets/file_icon/pdf.png'
import zip from '@/assets/file_icon/zip.png'
import doc from '@/assets/file_icon/doc.png'
import docx from '@/assets/file_icon/docx.png'
import ppt from '@/assets/file_icon/ppt.png'
import pptx from '@/assets/file_icon/pptx.png'
import xls from '@/assets/file_icon/xls.png'
import xlsx from '@/assets/file_icon/xlsx.png'
import PreviewFile from '@/components/PreviewFile'
import imageViewer from './image-viewer'
import { getSystemDocumentAttachmentList } from '@/api/dictionary'
import { getTrialDocumentAttachmentList } from '@/api/trials'
const defaultSearchData = () => {
return {
PageIndex: 1,
PageSize: 1000,
Asc: false,
OffLine: null,
SortField: null
}
}
export default {
name: 'Notice',
components: {
PreviewFile,
imageViewer
},
props: {
SystemDocumentId: {
type: String,
default: ''
},
visible: {
type: Boolean,
default: false
},
isView: {
type: Boolean,
default: false
},
isTrial: {
type: Boolean,
default: false
}
},
data() {
return {
pdf,
zip,
doc,
docx,
ppt,
pptx,
xls,
xlsx,
rowData: {},
list: [],
searchData: defaultSearchData(),
title: this.$t('dictionary:signature:fileList')
}
},
watch: {
SystemDocumentId: {
handler() {
this.getList()
},
immediate: true,
}
},
methods: {
getsrc(type) {
return this[type.toLowerCase()]
},
selected(row) {
this.rowData = row
},
handleClose() {
this.$emit("update:visible", false)
},
async getList() {
try {
if (!this.SystemDocumentId) return false
this.loading = true
if (!this.isTrial) {
this.searchData.SystemDocumentId = this.SystemDocumentId
} else {
this.searchData.TrialDocumentId = this.SystemDocumentId
}
if (this.isView) {
this.searchData.OffLine = false
}
let res = null
if (!this.isTrial) {
res = await getSystemDocumentAttachmentList(this.searchData)
} else {
res = await getTrialDocumentAttachmentList(this.searchData)
}
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData
this.rowData = this.list[0] || {}
}
} catch (err) {
this.loading = false
console.log(err)
}
},
},
}
</script>
<style lang="scss" scoped>
.img-container {
position: relative;
width: 100%;
height: 100%;
padding: 10px;
display: flex;
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
::v-deep .el-card__body {
padding: 0px;
}
}
.study-desc {
padding: 10px 5px;
line-height: 20px;
background-color: #d5d5d5;
font-weight: 500;
}
.left {
width: 220px;
height: 100%;
::v-deep .el-card__body {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
.title {
height: 40px;
line-height: 40px;
border: 1ppx solid;
border: 1px solid #ebe7e7;
padding-left: 10px;
background-color: #4e4e4e;
color: #ffffff;
}
.left-content {
flex: 1;
overflow-y: auto;
}
// ::v-deep .el-tabs{
// height: 100%;
// }
// ::v-deep .el-tabs__header{
// height: 40px;
// }
// ::v-deep .el-tabs__content{
// flex: 1;
// overflow-y: auto;
// padding: 0;
// }
.img-box {
// position: relative;
display: inline-block;
box-sizing: border-box;
border-bottom: 2px solid #f3f3f3;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-start;
padding: 5px 10px;
cursor: pointer;
// margin-bottom: 5px;
padding-left: 5px;
}
.img-text {
display: inline-block;
width: calc(100% - 60px);
margin-left: 5px;
height: 50px;
line-height: 50px;
overflow: hidden;
text-overflow: ellipsis;
/* 用省略号表示溢出的文本 */
white-space: nowrap;
}
.img-box:nth-last-child(1) {
margin-bottom: 0px;
}
.is-boxActive {
// border-color: #409eff;
color: #409eff;
}
.is-boxActiv:after {
opacity: 0;
}
}
.right {
flex: 1;
height: 100%;
margin-left: 10px;
::v-deep .el-card__body {
height: 100%;
width: 100%;
}
}
.switchBox {
width: 100%;
margin: 5px 0;
color: #4e4e4e;
.item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 5px;
}
}
.file-image {
width: 50px;
height: 50px;
}
::v-deep .el-collapse-item__header {
background-color: #d5d5d5;
}
::v-deep .el-collapse-item__header {
min-height: 48px;
height: auto;
}
::v-deep .el-collapse-item__content {
padding-bottom: 0;
}
</style>

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