Compare commits

..

224 Commits

Author SHA1 Message Date
wangxiaoshuang b45f16e3e1 阅片跟踪添加下载报告功能
continuous-integration/drone/push Build was killed
2026-05-27 16:43:11 +08:00
caiyiling f4ad839080 新增授权路由及pacs影像拉取bug更改
continuous-integration/drone/push Build is passing
2026-03-24 10:05:05 +08:00
caiyiling c7160f7bfb 拉取成功关闭按钮loading效果
continuous-integration/drone/push Build is passing
2026-03-13 17:28:46 +08:00
caiyiling 1633c6e3f8 按患者拉取数据逻辑更改
continuous-integration/drone/push Build is passing
2026-03-13 17:24:09 +08:00
caiyiling 130af3db46 拉取数据更改
continuous-integration/drone/push Build is passing
2026-03-13 17:10:00 +08:00
caiyiling a6456cd932 按项目拉取逻辑更改
continuous-integration/drone/push Build is passing
2026-03-13 17:01:36 +08:00
caiyiling 221bba266e 访视列表更改
continuous-integration/drone/push Build is passing
2026-03-12 13:11:42 +08:00
caiyiling 41c1dca7b2 修改配置文件
continuous-integration/drone/push Build is passing
2026-03-09 15:50:41 +08:00
hang 1b9aed8316 HIR Drone 打包增加企业微信通知
continuous-integration/drone/push Build is passing
2026-02-06 09:12:21 +08:00
wangxiaoshuang e2ca9e582e 下载优化
continuous-integration/drone/push Build is passing
2025-12-24 09:59:28 +08:00
wangxiaoshuang 6e70d32397 1
continuous-integration/drone/push Build is passing
2025-12-23 16:35:46 +08:00
wangxiaoshuang 876ee4fe32 下载优化
continuous-integration/drone/push Build is running
2025-12-23 16:23:44 +08:00
wangxiaoshuang 9eac0a7d6c 下载优化
continuous-integration/drone/push Build is passing
2025-12-23 11:17:14 +08:00
wangxiaoshuang 0444cee0b5 下载文件优化
continuous-integration/drone/push Build is passing
2025-12-23 10:07:55 +08:00
wangxiaoshuang dea612422e 下载优化
continuous-integration/drone/push Build is passing
2025-12-18 10:58:05 +08:00
wangxiaoshuang 6acadf6287 下载优化
continuous-integration/drone/push Build is passing
2025-12-18 09:51:23 +08:00
wangxiaoshuang b024b186b7 1
continuous-integration/drone/push Build is passing
2025-12-17 16:59:29 +08:00
wangxiaoshuang 97c91899e3 1
continuous-integration/drone/push Build is passing
2025-12-17 16:01:18 +08:00
wangxiaoshuang c9d930ce74 下载优化
continuous-integration/drone/push Build is passing
2025-12-17 15:25:00 +08:00
wangxiaoshuang ca12b70f41 1
continuous-integration/drone/push Build is passing
2025-12-12 17:57:45 +08:00
wangxiaoshuang 47ece38ec0 打包失败错误抛出
continuous-integration/drone/push Build is passing
2025-12-12 17:45:34 +08:00
wangxiaoshuang e5f3257f81 下载失败提示
continuous-integration/drone/push Build is passing
2025-12-12 17:34:06 +08:00
wangxiaoshuang 4bee20d1cd 下载优化
continuous-integration/drone/push Build is passing
2025-12-12 16:10:01 +08:00
wangxiaoshuang 927bb9c6be 1
continuous-integration/drone/push Build is passing
2025-12-12 09:17:57 +08:00
wangxiaoshuang 202e411384 1
continuous-integration/drone/push Build is running
2025-12-12 09:17:17 +08:00
wangxiaoshuang 9b0e2f9a2e 下载完成进度条清空
continuous-integration/drone/push Build is running
2025-12-12 09:14:48 +08:00
wangxiaoshuang 6bcd30969b 下载添加文件大小提醒、下载进度提示
continuous-integration/drone/push Build is passing
2025-12-11 16:29:44 +08:00
wangxiaoshuang b913f8e073 下载方式变更
continuous-integration/drone/push Build is passing
2025-12-11 10:57:15 +08:00
wangxiaoshuang af882fede8 1
continuous-integration/drone/push Build is passing
2025-11-24 14:48:14 +08:00
wangxiaoshuang cc10f961c8 下载路径修改
continuous-integration/drone/push Build is passing
2025-11-24 14:21:05 +08:00
wangxiaoshuang 03f9435cb9 下载功能修改
continuous-integration/drone/push Build is passing
2025-11-24 11:40:38 +08:00
wangxiaoshuang 081c82283d 1
continuous-integration/drone/push Build is passing
2025-11-21 18:05:36 +08:00
wangxiaoshuang f2e5f0810c 1
continuous-integration/drone/push Build is passing
2025-11-21 17:55:14 +08:00
wangxiaoshuang 7ce72608b4 1
continuous-integration/drone/push Build is passing
2025-11-21 17:44:56 +08:00
wangxiaoshuang 13c9bb8b73 下载问题解决
continuous-integration/drone/push Build is passing
2025-11-21 17:37:35 +08:00
wangxiaoshuang d956d6b64b 1
continuous-integration/drone/push Build is passing
2025-11-21 16:25:12 +08:00
wangxiaoshuang 46e209fe54 1
continuous-integration/drone/push Build is running
2025-11-21 16:24:35 +08:00
wangxiaoshuang 8f6121dcd0 影像下载
continuous-integration/drone/push Build is passing
2025-11-21 16:12:55 +08:00
wangxiaoshuang 3d9021acc6 推送工具下载修改
continuous-integration/drone/push Build is passing
2025-11-03 17:57:12 +08:00
hang 206087b5c1 修改传递参数值
continuous-integration/drone/push Build is passing
2025-10-30 15:03:34 +08:00
wangxiaoshuang 0fdf3ee8cd PACS按患者进行转发
continuous-integration/drone/push Build is passing
2025-10-30 14:04:16 +08:00
wangxiaoshuang d04b1b5e6f oa变更为sa
continuous-integration/drone/push Build is passing
2025-10-29 09:24:39 +08:00
wangxiaoshuang 947c75a8ec 1
continuous-integration/drone/push Build is passing
2025-09-26 09:55:22 +08:00
wangxiaoshuang de02c3c40e 通过改方式间隔天数导致访视点肿瘤评估变动保存时不进行必填校验提示
continuous-integration/drone/push Build is passing
2025-09-25 16:15:44 +08:00
wangxiaoshuang 962d0a67f6 1
continuous-integration/drone/push Build is passing
2025-09-24 16:44:50 +08:00
wangxiaoshuang 11638f54ea 失效任务退回按钮禁用
continuous-integration/drone/push Build is passing
2025-09-24 16:37:49 +08:00
wangxiaoshuang 94af3983f2 受试者确认访视问题修改
continuous-integration/drone/push Build is passing
2025-09-24 16:03:58 +08:00
wangxiaoshuang 05ff472d01 允许PM退回阅片任务到访视未提交状态
continuous-integration/drone/push Build is passing
2025-09-24 15:54:19 +08:00
wangxiaoshuang 7ca7b4c378 受试者新增添加访视入口
continuous-integration/drone/push Build is passing
2025-09-24 14:21:34 +08:00
wangxiaoshuang 3b8c2de88b 1
continuous-integration/drone/push Build is passing
2025-09-23 14:43:29 +08:00
wangxiaoshuang 2c4dd7f537 基线病灶数量在基线是1-99,后续随访时应该是:0-99
continuous-integration/drone/push Build is passing
2025-09-23 13:48:16 +08:00
wangxiaoshuang 5c90d74e08 页面优化
continuous-integration/drone/push Build is passing
2025-09-23 11:35:16 +08:00
wangxiaoshuang f20212cefe 阅片分享修改
continuous-integration/drone/push Build is passing
2025-09-22 17:54:17 +08:00
wangxiaoshuang 3187f475f1 1
continuous-integration/drone/push Build is passing
2025-09-22 16:29:35 +08:00
wangxiaoshuang 321d0dcaf0 1
continuous-integration/drone/push Build is passing
2025-09-22 16:14:03 +08:00
wangxiaoshuang a4a6b7ed91 【PCWG3】重阅至基线后,进入基线阅片,基线病灶不能将病灶数量修改为比历史数据大,这里不应该被限制
continuous-integration/drone/push Build is passing
2025-09-22 16:09:37 +08:00
wangxiaoshuang a9934f73be 1
continuous-integration/drone/push Build is passing
2025-09-19 17:00:56 +08:00
wangxiaoshuang 298e576323 1
continuous-integration/drone/push Build is passing
2025-09-19 16:36:42 +08:00
wangxiaoshuang 435c9b5d98 PCWG访视间隔必填校验
continuous-integration/drone/push Build is passing
2025-09-19 15:44:05 +08:00
wangxiaoshuang fb92362e6b 【用户管理】添加已有用户,输入非邮箱格式的数据查询后,无法删除输入框中数据,点击删除后再点击查询报错
continuous-integration/drone/push Build is passing
2025-09-19 14:01:46 +08:00
wangxiaoshuang 852bc20728 PCWG3访视间隔天数填写后自动计算访视点肿瘤评估(修改)
continuous-integration/drone/push Build is passing
2025-09-18 14:32:03 +08:00
wangxiaoshuang f28d84093c PCWG3访视间隔天数填写后自动计算访视点肿瘤评估
continuous-integration/drone/push Build is passing
2025-09-18 10:46:59 +08:00
wangxiaoshuang cf6e17b7c8 检查列表增加StudyInstanceUid
continuous-integration/drone/push Build is passing
2025-09-17 17:58:14 +08:00
wangxiaoshuang d31938b268 1
continuous-integration/drone/push Build is passing
2025-09-17 16:20:56 +08:00
wangxiaoshuang af1b78d8cd PCWG报告访视点肿瘤评估添加必填校验
continuous-integration/drone/push Build is passing
2025-09-17 16:15:01 +08:00
wangxiaoshuang 71d9dbccd1 影像库增加查看所有影像
continuous-integration/drone/push Build is passing
2025-09-17 16:09:58 +08:00
wangxiaoshuang fc0533c7d9 用户列表添加已有用户进入课题组入口
continuous-integration/drone/push Build is passing
2025-09-17 15:54:13 +08:00
wangxiaoshuang 3d1dfe9812 接收记录详情修改
continuous-integration/drone/push Build is passing
2025-09-17 14:27:56 +08:00
wangxiaoshuang 3fc39fd059 接收记录详情
continuous-integration/drone/push Build is passing
2025-09-17 11:49:37 +08:00
wangxiaoshuang 0c0e4315d5 阅片报告添加备注
continuous-integration/drone/push Build is passing
2025-09-17 11:31:13 +08:00
wangxiaoshuang 2432829ea5 阅片表单显示备注
continuous-integration/drone/push Build is passing
2025-09-17 10:20:25 +08:00
wangxiaoshuang a85503c173 mrecist病灶状态判断条件修改
continuous-integration/drone/push Build is passing
2025-09-16 18:06:30 +08:00
wangxiaoshuang 407b752e0c mrecist后续访视新病灶联动
continuous-integration/drone/push Build is passing
2025-09-16 18:00:53 +08:00
wangxiaoshuang a704ddbd70 去除TNM分期
continuous-integration/drone/push Build is passing
2025-09-16 16:46:51 +08:00
wangxiaoshuang 5ebae2c4f1 trials:reading:warnning:msg14 国际化修改
continuous-integration/drone/push Build is passing
2025-09-16 16:42:09 +08:00
wangxiaoshuang 214fb4d5ec 影像库列表添加课题组查询条件
continuous-integration/drone/push Build is passing
2025-09-16 14:52:06 +08:00
wangxiaoshuang addef9ec6b 1
continuous-integration/drone/push Build is passing
2025-09-16 11:11:05 +08:00
wangxiaoshuang bf502bcb34 PCWG3报告提交参数变更
continuous-integration/drone/push Build is passing
2025-09-15 16:07:36 +08:00
wangxiaoshuang deefe8d65a 1
continuous-integration/drone/push Build is passing
2025-09-15 14:07:00 +08:00
wangxiaoshuang c1a08df5d4 进入初始化账号页面填写完成后,保存报错
continuous-integration/drone/push Build is passing
2025-09-15 13:55:29 +08:00
wangxiaoshuang 651175d8c2 稽查搜索栏操作时间添加提示
continuous-integration/drone/push Build is passing
2025-09-15 11:24:27 +08:00
wangxiaoshuang 320451780b PCWG报告放开保存按钮
continuous-integration/drone/push Build is passing
2025-09-15 11:19:36 +08:00
wangxiaoshuang b336e048d7 影像浏览工具增加患者信息
continuous-integration/drone/push Build is running
2025-09-15 11:15:48 +08:00
wangxiaoshuang d7528de91d 账号登录日志,操作多选时,只显示一个操作的查询结果;创建时间缺少:开始时间、结束时间提示
continuous-integration/drone/push Build is passing
2025-09-15 11:02:47 +08:00
wangxiaoshuang 54e3b21010 1
continuous-integration/drone/push Build is passing
2025-09-12 18:39:47 +08:00
wangxiaoshuang 8483e02a3b 部分页面国际化
continuous-integration/drone/push Build is passing
2025-09-12 17:58:44 +08:00
wangxiaoshuang 72f2e0a459 部分问题修复
continuous-integration/drone/push Build is passing
2025-09-12 17:36:38 +08:00
wangxiaoshuang 1bef8a027a 1
continuous-integration/drone/push Build is passing
2025-09-12 16:54:54 +08:00
wangxiaoshuang 6fa8cbe602 1
continuous-integration/drone/push Build is passing
2025-09-12 15:54:35 +08:00
wangxiaoshuang ac94a70d4b 调窗问题修改
continuous-integration/drone/push Build is passing
2025-09-12 15:14:34 +08:00
wangxiaoshuang 671e73470f 阅片页首次进入默认不选择关键帧 2025-09-12 15:14:21 +08:00
wangxiaoshuang 6cb48a2490 影像库列表添加查看按钮 2025-09-12 15:13:49 +08:00
wangxiaoshuang 0eab6ba6fe 阅片布局后放大保存病灶时页面渲染问题
continuous-integration/drone/push Build is passing
2025-09-12 14:09:36 +08:00
wangxiaoshuang b4d5f1a269 调窗修改 2025-09-12 11:10:44 +08:00
wangxiaoshuang e3714b5cee pcwg3访视间隔天数可以填写
continuous-integration/drone/push Build is passing
2025-09-12 10:36:55 +08:00
wangxiaoshuang 20847e9423 ga登录跳转至影像库 2025-09-12 10:07:37 +08:00
wangxiaoshuang de04236455 退出登录接口参数
continuous-integration/drone/push Build is passing
2025-09-11 17:54:29 +08:00
wangxiaoshuang 48f3ac70e5 1
continuous-integration/drone/push Build is passing
2025-09-11 15:48:01 +08:00
wangxiaoshuang 4718373f08 部分问题修复
continuous-integration/drone/push Build is running
2025-09-11 15:45:56 +08:00
wangxiaoshuang 7f713f2cfc 问题修复
continuous-integration/drone/push Build is passing
2025-09-11 13:54:16 +08:00
wangxiaoshuang f5395a425a 1
continuous-integration/drone/push Build is passing
2025-09-11 13:37:09 +08:00
wangxiaoshuang 336031659e 互联网/局域网时,账号创建时的信息区别
continuous-integration/drone/push Build is passing
2025-09-11 11:19:12 +08:00
wangxiaoshuang b60d8a6797 【用户管理】新建账号时,如果医院设置为联网,则隐藏初始化密码
continuous-integration/drone/push Build is passing
2025-09-11 10:01:12 +08:00
wangxiaoshuang 073abd2efa 推送添加复制功能
continuous-integration/drone/push Build is passing
2025-09-10 16:55:53 +08:00
wangxiaoshuang 9622f23236 阅片关键帧画标注进行提示
continuous-integration/drone/push Build is passing
2025-09-10 11:16:47 +08:00
wangxiaoshuang 37e07fda42 iRECSIT在 首次为PD时,由RECSIT 1.1转为iRECST,进入阅片页时会显示新病灶的转换提示。当重置eICRF时,需要再次显示。
continuous-integration/drone/push Build is passing
2025-09-10 10:41:14 +08:00
wangxiaoshuang d3446833ce mRECISTD 新病灶,随访时,当长度<1cm,状态设置为疑似
continuous-integration/drone/push Build is running
2025-09-10 10:38:33 +08:00
wangxiaoshuang 79a00f61c0 PCWG3报告计算数值为空时不允许修改(退回)
continuous-integration/drone/push Build is passing
2025-09-09 18:08:53 +08:00
wangxiaoshuang 930aeefa7f 1
continuous-integration/drone/push Build is passing
2025-09-09 17:58:54 +08:00
wangxiaoshuang 90bd4d7f2c 日志
continuous-integration/drone/push Build is passing
2025-09-09 17:37:55 +08:00
wangxiaoshuang 7e37e2e6ae 双屏日志
continuous-integration/drone/push Build is running
2025-09-09 17:36:44 +08:00
wangxiaoshuang 46b3fbafbb iRECSIT在 首次为PD时,由RECSIT 1.1转为iRECST,进入阅片页时会显示新病灶的转换提示。当重置eICRF时,需要再次显示。
continuous-integration/drone/push Build is passing
2025-09-09 17:31:36 +08:00
wangxiaoshuang 096ff69778 PCWG3报告计算数值为空时不允许修改
continuous-integration/drone/push Build is passing
2025-09-09 17:12:41 +08:00
wangxiaoshuang 031c632620 1
continuous-integration/drone/push Build is passing
2025-09-09 16:59:21 +08:00
wangxiaoshuang cb4833ea0c 列表展示课题组修改
continuous-integration/drone/push Build is passing
2025-09-09 15:51:59 +08:00
wangxiaoshuang b296a5b728 1
continuous-integration/drone/push Build is passing
2025-09-09 15:45:00 +08:00
wangxiaoshuang c34200db19 当PM只有一个课题组时,拉取影像时,不需要选择课题组
continuous-integration/drone/push Build is passing
2025-09-09 14:56:55 +08:00
wangxiaoshuang c8c64946a0 阅片报告提交后刷新
continuous-integration/drone/push Build is passing
2025-09-09 14:44:19 +08:00
wangxiaoshuang 40de1d3b1d 从PACS页面返回影像库时,查询数据。
continuous-integration/drone/push Build is passing
2025-09-09 11:50:17 +08:00
wangxiaoshuang 5a4fa5a63d 用户列表:查询条件和列表,需要在角色前,增加课题组;去除演示用户的查询条件和列
continuous-integration/drone/push Build is running
2025-09-09 11:47:59 +08:00
wangxiaoshuang cc227f0e34 课题组管理弹框名称错误 2025-09-09 11:47:46 +08:00
wangxiaoshuang df477c6988 PCWG3修改
continuous-integration/drone/push Build is passing
2025-09-09 11:27:25 +08:00
wangxiaoshuang 4b03a52768 医院管理logo未显示问题
continuous-integration/drone/push Build is passing
2025-09-09 09:54:37 +08:00
wangxiaoshuang e165d5110e 推送工具
continuous-integration/drone/push Build is passing
2025-09-08 15:46:00 +08:00
wangxiaoshuang b80a17b205 阅片标准配置修改
continuous-integration/drone/push Build is passing
2025-09-08 15:36:25 +08:00
wangxiaoshuang df365e97df 附件工具文件上传文件名称处理
continuous-integration/drone/push Build is passing
2025-09-08 14:18:04 +08:00
wangxiaoshuang 33bc40d750 阅片期阅片标准过滤
continuous-integration/drone/push Build is passing
2025-09-08 14:05:25 +08:00
wangxiaoshuang da1862fa23 附件管理添加工具文件
continuous-integration/drone/push Build is passing
2025-09-08 11:08:00 +08:00
wangxiaoshuang 44365bc2d6 1
continuous-integration/drone/push Build is passing
2025-09-08 10:58:43 +08:00
wangxiaoshuang 3f1f24ed04 课题组列表添加ae名称
continuous-integration/drone/push Build is passing
2025-09-08 10:49:47 +08:00
wangxiaoshuang 20ef333325 阅片期修改
continuous-integration/drone/push Build is passing
2025-09-08 10:18:42 +08:00
wangxiaoshuang 23d2c61f9b 分享进入阅片屏蔽手册、临床数据、个性化设置按钮
continuous-integration/drone/push Build is passing
2025-09-05 14:48:29 +08:00
wangxiaoshuang 578c765514 阅片期修改
continuous-integration/drone/push Build is passing
2025-09-05 14:36:30 +08:00
wangxiaoshuang 596aa0d04d 阅片页面修改
continuous-integration/drone/push Build is passing
2025-09-05 14:05:34 +08:00
wangxiaoshuang 9c0e716dc8 添加国际化 2025-09-05 14:05:21 +08:00
wangxiaoshuang f9cbbd56ec 新增阅片期页面 2025-09-05 14:05:09 +08:00
wangxiaoshuang fe77889633 1
continuous-integration/drone/push Build is passing
2025-09-05 10:30:37 +08:00
wangxiaoshuang e04f33db37 1
continuous-integration/drone/push Build is passing
2025-09-05 10:21:29 +08:00
wangxiaoshuang b876f46bf0 pcwg查看报告禁用
continuous-integration/drone/push Build is running
2025-09-05 10:20:09 +08:00
wangxiaoshuang 24813787f0 国际化接口添加
continuous-integration/drone/push Build is passing
2025-09-04 18:03:17 +08:00
wangxiaoshuang 797e174e22 1
continuous-integration/drone/push Build is passing
2025-09-04 14:26:02 +08:00
wangxiaoshuang 9fab7eade2 国际化页面及功能修改
continuous-integration/drone/push Build is running
2025-09-04 14:24:39 +08:00
wangxiaoshuang b626079b7d 阅片分享修改
continuous-integration/drone/push Build is passing
2025-09-04 13:56:05 +08:00
wangxiaoshuang 6d0b3928ee 待阅列表添加双屏
continuous-integration/drone/push Build is passing
2025-09-04 13:49:10 +08:00
wangxiaoshuang 038f477d9e 竖屏修改
continuous-integration/drone/push Build is passing
2025-09-04 13:36:36 +08:00
wangxiaoshuang 70d6cc6010 PCWG已阅任务显示问题
continuous-integration/drone/push Build is passing
2025-09-04 09:45:39 +08:00
wangxiaoshuang 23c2ad92dc 稽查轨迹的详情页,在操作名称后增加操作人、操作时间
continuous-integration/drone/push Build is passing
2025-09-03 15:51:23 +08:00
wangxiaoshuang e1fa3a673c 转换任务表单重置时弹出提示
continuous-integration/drone/push Build is running
2025-09-03 15:47:16 +08:00
wangxiaoshuang 5c91e7a00a 阅片双击放大问题解决
continuous-integration/drone/push Build is passing
2025-09-03 14:33:44 +08:00
wangxiaoshuang 1f5157e476 阅片跟踪完成时间查询字段调整
continuous-integration/drone/push Build is passing
2025-09-03 11:22:56 +08:00
wangxiaoshuang dc5b1f5463 登录日志用户获取
continuous-integration/drone/push Build is passing
2025-09-03 10:39:10 +08:00
wangxiaoshuang 5b1651ed15 阅片播放循环播放
continuous-integration/drone/push Build is passing
2025-09-02 16:44:16 +08:00
wangxiaoshuang e09decd900 mrecist分裂数据未显示感叹号
continuous-integration/drone/push Build is passing
2025-09-02 16:13:48 +08:00
wangxiaoshuang bc85230ddc 靶病灶要是存在不是典型肝内病灶就不提示了
continuous-integration/drone/push Build is passing
2025-09-02 14:21:06 +08:00
wangxiaoshuang 33e6e77484 阅片两侧显隐图标变更
continuous-integration/drone/push Build is passing
2025-09-02 13:51:53 +08:00
wangxiaoshuang 04b3de28d1 稽查记录的子项,增加属性:指定标准显示
continuous-integration/drone/push Build is passing
2025-09-02 11:42:22 +08:00
wangxiaoshuang 081a9908dd 【mRecist】基线添加靶病灶未选择典型肝内病灶时进行提示
continuous-integration/drone/push Build is passing
2025-09-02 11:18:19 +08:00
wangxiaoshuang cc20dfa25b 个人中心角色切换
continuous-integration/drone/push Build is passing
2025-09-01 17:44:35 +08:00
wangxiaoshuang 61a1143d0b 阅片分享
continuous-integration/drone/push Build is passing
2025-09-01 15:43:13 +08:00
wangxiaoshuang b415c21440 登录日志详情国际化
continuous-integration/drone/push Build is passing
2025-09-01 14:35:05 +08:00
wangxiaoshuang 8ce1ffab48 列表页竖屏适配
continuous-integration/drone/push Build is passing
2025-09-01 14:23:50 +08:00
wangxiaoshuang 1ec8c81d0e 阅片页竖屏适配、mrecist新病灶状态
continuous-integration/drone/push Build is passing
2025-09-01 14:18:22 +08:00
wangxiaoshuang e582da7500 添加为典型肝内病灶的非靶病灶时,判断靶病灶中典型肝内病灶数量只在基线提示
continuous-integration/drone/push Build is passing
2025-09-01 10:31:52 +08:00
wangxiaoshuang 87654ddea9 肝门淋巴结校验修改
continuous-integration/drone/push Build is passing
2025-09-01 09:43:44 +08:00
wangxiaoshuang 3429ff3cbd tnm分期位置变动
continuous-integration/drone/push Build is passing
2025-08-29 17:17:33 +08:00
wangxiaoshuang 8b9c93c3b9 1
continuous-integration/drone/push Build is running
2025-08-29 17:15:14 +08:00
wangxiaoshuang 1625b5c417 人员管理国际化修改
continuous-integration/drone/push Build is passing
2025-08-29 16:16:01 +08:00
wangxiaoshuang afce1e2bab 【人员管理】pm需要禁止操作自己的账号
continuous-integration/drone/push Build is passing
2025-08-29 16:05:17 +08:00
wangxiaoshuang 6654981721 人员管理用户类型过滤
continuous-integration/drone/push Build is passing
2025-08-29 15:36:41 +08:00
wangxiaoshuang fe3d30bfcb 项目列表显示字段调整
continuous-integration/drone/push Build is passing
2025-08-29 15:26:12 +08:00
wangxiaoshuang c320adfa03 用户编辑角色限制去除
continuous-integration/drone/push Build is running
2025-08-29 15:23:19 +08:00
wangxiaoshuang 15675c1a99 1
continuous-integration/drone/push Build is passing
2025-08-29 15:06:03 +08:00
wangxiaoshuang fc83d3ee75 医院信息展示顺序调整
continuous-integration/drone/push Build is passing
2025-08-29 14:49:19 +08:00
wangxiaoshuang 53fbc45ba2 关键帧修改
continuous-integration/drone/push Build is passing
2025-08-29 14:34:12 +08:00
wangxiaoshuang 7854159587 TNM分期
continuous-integration/drone/push Build is passing
2025-08-29 11:09:25 +08:00
wangxiaoshuang 05b7e2e8e2 1
continuous-integration/drone/push Build is passing
2025-08-29 10:01:39 +08:00
wangxiaoshuang 9c9762913a 1
continuous-integration/drone/push Build is passing
2025-08-29 09:37:06 +08:00
wangxiaoshuang c62c80733f 管理课题组管理员信息填写变更
continuous-integration/drone/push Build is passing
2025-08-29 09:28:54 +08:00
wangxiaoshuang 5988ad8703 1
continuous-integration/drone/push Build is passing
2025-08-28 15:22:33 +08:00
wangxiaoshuang cc02fee7cb 关键序列在标记完成后立即刷新显示
continuous-integration/drone/push Build is passing
2025-08-28 14:53:25 +08:00
wangxiaoshuang c8ef378170 1
continuous-integration/drone/push Build is passing
2025-08-28 14:12:06 +08:00
wangxiaoshuang 98ab0d4588 管理端用户编辑课题组修改
continuous-integration/drone/push Build is passing
2025-08-28 13:55:18 +08:00
wangxiaoshuang 0cad63ddcd 项目总览项目信息添加课题组信息
continuous-integration/drone/push Build is passing
2025-08-27 17:33:52 +08:00
wangxiaoshuang eac3fde3b9 1
continuous-integration/drone/push Build is passing
2025-08-27 15:17:23 +08:00
wangxiaoshuang 832d239f16 邮箱初始化删除角色栏
continuous-integration/drone/push Build is passing
2025-08-27 14:39:34 +08:00
wangxiaoshuang 57f6761d42 1
continuous-integration/drone/push Build is passing
2025-08-27 13:46:10 +08:00
wangxiaoshuang c73280006f 1
continuous-integration/drone/push Build is passing
2025-08-27 13:11:27 +08:00
wangxiaoshuang 8517d37584 人员配置角色状态字典修改
continuous-integration/drone/push Build is passing
2025-08-27 11:08:00 +08:00
wangxiaoshuang 30144b479b 人员配置去除用户类型排序
continuous-integration/drone/push Build is passing
2025-08-27 10:53:04 +08:00
wangxiaoshuang b4c0718fa7 初始化账号信息页面修改
continuous-integration/drone/push Build is passing
2025-08-27 10:45:57 +08:00
wangxiaoshuang c389b867a9 1
continuous-integration/drone/push Build is passing
2025-08-26 16:44:10 +08:00
wangxiaoshuang bc3f202881 mrecist新病灶添加选框禁用问题
continuous-integration/drone/push Build is passing
2025-08-26 15:53:09 +08:00
wangxiaoshuang 4f9aec017c 异地登陆状态变更
continuous-integration/drone/push Build is passing
2025-08-26 15:26:12 +08:00
wangxiaoshuang b32fcec1ec 1
continuous-integration/drone/push Build is passing
2025-08-26 14:27:57 +08:00
wangxiaoshuang 19d352cc87 稽查轨迹获取访视接口变更
continuous-integration/drone/push Build is running
2025-08-26 14:27:46 +08:00
wangxiaoshuang 3fe64616e9 1
continuous-integration/drone/push Build is passing
2025-08-26 14:17:24 +08:00
wangxiaoshuang 23cb0fab62 多屏阅片未配置浏览器权限时进行提示并提供权限配置教程
continuous-integration/drone/push Build is passing
2025-08-26 14:10:44 +08:00
wangxiaoshuang 4fedec105f 用户列表修改
continuous-integration/drone/push Build is passing
2025-08-26 13:13:09 +08:00
wangxiaoshuang 9cdfb65a7b pm添加用户参数变更
continuous-integration/drone/push Build is passing
2025-08-26 10:19:44 +08:00
wangxiaoshuang 1c5e8edc15 头部样式调整
continuous-integration/drone/push Build is passing
2025-08-25 17:12:05 +08:00
wangxiaoshuang 3f8e2e84ae 拉取影像同步课题组信息
continuous-integration/drone/push Build is passing
2025-08-25 16:55:38 +08:00
wangxiaoshuang 1280a5d23a 影像阅片时,支持双屏
continuous-integration/drone/push Build is passing
2025-08-25 15:40:27 +08:00
wangxiaoshuang b5fbbbdfcc 1
continuous-integration/drone/push Build is passing
2025-08-25 15:21:28 +08:00
wangxiaoshuang 2e1abafa19 管理端邮箱禁止编辑放开
continuous-integration/drone/push Build is passing
2025-08-25 14:52:04 +08:00
wangxiaoshuang 08cde2f22e 初始化账号时,对于校验码,需要增加提示和校验
continuous-integration/drone/push Build is passing
2025-08-25 14:28:10 +08:00
wangxiaoshuang f101478135 用户评审功能
continuous-integration/drone/push Build is passing
2025-08-25 14:17:22 +08:00
wangxiaoshuang 64581a3e07 阅片页面增加患者信息、检查信息
continuous-integration/drone/push Build is passing
2025-08-25 14:00:46 +08:00
wangxiaoshuang ae2cb2c5fb 检查编辑课题组
continuous-integration/drone/push Build is passing
2025-08-25 13:45:19 +08:00
wangxiaoshuang cd224161bb 阅片分屏显示
continuous-integration/drone/push Build is passing
2025-08-22 14:50:20 +08:00
wangxiaoshuang 01cd9cf334 人员管理国际化同步
continuous-integration/drone/push Build is passing
2025-08-22 14:03:57 +08:00
wangxiaoshuang 75fd9cd7f8 课题组编辑新增字段CallingAE
continuous-integration/drone/push Build is passing
2025-08-22 09:28:14 +08:00
wangxiaoshuang b806d97d88 1
continuous-integration/drone/push Build is passing
2025-08-21 16:24:22 +08:00
wangxiaoshuang 45ec78e824 部分问题修复
continuous-integration/drone/push Build is passing
2025-08-21 14:13:42 +08:00
wangxiaoshuang 70b27f7545 课题组状态显示修改
continuous-integration/drone/push Build is passing
2025-08-21 13:24:52 +08:00
wangxiaoshuang 7a88f74840 课题组编辑样式修改1
continuous-integration/drone/push Build is passing
2025-08-21 11:47:05 +08:00
wangxiaoshuang 15e8a8edc2 项目添加课题组相关
continuous-integration/drone/push Build is passing
2025-08-21 11:38:17 +08:00
wangxiaoshuang 15adb3611a mRecist功能添加
continuous-integration/drone/push Build is passing
2025-08-20 16:39:11 +08:00
wangxiaoshuang 216182f48e 后台管理可以添加课题组 2025-08-20 16:38:23 +08:00
wangxiaoshuang 3138bbcb3b 邮件管理
continuous-integration/drone/push Build is passing
2025-08-20 09:14:10 +08:00
wangxiaoshuang 04d6972462 初始化mRecist
continuous-integration/drone/push Build is passing
2025-08-18 15:39:27 +08:00
wangxiaoshuang bb8a1f84a4 重置密码
continuous-integration/drone/push Build is passing
2025-08-18 14:33:17 +08:00
wangxiaoshuang d0887851c2 用户登录及角色切换
continuous-integration/drone/push Build is passing
2025-08-18 13:41:39 +08:00
wangxiaoshuang e7e373ca37 登录接口变更
continuous-integration/drone/push Build is passing
2025-08-15 15:33:24 +08:00
wangxiaoshuang 687985e66b dicom新增时间限制最大值去除
continuous-integration/drone/push Build is passing
2025-07-18 15:35:42 +08:00
137 changed files with 19314 additions and 9280 deletions
+11 -5
View File
@@ -16,11 +16,17 @@ server:
from_secret: local_pwd
steps:
- name: publish-test-hir-vue
commands:
- echo start publish test-hir-vue
- cd /opt/1panel/hang/vue/test-hir
- sh test-hir.sh v${DRONE_BUILD_NUMBER}
- name: publish-test-hir-web
commands:
- bash /opt/1panel/xc-deploy-new/devops-center/build-vue-then-publish.sh HIR_Web main
- name: notify-wecom
commands:
- echo $DRONE_COMMIT_AUTHOR "$DRONE_COMMIT_MESSAGE"
- bash /opt/1panel/xc-deploy-new/devops-center/drone-notify-wecom.sh "$DRONE_BUILD_STATUS" "$DRONE_REPO_NAME" "$DRONE_BRANCH" "$DRONE_BUILD_NUMBER" "4355b98e-1e72-4678-8dfb-2fc6ad0bf449" "$DRONE_COMMIT_MESSAGE" "$DRONE_COMMIT_AUTHOR" "Test_HIR_WEB" "hir.test.extimaging.com"
when:
status:
- success
- failure
trigger:
branch:
+2
View File
@@ -42,6 +42,7 @@
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"pdfobject": "^2.2.8",
"prismjs": "^1.30.0",
"popper.js": "^1.16.1",
"sass-loader": "^8.0.0",
"screenfull": "^4.2.0",
@@ -54,6 +55,7 @@
"vue-contextmenujs": "^1.3.13",
"vue-count-to": "^1.0.13",
"vue-i18n": "^8.7.0",
"vue-prism-editor": "^1.3.0",
"vue-pdf": "^4.3.0",
"vue-puzzle-vcode": "^1.1.10",
"vue-router": "3.0.6",
+30
View File
@@ -0,0 +1,30 @@
影像双屏浏览设置
开启双屏显示具有浏览器相应权限,Chrome 和 Edge 浏览器的设置如下:
1、 Chrome 浏览器设置
点击地址栏左侧按钮,如图所示
点击网站设置,如图所示。
进入网站设置页面,向下滚动页面找到窗口管理,点击右侧下拉框并选择:
允许,如图所示。
1
返回网站,点击重新加载,页面刷新后再次点击阅片按钮即可进行双屏阅片。
2、 Microsoft Edge 浏览器
点击地址栏左侧按钮,如图所示。
2
点击此网站的权限,如图所示。
进入网站权限设置页面,向下滚动页面找到窗口管理,点击右侧下拉框并选
择:允许,如图所示。
3
返回网站,点击刷新,页面刷新后再次点击阅片按钮即可进行双屏阅片,如
图所示。
4
+159 -87
View File
@@ -1,11 +1,7 @@
<template>
<div id="app" style="position: relative">
<router-view />
<div
v-show="show"
v-adaptive
@click="openI18n"
style="
<div v-show="show" v-adaptive @click="openI18n" style="
position: fixed;
bottom: 50px;
left: 50px;
@@ -18,68 +14,65 @@
color: #fff;
border-radius: 50%;
cursor: pointer;
"
>
">
i18n
</div>
<el-drawer title="国际化" :visible.sync="drawer" direction="rtl" size="80%">
<div style="width: 320px">
<el-form label-width="100px" size="small">
<el-form-item label="关键字">
<el-drawer :title="$t('il8n:title')" :visible.sync="drawer" :wrapperClosable="false" direction="rtl" size="80%">
<div style="width: 800px">
<el-form label-width="100px" @submit.native.prevent size="small" :inline="true" class="demo-form-inline">
<el-form-item :label="$t('il8n:search:keyword')">
<el-input v-model="key" @input="keyChange" />
<el-input v-model="key" @input="keyChange" style="display: none" />
</el-form-item>
<el-form-item :label="$t('il8n:search:state')">
<el-select v-model="State" clearable filterable @change="handleStateChange">
<el-option v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
</div>
<el-table
:data="tableData"
v-adaptive="{ bottomOffset: 50 }"
height="100"
style="width: 100%"
>
<el-table-column prop="Code" label="标签" width="300">
</el-table-column>
<!-- <el-table-column-->
<!-- prop="Description"-->
<!-- label="路由"-->
<!-- show-overflow-tooltip-->
<!-- width="180">-->
<!-- <template slot-scope="scope">-->
<!-- {{scope.row.Description}}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="Value" label="英文">
<el-table :data="tableData" v-adaptive="{ bottomOffset: 50 }" height="100" style="width: 100%"
@sort-change="handleSortByColumn">
<el-table-column prop="Code" :label="$t('il8n:table:label')" width="300" sortable="custom">
<template slot-scope="scope">
<el-input
v-model="scope.row.Value"
@input="
(e) => {
$set(scope.row, 'Value', e)
}
"
size="mini"
></el-input>
<span @click="$copyText(scope.row.Code)">{{ scope.row.Code }}</span>
</template>
</el-table-column>
<el-table-column prop="ValueCN" label="中文">
<el-table-column prop="Value" :label="$t('il8n:table:en')" sortable="custom">
<template slot-scope="scope">
<el-input
v-model="scope.row.ValueCN"
@input="
(e) => {
$set(scope.row, 'ValueCN', e)
}
"
size="mini"
></el-input>
<el-input v-model="scope.row.Value" @input="
(e) => {
$set(scope.row, 'Value', e)
}
" size="mini"></el-input>
</template>
</el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:cn')" sortable="custom">
<template slot-scope="scope">
<el-input v-model="scope.row.ValueCN" @input="
(e) => {
$set(scope.row, 'ValueCN', e)
}
" size="mini"></el-input>
</template>
</el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:state')" sortable="custom">
<template slot-scope="scope">
<el-select v-model="scope.row.State" clearable filterable size="mini">
<el-option v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" />
</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>
</div>
@@ -92,6 +85,7 @@ import {
} from '@/api/dictionary/dictionary'
import Vue from 'vue'
import i18n from './lang'
import { getHospital } from '@/api/hospital.js'
export default {
name: 'App',
data() {
@@ -101,13 +95,34 @@ export default {
show: false,
key: null,
arr: [],
il8nExternal: false,
State: null,
}
},
mounted() {
this.show = process.env.VUE_APP_OSS_PATH === "/hir_test/dist";
// this.show = false;
Vue.prototype.$openI18n = this.openI18n
this.getInfo()
},
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
})
},
changeValue(target, attr, e) {
this.$set(target, attr, e)
},
@@ -117,9 +132,12 @@ export default {
[],
this.arr.filter(
(v) =>
~v.Code.indexOf(this.key) ||
~v.Value.indexOf(this.key) ||
~v.ValueCN.indexOf(this.key)
(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 {
@@ -127,39 +145,75 @@ 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('国际化修改成功')
}
)
})
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() {
openI18n(ARRAY) {
this.tableData = []
this.il8nExternal = false
this.State = null
this.key = null
this.drawer = true
let arr = []
let tableData = this.$tl.map((v) => {
let a = { ...v }
// if (!a.Description) {
// a.Description = this.$route.path
// }
return a
})
let tableData = []
if (ARRAY && Array.isArray(ARRAY)) {
this.il8nExternal = true
let data = ARRAY.map((v) => {
let a = { ...v }
return a
})
tableData = data.map((item) => {
return {
Code: item.Code,
Description: item.Description,
FrontType: item.FrontType,
Module: item.Module,
Value: item.Value,
ValueCN: item.ValueCN,
State: item.State,
Version: item.Version,
InternationalizationType: item.InternationalizationType,
}
})
this.tableData = Object.assign([], tableData)
this.arr = Object.assign([], tableData)
return false
} else {
tableData = this.$tl.map((v) => {
let a = { ...v }
// if (!a.Description) {
// a.Description = this.$route.path
// }
return a
})
}
tableData = tableData.filter((v) => {
// return ~this.$path.indexOf(v.Description + '_' + v.Code)
return ~this.$path.indexOf(v.Code)
@@ -176,6 +230,9 @@ export default {
Description: null,
Value: null,
ValueCN: null,
State: 0,
Version: this.$version.Version,
InternationalizationType: 0,
})
}
})
@@ -193,10 +250,19 @@ export default {
} else {
this.tableData = Object.assign([], this.arr)
}
// console.log(JSON.stringify(this.$path));
// console.log(JSON.stringify(this.tableData));
},
},
// 获取医院信息
async getInfo() {
try {
let res = await getHospital()
if (res.IsSuccess) {
Vue.prototype.$IsCanConnectInternet = res.Result.IsCanConnectInternet
}
} catch (err) {
console.log(err)
}
},
}
}
</script>
@@ -204,10 +270,12 @@ export default {
.el-tooltip__popper {
max-width: 400px;
}
.my_multiple {
.el-input--medium .el-input__inner {
height: 36px !important;
}
.el-select__tags {
flex-wrap: nowrap;
overflow: hidden;
@@ -216,6 +284,7 @@ export default {
display: block;
}
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
@@ -228,6 +297,7 @@ input[type='number'] {
.viewer-fixed.viewer-container {
z-index: 10000;
}
textarea {
white-space: break-spaces;
word-break: normal;
@@ -236,9 +306,11 @@ textarea {
* {
word-break: normal !important;
}
.box-body .el-button.is-circle:not(.is-disabled) i:before {
color: #428bca;
}
.box-body .el-button.is-circle i.el-icon-question:before {
color: #fff;
}
+89 -4
View File
@@ -7,7 +7,13 @@ export function getUserList(param) {
data: param
})
}
export function getUserByEmail(params) {
return request({
url: '/User/getUserByEmail',
method: 'get',
params
})
}
export function getUserTypeList() {
return request({
url: `/UserTypeRole/getUserTypeList/0`,
@@ -46,10 +52,11 @@ export function updateUser(param) {
})
}
export function getUser(userId) {
export function getUser(params) {
return request({
url: `/user/getUser/${userId}`,
method: 'get'
url: `/user/getUser`,
method: 'get',
params
})
}
@@ -278,6 +285,22 @@ export function batchAddInternationalization(param) {
data: param
})
}
// 管理端修改用户课题组
export function updateUserHospitalGroupInfo(data) {
return request({
url: `/User/updateUserHospitalGroupInfo`,
method: 'put',
data
})
}
// 管理端修改用户角色
export function updateUserRoleInfo(data) {
return request({
url: `/User/updateUserRoleInfo`,
method: 'put',
data
})
}
// 获取医院列表
export function getHIRHospitalList(param) {
return request({
@@ -309,4 +332,66 @@ export function updateDefaultHospital(params) {
params
})
}
// 获取课题组列表-不分页
export function getHospitalGroupList(data) {
return request({
url: `/HospitalGroup/getHospitalGroupList`,
method: 'post',
data
})
}
// 获取课题组列表-分页
export function getHospitalGroupPageList(data) {
return request({
url: `/HospitalGroup/getHospitalGroupPageList`,
method: 'post',
data
})
}
// 新增或编辑课题组
export function addOrUpdateHospitalGroup(data) {
return request({
url: `/HospitalGroup/addOrUpdateHospitalGroup`,
method: 'post',
data
})
}
// 删除课题组
export function deleteHospitalGroup(id) {
return request({
url: `/HospitalGroup/deleteHospitalGroup/${id}`,
method: 'delete'
})
}
// 获取课题组相关ga
export function getGAUserList(params) {
return request({
url: `/HospitalGroup/getGAUserList`,
method: 'get',
params
})
}
// 修改检查课题组
export function modifySCPStudyHospitalGroup(data) {
return request({
url: `/Patient/modifySCPStudyHospitalGroup`,
method: 'post',
data
})
}
// 国际化获取迭代列表
export function getPublishVersionSelect() {
return request({
url: `/PublishLog/getPublishVersionSelect`,
method: 'get',
})
}
// 国际化批量更新
export function batchUpdateInternationalInfo(data) {
return request({
url: `/Internationalization/batchUpdateInternationalInfo`,
method: 'put',
data
})
}
+7 -1
View File
@@ -265,7 +265,13 @@ export function getCommonDocumentList(param) {
data: param
})
}
export function getCommonDocument(param) {
return request({
url: `/CommonDocument/getCommonDocument`,
method: 'get',
params: param
})
}
export function addOrUpdateCommonDocument(param) {
return request({
url: `/CommonDocument/addOrUpdateCommonDocument`,
+7
View File
@@ -51,3 +51,10 @@ export function batchAddOrUpdateFrontInternationalization(params) {
data: params
})
}
// 获取当前版本
export function getCurrentPublishInfo() {
return request({
url: `/PublishLog/getCurrentPublishInfo`,
method: 'get'
})
}
+9
View File
@@ -203,4 +203,13 @@ export function getCommonJudgeRatioList_Export(data) {
data
})
}
// 导出国际化列表
export function GetInternationalizationList_Export(data) {
return requestDownload({
url: `/ExcelExport/GetInternationalizationList_Export`,
responseType: 'blob',
method: 'post',
data
})
}
+18
View File
@@ -1,5 +1,6 @@
// 检查管理
import request from '@/utils/request'
import requestDownload from '@/utils/request-download'
// 检查->患者列表
export function getPatientList(data) {
@@ -195,4 +196,21 @@ export function getUserJoinedTrialPatientList() {
url: '/Patient/getUserJoinedTrialPatientList',
method: 'get',
})
}
// 获取影像下载数据
export function getDownloadPatientStudyInfo(data) {
return request({
url: '/Patient/getDownloadPatientStudyInfo',
method: 'post',
data
})
}
// 获取影像下载数据(接口二)
export function PatientStudyBatchDownload(data) {
return requestDownload({
url: '/download/PatientStudyBatchDownload',
method: 'post',
responseType: 'blob',
data
})
}
+24
View File
@@ -247,4 +247,28 @@ export function clearSkipReadingCache(param) {
method: 'post',
data: param
})
}
// 获取tnm
export function getTNMValue(param) {
return request({
url: `/ReadingImageTask/getTNMValue`,
method: 'post',
data: param
})
}
// 设置tnm
export function setTNMValue(param) {
return request({
url: `/ReadingImageTask/setTNMValue`,
method: 'post',
data: param
})
}
// 设置tnm
export function frontGetSiteVisitForTumorEvaluation(param) {
return request({
url: `/PCWG3Calculate/frontGetSiteVisitForTumorEvaluation`,
method: 'post',
data: param
})
}
+7
View File
@@ -7,6 +7,13 @@ export function createImageShare(data) {
data
})
}
export function updateImageShare(data) {
return request({
url: '/ImageShare/updateImageShare',
method: 'put',
data
})
}
export function verifyShareImage(resourceId, password) {
return request({
url: `/imageShare/verifyShareImage/${resourceId}/${password}`,
+56 -1
View File
@@ -348,6 +348,13 @@ export function getTrialVisitStageSelect(trialId) {
})
}
export function getTrialVisitSelect(trialId) {
return request({
url: `/visitPlan/getTrialVisitSelect/${trialId}`,
method: 'get'
})
}
export function getSubjectList(param) {
return request({
url: `/subject/getSubjectList`,
@@ -2787,7 +2794,13 @@ export function changeDicomReadingQuestionAnswer(param) {
data: param
})
}
export function changeReportAnswer(param) {
return request({
url: `/ReadingImageTask/changeReportAnswer`,
method: 'post',
data: param
})
}
export function saveImageQuality(param) {
return request({
url: `/ReadingImageTask/saveImageQuality`,
@@ -2905,6 +2918,14 @@ export function getReadingVisitStudyList(trialId, sujectVisitId, visitTaskId) {
}
})
}
// 获取关键序列
export function getKeySeries(data) {
return request({
url: `/SubjectVisit/getKeySeries`,
method: 'post',
data
})
}
export function localFilePreview(relativePath) {
return request({
url: `/Common/LocalFilePreview?relativePath=${relativePath}`,
@@ -3634,4 +3655,38 @@ export function saveTaskQuestion(saveQuestionType, param) {
method: 'post',
data: param
})
}
// 项目添加角色修改权限
export function updateTrialUserRole(data) {
return request({
url: `/TrialMaintenance/updateTrialUserRole`,
method: 'put',
data
})
}
// 阅片任务退回
export function visitImageBack(data) {
return request({
url: `/Patient/visitImageBack`,
method: 'put',
data
})
}
// 访视影像下载
export function VisitImageDownload(data) {
return requestDownload({
url: `/download/VisitImageDownload`,
method: 'post',
responseType: 'blob',
data
})
}
// 临床数据下载
export function ClinicalDataDownload(data) {
return requestDownload({
url: `/download/ClinicalDataDownload`,
method: 'post',
responseType: 'blob',
data
})
}
+35 -10
View File
@@ -131,10 +131,11 @@ export function setAutoCutNextTask(params) {
})
}
export function loginOut() {
export function loginOut(params) {
return request({
url: `/User/loginOut`,
method: 'get'
method: 'get',
params
})
}
@@ -159,14 +160,6 @@ export function GetObjectStoreToken(params) {
method: 'get'
})
}
export function loginSelectUserRole(params) {
return request({
url: `/user/loginSelectUserType`,
method: 'get',
params
})
}
// 置换token
export function TJUserLoginInfo(params) {
return request({
@@ -175,4 +168,36 @@ export function TJUserLoginInfo(params) {
params
})
}
// 登陆获取角色
export function getUserLoginRoleList(data) {
return request({
url: `/User/getUserLoginRoleList`,
method: 'post',
data,
})
}
// 登陆角色id获取token
export function loginSelectUserRole(params) {
return request({
url: `/User/loginSelectUserRole`,
method: 'get',
params,
})
}
// 忽略异地登录
export function setIsIgnoreUncommonly(data) {
return request({
url: `/User/setIsIgnoreUncommonly`,
method: 'post',
data,
})
}
// 获取登录用户
export function getTrialUserList(params) {
return request({
url: `/TrialMaintenance/getTrialUserList`,
method: 'get',
params
})
}
+47 -137
View File
@@ -1,158 +1,68 @@
<!-- 搜索表单 -->
<template>
<div class="base-search-form">
<el-form :size="size" :inline="true" :label-width="labelWidth">
<el-form-item
v-for="item in searchForm"
:key="item.prop"
:label="item.label"
>
<el-form :inline="true" :label-width="labelWidth">
<el-form-item v-for="item in searchForm" :key="item.prop" :label="item.label">
<!-- 输入框 -->
<el-input
v-if="item.type === 'Input'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
:style="{ width: item.width }"
:readonly="item.readonly"
clearable
/>
<el-input v-if="item.type === 'Input'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
size="mini" clearable :style="{ width: item.width }" :readonly="item.readonly" />
<!-- 下拉框 -->
<el-select
v-if="item.type === 'Select'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
clearable
:style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])"
>
<el-option
v-for="op in item.options"
:key="op[item.props['label']]"
:label="op[item.props['label']]"
:value="op[item.props['value']]"
/>
<el-select v-if="item.type === 'Select'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
size="mini" clearable :style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])">
<el-option v-for="op in item.options" :key="op[item.props['label']]" :label="op[item.props['label']]"
:value="op[item.props['value']]" />
</el-select>
<el-select
v-if="item.type === 'Select2'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
clearable
:style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])"
>
<el-option
v-for="(key, value) of item.options"
:key="key"
:label="key"
:value="value"
/>
<el-select v-if="item.type === 'Select2'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
size="mini" clearable :style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])">
<el-option v-for="(key, value) of item.options" :key="key" :label="key" :value="value" />
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="item.type === 'Radio'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
>
<el-radio
v-for="ra in item.radios"
:key="ra.value"
:label="ra.value"
>{{ ra.label }}</el-radio
>
<el-radio-group v-if="item.type === 'Radio'" v-model="searchData[item.prop]" :style="{ width: item.width }">
<el-radio v-for="ra in item.radios" :key="ra.value" :label="ra.value">{{ ra.label }}</el-radio>
</el-radio-group>
<!-- 单选按钮 -->
<el-radio-group
v-if="item.type === 'RadioButton'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
@change="item.change && item.change(searchData[item.prop])"
>
<el-radio-button
v-for="ra in item.radios"
:key="ra.value"
:label="ra.value"
>{{ ra.label }}</el-radio-button
>
<el-radio-group v-if="item.type === 'RadioButton'" v-model="searchData[item.prop]"
:style="{ width: item.width }" @change="item.change && item.change(searchData[item.prop])">
<el-radio-button v-for="ra in item.radios" :key="ra.value" :label="ra.value">{{ ra.label }}</el-radio-button>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="item.type === 'Checkbox'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
>
<el-checkbox
v-for="ch in item.checkboxs"
:key="ch.value"
:label="ch.value"
>{{ ch.label }}</el-checkbox
>
<el-checkbox-group v-if="item.type === 'Checkbox'" v-model="searchData[item.prop]"
:style="{ width: item.width }">
<el-checkbox v-for="ch in item.checkboxs" :key="ch.value" :label="ch.value">{{ ch.label }}</el-checkbox>
</el-checkbox-group>
<!-- 日期 -->
<el-date-picker
v-if="item.type === 'Date'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
:style="{ width: item.width }"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
:picker-options="item.pickerOption"
clearable
/>
<el-date-picker v-if="item.type === 'Date'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
:style="{ width: item.width }" value-format="yyyy-MM-dd" format="yyyy-MM-dd"
:picker-options="item.pickerOption" clearable />
<!-- 时间 -->
<el-time-select
v-if="item.type === 'Time'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
type=""
:style="{ width: item.width }"
clearable
/>
<el-time-select v-if="item.type === 'Time'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
type="" :style="{ width: item.width }" clearable />
<!-- 日期时间 -->
<el-date-picker
v-if="item.type === 'DateTime'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
type="datetime"
:disabled="item.disable && item.disable(searchData[item.prop])"
:style="{ width: item.width }"
clearable
/>
<el-date-picker v-if="item.type === 'DateTime'" v-model="searchData[item.prop]" :placeholder="item.placeholder"
type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
:disabled="item.disable && item.disable(searchData[item.prop])" :style="{ width: item.width }" clearable />
<!-- 日期时间段 -->
<el-date-picker
v-if="item.type === 'Daterange'"
v-model="searchData[item.prop]"
type="datetimerange"
range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
:style="{ width: item.width }"
clearable
/>
<el-date-picker v-if="item.type === 'Daterange'" v-model="searchData[item.prop]" type="datetimerange"
:default-time="['00:00:00', '23:59:59']" :range-separator="$t('baseForm:daterange:rangeSeparator')"
:start-placeholder="$t('baseForm:daterange:startPlaceholder')"
:end-placeholder="$t('baseForm:daterange:startendPlaceholder')" value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss" :style="{ width: item.width }" clearable />
<!-- 滑块 -->
<!-- <el-slider v-if="item.type==='Slider'" v-model="searchData[item.prop]"></el-slider> -->
<!-- 开关 -->
<el-switch
v-if="item.type === 'Switch'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
/>
<el-switch v-if="item.type === 'Switch'" v-model="searchData[item.prop]" :style="{ width: item.width }" />
<!-- 具名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>
@@ -170,11 +80,11 @@ export default {
},
labelWidth: {
type: String,
default: "",
default: '',
},
size: {
type: String,
default: "mini",
default: 'mini',
},
searchForm: {
type: Array,
@@ -186,16 +96,16 @@ export default {
},
searchData: {
type: Object,
default: () => {},
default: () => { },
},
},
methods: {
handleClick(emitKey) {
// emit事件
this.$emit(`${emitKey}`);
this.$emit(`${emitKey}`)
},
},
};
}
</script>
<style lang="scss">
.base-search-form {
+38 -32
View File
@@ -1,29 +1,31 @@
<template>
<el-row>
<el-col class="m-b-10" :span="24">
<el-table
v-adaptive="{bottomOffset}"
:data="list"
:height="tableHeight"
v-bind="$attrs"
stripe
:highlight-current-row="highlightCurrentRow"
@selection-change="handleSelectionChange"
@sort-change="sortByColumn"
@select="handleSelect"
@cell-dblclick="celldblclick"
>
<el-table v-adaptive="{ bottomOffset }" :data="list" height="100" v-bind="$attrs" stripe
:highlight-current-row="highlightCurrentRow" @selection-change="handleSelectionChange"
@sort-change="sortByColumn" @select="handleSelect" @cell-dblclick="celldblclick">
<template v-for="(column, index) in columns">
<slot name="front-slot" />
<el-table-column v-if="column.type === 'tip'" :key="index" width="35">
<template slot-scope="scope">
<span v-if="column.slot">
<!-- 具名slot -->
<slot v-if="column.slot" :name="column.slot" :scope="scope" />
</span>
</template>
</el-table-column>
<!-- 序号 -->
<el-table-column v-if="column.type === 'selection'" :key="index" type="selection" width="55" />
<el-table-column v-else-if="column.type === 'selection'" :key="index" type="selection" width="55" />
<!-- 复选框 -->
<el-table-column v-else-if="column.type === 'index'" :key="index" type="index" width="50" />
<!-- 具体内容 -->
<el-table-column v-else :key="index" align="left" :label="column.label" :width="column.width" :min-width="column.minWidth" :show-overflow-tooltip="column.showOverflowTooltip || false" :sortable="column.sortable || false" :prop="column.prop">
<el-table-column v-else :key="index" align="left" :label="column.label" :width="column.width"
:min-width="column.minWidth" :show-overflow-tooltip="column.showOverflowTooltip || false"
:sortable="column.sortable || false" :prop="column.prop" :fixed="column.fixed">
<template slot-scope="scope">
<!-- 仅仅显示文字 -->
<span v-if="!column.hidden"> <!-- 如果hidden为true的时候 那么当前格可以不显示可以选择显示自定义的slot-->
<span v-if="!column.hidden">
<!-- 如果hidden为true的时候 那么当前格可以不显示可以选择显示自定义的slot-->
<!-- 操作按钮 -->
<span v-if="column.type === 'operate'">
<!-- <a v-for="(operate, i) in column.operates" :key="i" href="javascript:void(0)" class="operate-button" @click="handleClick(operate, scope.row)">
@@ -31,7 +33,11 @@
&nbsp;&nbsp;
</a> -->
<span v-for="(operate, i) in column.operates" :key="i">
<el-button :size="operate.size || 'mini'" :type="operate.type || 'primary'" style="margin-right:5px;" @click="handleClick(operate, scope.row)">{{ operate.name }}</el-button>
<el-button :type="operate.type || 'primary'" v-if="
(operate.show && scope.row[operate.show]) ||
!operate.show
" style="margin-right: 5px" @click="handleClick(operate, scope.row)">{{ operate.name
}}</el-button>
</span>
</span>
<span v-else>
@@ -52,7 +58,8 @@
</el-col>
<!-- 分页部分 -->
<el-col v-if="!hiddenPage" :span="24" class="page">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="pagination" />
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="pagination" />
</el-col>
</el-row>
</template>
@@ -96,45 +103,44 @@ export default {
// 核心数据
list: {
type: Array,
default: () => []
default: () => [],
},
// columns
columns: {
type: Array,
required: true,
default: () => []
default: () => [],
},
// is hidden page for table
hiddenPage: {
type: Boolean,
default: false
default: false,
},
bottomOffset: {
type: Number,
default: 45
default: 45,
},
searchData: {
type: Object,
default: () => {}
default: () => { },
},
total: {
type: Number,
default: 0
default: 0,
},
highlightCurrentRow: {
type: Boolean,
default: false
}
default: false,
},
},
data() {
return {
}
return {}
},
computed: {
tableHeight() {
return 100
}
return '100'
},
},
methods: {
// 处理点击事件
@@ -157,12 +163,12 @@ export default {
},
pagination() {
this.$emit('getList')
}
}
},
},
}
</script>
<style lang="scss" scoped>
.page{
.page {
padding-top: 3px;
text-align: right;
}
+51 -69
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)">
@@ -46,15 +40,20 @@
<div class="info-subject">
<div>{{ stack.description }}</div>
<!-- <div>{{ dicomInfo.hospital }}</div> -->
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
<!-- <div>{{ dicomInfo.name }}</div> -->
<div v-if="dicomInfo.pid">{{ dicomInfo.pid }}</div>
<div v-if="dicomInfo.patientName">{{ dicomInfo.patientName }}</div>
<!-- <div>{{ subjectCode }}</div> -->
<!-- <div>{{ dicomInfo.sex }} {{ dicomInfo.age }}</div> -->
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> -->
<div v-if="dicomInfo.modality">{{ dicomInfo.modality }}</div>
<div v-if="dicomInfo.time">{{ 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,15 +80,8 @@
<!-- <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
>
<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>
</div>
@@ -104,7 +96,7 @@ const scroll = cornerstoneTools.import('util/scrollToIndex')
import Hammer from 'hammerjs'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'
import { convertBytes } from '@/utils/dicom-character-set'
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
// import requestPoolManager from '@/utils/request-pool'
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
@@ -263,9 +255,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)
}
@@ -313,39 +305,14 @@ export default {
}
cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {})
}
// if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.OrientationMarkersTool)) {
// cornerstoneTools.addToolForElement(
// element,
// cornerstoneTools.OrientationMarkersTool
// )
// }
// cornerstoneTools.setToolActiveForElement(
// element,
// 'OrientationMarkers',
// {}
// )
cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'playClip'])
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
// cornerstoneTools.stackPrefetch.enable(this.canvas)
cornerstone.updateImage(element, true)
// cornerstoneTools.stackPrefetch.setConfiguration({ maxImagesToPrefetch: Infinity,
// preserveExistingPool: true })
// cornerstoneTools.stackPrefetch.enable(this.canvas)
// this.stack.imageIds.forEach((item, index) => {
// if (index === 0) {
// return
// }
// cornerstone.loadImage(item)
// })
cornerstone.updateImage(element, true)
this.stack.firstImageLoading = false
this.toolState.dicomInfoVisible = true
// 重绘历史标记
// if (ToolStateManager.toolState.hasOwnProperty(image.imageId) === true) {
// 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
@@ -355,25 +322,36 @@ export default {
onNewImage(e) {
e.detail.enabledElement.options = {}
var data = e.detail.image.data
const patientNameElement = data.elements.x00100010
const patientNameBytes = new Uint8Array(
data.byteArray.buffer,
patientNameElement ? patientNameElement.dataOffset : 0,
patientNameElement ? patientNameElement.length : 0
)
// 解析dicom中字符集字段与解析库不一致 2025.03.04
let SpecificCharacterSet = data.string('x00080005')
? data.string('x00080005').replace('ISO IR', 'ISO_IR')
: ''
const patientNameStr = convertBytes(
SpecificCharacterSet,
patientNameBytes
)
this.dicomInfo.hospital = data.string('x00080080')
// this.dicomInfo.pid = data.string('x00100020')
this.dicomInfo.pid = data.string('x00120040')
this.dicomInfo.pid = data.string('x00100020')
this.dicomInfo.patientName = patientNameStr
this.dicomInfo.name = data.string('x00100010')
this.dicomInfo.age = data.string('x00101010')
this.dicomInfo.sex = data.string('x00100040')
this.dicomInfo.acc = data.string('x00080050') // 登记号
this.dicomInfo.acc = data.string('x00080050')
this.dicomInfo.modality = data.string('x00080060')
this.dicomInfo.time = this.formatDicomDateTime(
data.string('x00080020'),
data.string('x00080030')
)
this.dicomInfo.series = data.string('x00200011')
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
this.stack.imageIds.length
}`
this.dicomInfo.size = `${data.uint16('x00280011')}x${data.uint16(
'x00280010'
)}`
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${this.stack.imageIds.length}`
this.dicomInfo.size = `${data.uint16('x00280011')}*${data.uint16('x00280010')}`
console.log(this.dicomInfo, 'this.dicomInfo')
var pixel = data.floatString('x00280030')
if (pixel) {
this.dicomInfo.pixel = pixel.toFixed(2)
@@ -1135,6 +1113,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-image {
position: absolute;
left: 10px;
@@ -1154,6 +1133,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-instance {
position: absolute;
right: 15px;
@@ -1186,6 +1166,7 @@ export default {
margin: 10px;
cursor: default;
}
.menu__item:hover {
color: #ff0000;
}
@@ -1205,7 +1186,8 @@ li:hover {
background-color: #e0e0e2;
color: white;
}
.my_slider_box:after{
.my_slider_box:after {
content: '';
position: absolute;
bottom: -20px;
+36 -61
View File
@@ -2,66 +2,42 @@
<template>
<div class="trialsTab">
<el-tabs v-model="trialsTab" @tab-click="clickTab">
<el-tab-pane
v-for="item of trialsRouter.children.find((v) => {
return v.name == 'TrialsPanel';
}).children"
:key="`tab${item.path}`"
:disabled="
TotalNeedSignTrialDocCount !== 0 ||
(TrialStatusStr === 'Initializing' && item.PermissionStr!=='trials:trials-panel:trial-information')
"
:label="$t(item.LanguageMark)"
:name="item.path"
>
<el-tabs
v-if="!item.tabHiddn"
v-model="trialsTabChild"
@tab-click="clickTab"
>
<el-tab-pane v-for="item of trialsRouter.children.find((v) => {
return v.name == 'TrialsPanel';
}).children" :key="`tab${item.path}`" :disabled="TotalNeedSignTrialDocCount !== 0 ||
(TrialStatusStr === 'Initializing' && item.PermissionStr !== 'trials:trials-panel:trial-information')
" :label="$t(item.LanguageMark)" :name="item.path">
<el-tabs v-if="!item.tabHiddn" v-model="trialsTabChild" @tab-click="clickTab">
<template v-for="item1 of item.children">
<el-tab-pane
v-if="TrialConfig && isShow(item1.path)"
:key="`tab1${item1.path}`"
:disabled="
TotalNeedSignTrialDocCount !== 0 ||
(TrialStatusStr === 'Initializing' &&
(item1.path ===
'/trials/trials-panel/setting/personnel-manage' ||
item1.path === '/trials/trials-panel/setting/qc-question' ||
item1.path ===
'/trials/trials-panel/setting/reading-unit' ||
item1.path ===
'/trials/trials-panel/setting/medical-audit' ||
item1.path === '/trials/trials-panel/setting/email-manage'))
"
:label="$t(item1.LanguageMark)"
:name="item1.path"
/>
<el-tab-pane v-if="TrialConfig && isShow(item1.path)" :key="`tab1${item1.path}`" :disabled="TotalNeedSignTrialDocCount !== 0 ||
(TrialStatusStr === 'Initializing' &&
(item1.path ===
'/trials/trials-panel/setting/personnel-manage' ||
item1.path === '/trials/trials-panel/setting/qc-question' ||
item1.path ===
'/trials/trials-panel/setting/reading-unit' ||
item1.path ===
'/trials/trials-panel/setting/medical-audit' ||
item1.path === '/trials/trials-panel/setting/email-manage'))
" :label="$t(item1.LanguageMark)" :name="item1.path" />
</template>
</el-tabs>
</el-tab-pane>
</el-tabs>
<div
style="
<div style="
position: absolute;
top: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
"
>
">
<trials-select />
<div>
<i class="iconfont" style="font-size: 30px; color: #ccc">&#xe680;</i>
</div>
<!-- 返回项目列表 -->
<div
class="my_icon_box"
:title="$t('trials:trials:title:backTrialList')"
@click="goBack"
>
<div class="my_icon_box" :title="$t('trials:trials:title:backTrialList')" @click="goBack">
<i class="iconfont">&#xe670;</i>
<!-- 返回 -->
<span>{{ $t("trials:trials:title:back") }}</span>
@@ -71,9 +47,8 @@
</template>
<script>
import { mapGetters } from "vuex";
import { getTrialSelect } from "@/api/trials";
import { getTrialSelect, getTrialInfoHir } from "@/api/trials";
import TrialsSelect from "@/components/TrialsSelect/index.vue";
import { getUserDocumentList } from "@/api/trials";
import store from "@/store";
export default {
name: "TrialsTab",
@@ -129,16 +104,11 @@ export default {
// document.cookie = 'TrialId=' + this.$route.query.trialId + ';path=/'
},
trialId(v) {
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(
getTrialInfoHir(this.trialId).then(
async (res) => {
var total = res.OtherInfo.NeedSignCount;
var TrialStatusStr = res.OtherInfo.TrialStatusStr;
this.IsAdditionalAssessment = res.OtherInfo.IsAdditionalAssessment;
var TrialStatusStr = res.Result.TrialStatusStr;
this.TrialStatusStr = TrialStatusStr;
await store.dispatch("user/setTotalNeedSignTrialDocCount", total);
await store.dispatch("user/setTrialStatusStr", TrialStatusStr);
this.TrialConfig = res.OtherInfo.TrialConfig;
this.IsAllOnlySRReading = res.OtherInfo.IsAllOnlySRReading;
}
);
},
@@ -150,16 +120,11 @@ export default {
if (~url.indexOf("?")) {
query = url.split("?")[1];
}
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(
getTrialInfoHir(this.$route.query.trialId).then(
async (res) => {
var total = res.OtherInfo.NeedSignCount;
var TrialStatusStr = res.OtherInfo.TrialStatusStr;
this.IsAdditionalAssessment = res.OtherInfo.IsAdditionalAssessment;
var TrialStatusStr = res.Result.TrialStatusStr;
this.TrialStatusStr = TrialStatusStr;
await store.dispatch("user/setTotalNeedSignTrialDocCount", total);
await store.dispatch("user/setTrialStatusStr", TrialStatusStr);
this.TrialConfig = res.OtherInfo.TrialConfig;
this.IsAllOnlySRReading = res.OtherInfo.IsAllOnlySRReading;
}
);
this.selectedTab();
@@ -260,7 +225,7 @@ export default {
this.options = res.Result;
this.tabTrialsId = this.$route.query.trialId;
})
.catch(() => {});
.catch(() => { });
},
selectedTab() {
var path = this.$route.path;
@@ -329,18 +294,23 @@ export default {
display: flex;
justify-content: center;
align-items: center;
&:hover {
color: #428bca;
}
span {
margin-left: 3px;
font-size: 14px;
}
}
.el-tabs__header {
margin-bottom: 3px;
}
position: relative;
.el-input--medium .el-input__inner {
height: 44px;
line-height: 44px;
@@ -349,16 +319,20 @@ export default {
text-align: right;
}
}
.base-model-wrapper {
.el-dialog__header {
padding: 10px;
.el-dialog__headerbtn {
top: 10px;
right: 10px;
}
}
.el-dialog__body {
padding: 10px 10px 10px 10px;
.base-modal-body {
min-height: 100px;
max-height: 650px;
@@ -367,6 +341,7 @@ export default {
border: 1px solid #e0e0e0;
}
}
.el-dialog__footer {
padding: 10px;
}
@@ -106,7 +106,7 @@ export default {
}
},
mounted() {
console.log('自定义上传组件', this)
// console.log('自定义上传组件', this)
},
data() {
return {
+1 -4
View File
@@ -70,10 +70,7 @@ export default {
if (!this.form.userRoleId)
return this.$message.warning(this.$t('toggleRole:ruleMessage:select'))
zzSessionStorage.removeItem('lastWorkbench')
this.$emit('save', {
UserId: this.form.userRoleId,
UserTypeId: this.roles.find(item => item.Id === this.form.userRoleId).UserTypeId
})
this.$emit('save', this.form.userRoleId)
} catch (err) {
console.log(err)
}
+3 -3
View File
@@ -9,16 +9,16 @@ const doResize = async (el, binding, vnode) => {
const { componentInstance: $table } = await vnode
// 获取调用传递过来的数据
const { value } = binding
if (value && value.notAdaptive) return;
// 获取距底部距离(用于展示页码等信息)
const bottomOffset = (value && value.bottomOffset) || 40
if (!$table) return
// 计算列表高度并设置
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
// $table.layout.setMaxHeight(height) bodyHeight
// $table.layout.setMaxHeight(height)
$table.layout.setHeight(height)
// $table.bodyWrapper.style.cssText = `height:${$table.layout.bodyHeight - 20}px`
// $table.maxHeight = height
let timer = setTimeout(() => { $table.doLayout(); timer = null; }, 500)
$table.doLayout()
}
export default {
+6 -4
View File
@@ -10,7 +10,7 @@ const dialogDrag = Vue.directive('dialogDrag', {
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = (function() {
const sty = (function () {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
@@ -47,8 +47,10 @@ const dialogDrag = Vue.directive('dialogDrag', {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
const oldMousemove = document.onmousemove
document.onmousemove = function(e) {
document.onmousemove = function (e) {
oldMousemove(e)
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
const top = e.clientY - disY
@@ -70,8 +72,8 @@ const dialogDrag = Vue.directive('dialogDrag', {
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = function (e) {
document.onmousemove = oldMousemove
document.onmouseup = null
}
}
+4 -5
View File
@@ -95,16 +95,15 @@ export default {
this.toggleRoleVisible = true
})
},
loginByRole(row) {
let { UserId, UserTypeId } = row
if (this.$store.state.user.userId === UserId) {
loginByRole(userRoleId) {
if (this.$store.state.user.userId === userRoleId) {
this.toggleRoleVisible = false
this.toggleRoleLoading = false
return false
}
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { UserId, UserTypeId })
.dispatch('user/loginByRole', { userRoleId })
.then((res) => {
if (res) {
this.$store
@@ -124,7 +123,7 @@ export default {
return
}
if (
this.hasPermi(['role:pm', 'role:oa', 'role:admin', 'role:dev'])
this.hasPermi(['role:pm', 'role:sa', 'role:admin', 'role:dev', 'role:ga'])
) {
history.replaceState(null, null, '/trials/trials-inspection')
history.go(0)
+22 -5
View File
@@ -3,7 +3,7 @@ import Vue from 'vue'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import ElementUI from 'element-ui'
import { getBasicDataAllSelect, getFrontInternationalizationList } from '@/api/dictionary/dictionary'
import { getBasicDataAllSelect, getFrontInternationalizationList, getCurrentPublishInfo } from '@/api/dictionary/dictionary'
import './assets/css/theme-blue/index.css' // 浅绿色主题
import './assets/css/iconfont/index.css' // 阿里巴巴图标库
import i18n from './lang'
@@ -15,7 +15,7 @@ Vue.use(vcrontab); //使用方式:
import App from './App'
import store from './store'
import router from './router'
import WHITELIST from "./utils/whiteList"
import '@/icons' // icon
import '@/permission' // permission control
import md5 from 'js-md5'
@@ -185,6 +185,9 @@ async function VueInit() {
zhMessages[v.Code] = v.ValueCN
enMessages[v.Code] = v.Value
})
// 获取版本信息
let PublishInfo = await getCurrentPublishInfo();
Vue.prototype.$version = PublishInfo.Result;
i18n.mergeLocaleMessage('zh', zhMessages)
i18n.mergeLocaleMessage('en', enMessages)
let d = function (code) {
@@ -248,6 +251,20 @@ async function VueInit() {
}()
_vm.$forceUpdate()
}
Vue.prototype.$reg = () => {
// if (localStorage.getItem('CompanyInfo')) {
// let { EmailRegexStr } = JSON.parse(localStorage.getItem('CompanyInfo'))
// if (EmailRegexStr) {
// return { EmailRegexStr }
// }
// } else if (Vue.prototype.$companyInfo) {
// let { EmailRegexStr } = Vue.prototype.$companyInfo
// if (EmailRegexStr) {
// return { EmailRegexStr }
// }
// }
return { EmailRegexStr: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' };
}
Vue.prototype.$path = []
var t = function (key) {
// if (![Vue.prototype.toPath + '_' + key].includes(Vue.prototype.$path)) {
@@ -278,7 +295,7 @@ async function VueInit() {
if (eval(process.env.VUE_APP_LOGIN_FOR_PERMISSION)) {
setInterval(() => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
if (_vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
if (WHITELIST.includes(_vm.$route.path)) {
return
}
if (_vm.$store.state.user.userId !== zzSessionStorage.getItem('userId')) {
@@ -338,7 +355,7 @@ async function VueInit() {
/* eslint-disable */
waitOperate(eval(process.env.VUE_APP_LOGOUT_FOR_PERMISSION) ? () => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
if (_vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/' || _vm.$route.path === '/login' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
if (WHITELIST.includes(_vm.$route.path)) {
count = 0;
localStorage.setItem('count', '0')
return
@@ -366,7 +383,7 @@ async function VueInit() {
} : () => { }, process.env.VUE_APP_LOGOUT_FOR_TIME,
eval(process.env.VUE_APP_LOCK_FOR_PERMISSION) ? () => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
if (_vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
if (WHITELIST.includes(_vm.$route.path)) {
count = 0;
localStorage.setItem('count', '0')
if (_vm.$route.path === '/login') {
+42 -19
View File
@@ -1,18 +1,19 @@
import router from './router'
import { resetRouter } from '@/router'
import store from './store'
// import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { getToken, removeToken } from '@/utils/auth'
import Vue from 'vue'
import { OSSclient } from './utils/oss'
import WHITELIST from './utils/whiteList'
import moment from "moment";
// import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false })
const whiteList = ['/activate', '/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
// 影像页关闭
const whiteList = WHITELIST
Vue.prototype.$openWindow = null
Vue.prototype.$setOpenWindow = (openWindow) => {
if (Vue.prototype.$openWindow) {
@@ -27,7 +28,7 @@ router.beforeEach(async (to, from, next) => {
Vue.prototype.$setOpenWindow();
// 设置页面标题
// document.title = getPageTitle(to.meta.title)
await OSSclient()
// 确定用户是否已登录
const hasToken = getToken()
Vue.prototype.toPath = to.path
@@ -35,19 +36,26 @@ router.beforeEach(async (to, from, next) => {
if (hasToken) {
if (to.path === '/login' || to.path === '/recompose' || to.path === '/email-recompose' || to.path === '/error' || to.path === '/ReviewersResearchForm' || to.path === '/ReviewersResearch') {
if (to.path === '/ReviewersResearch') {
OSSclient()
await this.$store.dispatch('user/logout')
await OSSclient()
await store.dispatch('user/logout')
}
if (to.path === '/ReviewersResearchForm') {
OSSclient()
}
if (to.path === '/login') {
OSSclient()
await OSSclient()
}
next()
NProgress.done()
} else if (from.path === '/researchForm') {
removeToken()
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()
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else {
OSSclient()
await OSSclient()
const hasGetUserInfo = store.getters.userId
if (hasGetUserInfo) {
next()
@@ -55,10 +63,13 @@ router.beforeEach(async (to, from, next) => {
try {
// 获取用户信息
await store.dispatch('user/getInfo')
await store.dispatch('user/getUserInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes')
resetRouter()
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} catch (error) {
console.log(error)
// 删除token并进入登录页面以重新登录
await store.dispatch('user/resetToken')
next(`/login?redirect=${to.path}`)
@@ -69,17 +80,29 @@ router.beforeEach(async (to, from, next) => {
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录whiteList中,直接进入
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading') {
OSSclient()
if (to.path === '/researchLogin') {
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}`)
} else {
next()
}
} else {
// 在免登录whiteList中,直接进入
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading') {
await OSSclient()
}
next()
}
if (to.path === '/login') {
OSSclient()
}
next()
} else {
if (to.path === '/researchForm') {
next(`/researchLogin?`)
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else if (to.path === '/researchDetail_m') {
const lang = to.query.lang || zzSessionStorage.getItem('lang')
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
NProgress.done()
} else if (to.path === '/ReviewersResearchForm') {
next(`/ReviewersResearch?`)
+6
View File
@@ -232,6 +232,12 @@ export const constantRoutes = [
// component: () => import('@/views/trials/audit'),
// hidden: true
// },
{
path: '/authorize',
component: () => import('@/views/authorize/index'),
name: 'Authorize',
hidden: true
},
{
path: '/error',
component: () => import('@/views/error'),
+3
View File
@@ -3,10 +3,12 @@ const getters = {
device: state => state.app.device,
token: state => state.user.token,
name: state => state.user.name,
userTypeShortName: state => state.user.userTypeShortName,
permissions: state => state.user.permissions,
tree: state => state.user.tree,
userName: state => state.user.userName,
userId: state => state.user.userId,
identityUserId: state => state.user.identityUserId,
routes: state => state.permission.routes,
asyncRoutes: state => state.permission.addRoutes,
visitedViews: state => state.tagsView.visitedViews,
@@ -41,6 +43,7 @@ const getters = {
lastCanvasTaskId: state => state.reading.lastCanvasTaskId,
imageQuality: state => state.reading.imageQuality,
imageQualityIssues: state => state.reading.imageQualityIssues,
currentLoadIns: state => state.reading.currentLoadIns,
language: state => state.lang.language,
TotalNeedSignSystemDocCount: state => state.user.TotalNeedSignSystemDocCount,
TotalNeedSignTrialDocCount: state => state.user.TotalNeedSignTrialDocCount,
+112 -1
View File
@@ -908,7 +908,118 @@ const actions = {
}
})
},
getKeySeries({ state }, obj) {
return new Promise(resolve => {
console.log('getKeySeries')
let { study, idx, visitTaskId } = obj
let data = null
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
var keyImages = []
if (study) {
data = {}
const series = study.SeriesList && study.SeriesList
series.map(i => {
i.InstanceInfoList.map(k => {
keyImages.push({ instanceId: k.Id })
})
})
data.StudyId = study.StudyId
data.StudyCode = study.StudyCode
data.Modalities = study.Modalities
data.SeriesCount = study.SeriesCount
data.InstanceCount = study.InstanceCount
data.InstanceCount = study.InstanceCount
data.IsDicom = study.IsDicom
data.PreviewImageCount = 0
data.IsCriticalSequence = study.IsCriticalSequence
var seriesList = []
study.SeriesList.forEach((series, seriesIndex) => {
const imageIds = []
const instanceList = []
series.InstanceInfoList.forEach(instance => {
if (instance.NumberOfFrames && instance.NumberOfFrames > 1) {
if (study.IsCriticalSequence && instance.KeyFramesList.length > 0) {
instance.KeyFramesList.map(i => {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${idx}|${seriesIndex}|${index}`
imageIds.push(imageId)
})
} else {
for (let i = 0; i < instance.NumberOfFrames; i++) {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${idx}|${seriesIndex}|${index}`
imageIds.push(imageId)
}
}
instance.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${0}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${idx}|${seriesIndex}|${index}`
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${idx}|${seriesIndex}|${index}`
imageIds.push(imageId)
instance.ImageId = imageId
}
if (!study.IsCriticalSequence && series.IsBeMark) {
const i = keyImages.findIndex(i => i.instanceId === instance.Id)
if (i > -1) {
keyImages[i].idx = idx
keyImages[i].seriesIndex = seriesIndex
}
}
instanceList.push(instance.Id)
})
seriesList.push({
isDicom: study.IsDicom,
imageIds: imageIds,
instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
seriesId: series.Id,
imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid,
seriesNumber: series.SeriesNumber,
sliceThickness: series.SliceThickness,
modality: series.Modality,
description: series.Description,
previewImageUrl: study.IsDicom ? series.ImageResizePath ? Vue.prototype.OSSclientConfig.basePath + series.ImageResizePath : `/api/series/preview/${series.Id}` : Vue.prototype.OSSclientConfig.basePath + `${series.NoneDicomFileFirstFile}`,
instanceCount: series.InstanceCount,
instanceHtmlPathList: series.InstanceHtmlPathList,
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: series.InstanceInfoList,
studyId: study.StudyId,
studyIndex: idx,
seriesIndex: seriesIndex,
studyCode: study.StudyCode,
taskBlindName: state.visitTaskList[index].TaskBlindName,
visitTaskId: obj.visitTaskId,
readingTaskState: state.visitTaskList[index].ReadingTaskState,
isBaseLineTask: state.visitTaskList[index].IsBaseLineTask,
isCurrentTask: state.visitTaskList[index].IsCurrentTask,
isExistsClinicalData: state.visitTaskList[index].IsExistsClinicalData,
isLoading: false,
isBeMark: series.IsBeMark,
ww: series.WindowWidth,
wc: series.WindowCenter,
isExistMutiFrames: series.IsExistMutiFrames
})
})
data.SeriesList = seriesList
}
let stateIndex = state.visitTaskList[index].StudyList.findIndex(item => item.IsCriticalSequence)
console.log(stateIndex, 'stateIndex')
if (data) {
if (!!~stateIndex) {
state.visitTaskList[index].StudyList.splice(stateIndex, 1, data)
} else {
state.visitTaskList[index].StudyList.unshift(data)
}
} else {
if (!!~stateIndex) {
state.visitTaskList[index].StudyList.splice(stateIndex, 1)
}
}
state.visitTaskList[index].studyListInit = true
state.visitTaskList[index].KeyImages = keyImages
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve(data)
})
},
updateStudyList({ state }, obj) {
return new Promise(resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
+86 -45
View File
@@ -1,5 +1,5 @@
import { getToken, setToken, removeToken, setName, removeName } from '@/utils/auth'
import { login, getUserMenuTree, getUserPermissions, loginSelectUserRole, TJUserLoginInfo } from '@/api/user'
import { login, loginOut, getUserMenuTree, getUserPermissions, loginSelectUserRole, getUserLoginRoleList, TJUserLoginInfo } from '@/api/user'
import { getUser } from '@/api/admin'
import { resetRouter } from '@/router'
import md5 from 'js-md5'
@@ -7,14 +7,17 @@ const getDefaultState = () => {
return {
token: getToken(),
name: '',
userTypeShortName: '',
userName: '',
userId: '',
identityUserId: '',
avatar: '',
permissions: [],
tree: [],
/* eslint-disable */
TotalNeedSignSystemDocCount: eval(process.env.VUE_APP_WORD_FOR_PERMISSION) ? null : 0,
TotalNeedSignTrialDocCount: eval(process.env.VUE_APP_WORD_FOR_PERMISSION) ? null : 0,
IsFirstSysDocNeedSign: false,
TrialStatusStr: null,
isTestUser: false,
roles: []
@@ -38,6 +41,9 @@ const mutations = {
SET_NAME: (state, name) => {
state.name = name
},
SET_USERTYPESHORTNAME: (state, userTypeShortName) => {
state.userTypeShortName = userTypeShortName
},
SET_USERNAME: (state, name) => {
state.userName = name
},
@@ -53,9 +59,16 @@ const mutations = {
SET_USERID: (state, id) => {
state.userId = id
},
SET_IDENTITYUSERID: (state, id) => {
state.identityUserId = id
},
SET_ISTESTUSER: (state, isTestUser) => {
state.isTestUser = eval(isTestUser)
},
SET_IS_FIRST_SYSTEM_DOC_SIGN: (state, IsFirstSysDocNeedSign) => {
zzSessionStorage.setItem('IsFirstSysDocNeedSign', IsFirstSysDocNeedSign)
state.IsFirstSysDocNeedSign = IsFirstSysDocNeedSign
},
SET_NEED_SIGN_SYSTEM_DOC_COUNT: (state, TotalNeedSignSystemDocCount) => {
/* eslint-disable */
if (eval(process.env.VUE_APP_WORD_FOR_PERMISSION) && !state.isTestUser) {
@@ -87,20 +100,29 @@ const actions = {
},
// user login
login({ commit }, userInfo) {
const { username, password } = userInfo
const { username, password, UserId } = userInfo
return new Promise((resolve, reject) => {
login({ UserName: username.trim(), Password: md5(password) }).then(async response => {
let data = {
UserName: username.trim(), Password: md5(password)
}
if (UserId) {
data.UserId = UserId;
}
getUserLoginRoleList(data).then(async response => {
if (response.IsSuccess) {
zzSessionStorage.removeItem('lastWorkbench')
zzSessionStorage.setItem('my_username', username.trim())
zzSessionStorage.setItem('my_password', md5(password))
zzSessionStorage.setItem('my_EMail', response.Result.BasicInfo.EMail)
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
const data = response.Result
if (data.BasicInfo.IsFirstAdd) {
commit('SET_ROLES', data.BasicInfo.AccountList)
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1) {
try {
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
zzSessionStorage.setItem('identityUserId', data.BasicInfo.IdentityUserId)
commit('SET_TOKEN', data.JWTStr)
setToken(data.JWTStr)
resolve(false)
resolve(response.Result)
} catch (e) {
console.log(e)
}
@@ -110,25 +132,24 @@ const actions = {
zzSessionStorage.setItem('IsReviewer', data.BasicInfo.IsReviewer)
zzSessionStorage.setItem('userName', data.BasicInfo.UserName)
commit('SET_TOKEN', data.JWTStr)
commit('SET_NAME', data.BasicInfo.RealName)
zzSessionStorage.setItem('realName', data.BasicInfo.RealName)
// commit('SET_NAME', data.BasicInfo.UserName)
zzSessionStorage.setItem('isTestUser', data.BasicInfo.IsTestUser)
commit('SET_ISTESTUSER', data.BasicInfo.IsTestUser)
commit('SET_USERNAME', data.BasicInfo.UserName)
commit('SET_USERID', data.BasicInfo.Id)
setToken(data.JWTStr)
setName(data.BasicInfo.RealName)
const userString = decodeURIComponent(escape(window.atob(data.JWTStr.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))))
const user = JSON.parse(userString)
zzSessionStorage.setItem('userTypeShortName', user.userTypeShortName)
zzSessionStorage.setItem('userId', user.id)
zzSessionStorage.setItem('userTypeEnumInt', user.userTypeEnumInt)
var permissions = await getUserPermissions()
var menuTree = await getUserMenuTree()
commit('SET_TREE', menuTree.Result)
commit('SET_PERMISSIONS', permissions.Result)
zzSessionStorage.setItem('newTree', JSON.stringify(menuTree.Result))
zzSessionStorage.setItem('permissions', JSON.stringify(permissions.Result))
// setName(data.BasicInfo.RealName)
// const userString = decodeURIComponent(escape(window.atob(data.JWTStr.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))))
// const user = JSON.parse(userString)
// zzSessionStorage.setItem('userId', user.identityUserId)
// commit('SET_IDENTITYUSERID', user.identityUserId)
// zzSessionStorage.setItem('identityUserId', user.identityUserId)
// zzSessionStorage.setItem('userTypeEnumInt', user.userTypeEnumInt)
// var permissions = await getUserPermissions()
// var menuTree = await getUserMenuTree()
// commit('SET_TREE', menuTree.Result)
// commit('SET_PERMISSIONS', permissions.Result)
// zzSessionStorage.setItem('newTree', JSON.stringify(menuTree.Result))
// zzSessionStorage.setItem('permissions', JSON.stringify(permissions.Result))
} catch (e) {
console.log(e)
}
@@ -161,29 +182,29 @@ const actions = {
})
},
loginByRole({ commit }, userInfo) {
const { UserId, UserTypeId } = userInfo
const { userRoleId } = userInfo
let params = {
UserId, UserTypeId
userRoleId
}
return new Promise((resolve, reject) => {
loginSelectUserRole(params).then(async response => {
if (response.IsSuccess) {
const data = response.Result.JWTStr
const data = response.Result
try {
commit('SET_TOKEN', data)
setToken(data)
commit('SET_USERID', UserId)
zzSessionStorage.setItem('userId', UserId)
commit('SET_USERID', userRoleId)
zzSessionStorage.setItem('userId', userRoleId)
const userString = decodeURIComponent(escape(window.atob(data.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))))
const user = JSON.parse(userString)
// return console.log(user, user.realName)
zzSessionStorage.setItem('userTypeShortName', user.userTypeShortName)
// commit('SET_USERTYPESHORTNAME', user.userTypeShortName)
commit('SET_NAME', user.realName)
setName(user.realName)
zzSessionStorage.setItem('realName', user.realName)
commit('SET_USERTYPESHORTNAME', user.userTypeShortName)
commit('SET_NAME', user.fullName)
setName(user.fullName)
commit('SET_IDENTITYUSERID', user.identityUserId)
zzSessionStorage.setItem('identityUserId', user.identityUserId)
zzSessionStorage.setItem('userTypeEnumInt', user.userTypeEnumInt)
var permissions = await getUserPermissions()
var menuTree = await getUserMenuTree()
@@ -211,6 +232,9 @@ const actions = {
setPermissions({ commit }, permissions) {
commit('SET_PERMISSIONS', permissions)
},
setIsFirstSysDocNeedSign({ commit }, IsFirstSysDocNeedSign) {
commit('SET_IS_FIRST_SYSTEM_DOC_SIGN', IsFirstSysDocNeedSign)
},
setTotalNeedSignSystemDocCount({ commit }, TotalNeedSignSystemDocCount) {
commit('SET_NEED_SIGN_SYSTEM_DOC_COUNT', TotalNeedSignSystemDocCount)
},
@@ -229,30 +253,47 @@ const actions = {
commit('SET_PERMISSIONS', JSON.parse(zzSessionStorage.getItem('permissions')))
commit('SET_ISTESTUSER', zzSessionStorage.getItem('isTestUser'))
const user = JSON.parse(userString)
commit('SET_NAME', zzSessionStorage.getItem('realName'))
commit('SET_USERID', user.id)
commit('SET_NAME', zzSessionStorage.getItem('Name'))
commit('SET_USERTYPESHORTNAME', user.userTypeShortName)
commit('SET_IDENTITYUSERID', user.identityUserId)
commit('SET_USERID', user.userRoleId)
commit('SET_USERNAME', zzSessionStorage.getItem('userName'))
commit('SET_NEED_SIGN_SYSTEM_DOC_COUNT', parseInt(zzSessionStorage.getItem('TotalNeedSignSystemDocCount')))
commit('SET_NEED_SIGN_TRIALS_DOC_COUNT', parseInt(zzSessionStorage.getItem('TotalNeedSignTrialDocCount')))
console.log(zzSessionStorage.getItem('TotalNeedSignSystemDocCount'))
console.log(zzSessionStorage.getItem('TotalNeedSignTrialDocCount'))
commit('SET_IS_FIRST_SYSTEM_DOC_SIGN', zzSessionStorage.getItem('IsFirstSysDocNeedSign'))
// console.log(zzSessionStorage.getItem('TotalNeedSignSystemDocCount'))
// console.log(zzSessionStorage.getItem('TotalNeedSignTrialDocCount'))
zzSessionStorage.setItem('userName', user.name)
zzSessionStorage.setItem('my_username', user.name)
zzSessionStorage.setItem('userId', user.id)
zzSessionStorage.setItem('userId', user.userRoleId)
zzSessionStorage.setItem('identityUserId', user.identityUserId)
zzSessionStorage.setItem('userTypeShortName', user.userTypeShortName)
zzSessionStorage.setItem('userTypeEnumInt', user.userTypeEnumInt)
return user
},
updateInfo({ commit, state }) {
commit('SET_NAME', zzSessionStorage.getItem('realName'))
commit('SET_NAME', zzSessionStorage.getItem('Name'))
},
// user logout
logout({ commit, state }) {
removeToken() // must remove token first
resetRouter()
removeName()
zzSessionStorage.clear()
commit('RESET_STATE')
async logout({ commit, state }) {
try {
removeToken() // must remove token first
let params = {}
if (zzSessionStorage.getItem('identityUserId')) {
params.IdentityUserId = zzSessionStorage.getItem('identityUserId')
}
if (zzSessionStorage.getItem('userId')) {
params.UserRoleId = zzSessionStorage.getItem('userId')
}
await loginOut(params)
resetRouter()
removeName()
let lang = zzSessionStorage.getItem('lang')
zzSessionStorage.clear()
zzSessionStorage.setItem('lang', lang)
commit('RESET_STATE')
} catch (e) {
console.log(e)
}
},
setToken({ commit }, token) {
commit('SET_TOKEN', token)
@@ -260,7 +301,7 @@ const actions = {
// 获取用户信息
getUserInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getUser(state.userId).then(res => {
getUser().then(res => {
if (res.Result) {
commit('SET_ROLES', res.Result.AccountList)
}
+7
View File
@@ -47,3 +47,10 @@
.el-range-separator {
box-sizing: content-box;
}
.el-select-dropdown__wrap {
max-height: 350px;
}
.el-checkbox__inner{
border: 1px solid #909399;
}
+175 -95
View File
@@ -9,7 +9,7 @@ body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
// font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
// font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
// "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial,
@@ -52,6 +52,7 @@ a:hover {
div:focus {
outline: none;
}
body .el-table th.gutter {
display: table-cell !important;
}
@@ -66,6 +67,13 @@ body .el-table th.gutter {
height: 0;
}
}
.text-ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.el-loading-mask {
background-color: rgba(255, 255, 255, 0.5);
}
@@ -80,6 +88,7 @@ body .el-table th.gutter {
.table-container {
height: calc(100% - 100px);
}
// .pagination-container{
// text-align: right;
// }
@@ -92,10 +101,12 @@ body .el-table th.gutter {
border-left: 3px solid #0fc8e0;
font-size: 13px;
margin-bottom: 10px;
p {
margin: 0;
padding-left: 5px;
}
.add {
position: absolute;
right: 10px;
@@ -104,9 +115,11 @@ body .el-table th.gutter {
margin-top: -15px;
}
}
.el-dialog__body {
padding: 0 10px;
}
.el-date-editor.el-input,
.el-date-editor.el-input__inner,
.el-select {
@@ -114,167 +127,234 @@ body .el-table th.gutter {
}
}
}
.data-list {
display: flex;
flex-direction: column;
flex: 1;
.toolbar {
display: flex;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination {
height: 32px;
text-align: right;
}
}
.is-fullscreen{
.el-dialog__headerbtn{
top:10px;
.is-fullscreen {
.el-dialog__headerbtn {
top: 10px;
font-size: 30px;
}
.el-dialog__body{
.el-dialog__body {
margin-top: 15px;
height: calc(100% - 70px);
padding: 0 20px;
.base-modal-body{
.base-modal-body {
padding: 10px 20px;
height: 100%;
overflow-y: auto;
}
}
.el-dialog__footer{
.el-dialog__footer {
padding: 10px;
}
.link-breadcrumb{
.link-breadcrumb {
cursor: pointer;
color: #428bca;
}
}
.base-dialog-wrapper{
.el-dialog__header{
.base-dialog-wrapper {
.el-dialog__header {
padding: 15px;
}
.base-dialog-body{
.base-dialog-body {
border: 1px solid #e0e0e0;
padding:10px;
max-height:600px;
padding: 10px;
max-height: 600px;
overflow-y: auto;
}
.base-dialog-footer{
text-align:right;
margin-top:10px;
.base-dialog-footer {
text-align: right;
margin-top: 10px;
}
.el-dialog__body{
padding:10px;
.el-dialog__body {
padding: 10px;
}
.el-dialog__footer{
padding: 10px;
.el-dialog__footer {
padding: 10px;
}
}
.el-descriptions{
box-sizing:border-box;
font-size:14px;
color:#303133
.el-descriptions {
box-sizing: border-box;
font-size: 14px;
color: #303133
}
.el-descriptions__header{
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:20px
.el-descriptions__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px
}
.el-descriptions__title{
font-size:16px;
font-weight:700
.el-descriptions__title {
font-size: 16px;
font-weight: 700
}
.el-descriptions__body{
color:#606266;
background-color:#fff
.el-descriptions__body {
color: #606266;
background-color: #fff
}
.el-descriptions__body .el-descriptions__table{
border-collapse:collapse;
width:100%;
table-layout:fixed
.el-descriptions__body .el-descriptions__table {
border-collapse: collapse;
width: 100%;
table-layout: fixed
}
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell{
box-sizing:border-box;
text-align:left;
font-weight:400;
line-height:1.5
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell {
box-sizing: border-box;
text-align: left;
font-weight: 400;
line-height: 1.5
}
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-left{
text-align:left
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-left {
text-align: left
}
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-center{
text-align:center
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-center {
text-align: center
}
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-right{
text-align:right
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-right {
text-align: right
}
.el-descriptions .is-bordered{
table-layout:auto
.el-descriptions .is-bordered {
table-layout: auto
}
.el-descriptions .is-bordered .el-descriptions-item__cell{
border:1px solid #ebeef5;
padding:12px 10px
.el-descriptions .is-bordered .el-descriptions-item__cell {
border: 1px solid #ebeef5;
padding: 12px 10px
}
.el-descriptions :not(.is-bordered) .el-descriptions-item__cell{
padding-bottom:12px
.el-descriptions :not(.is-bordered) .el-descriptions-item__cell {
padding-bottom: 12px
}
.el-descriptions--medium.is-bordered .el-descriptions-item__cell{
padding:10px
.el-descriptions--medium.is-bordered .el-descriptions-item__cell {
padding: 10px
}
.el-descriptions--medium:not(.is-bordered) .el-descriptions-item__cell{
padding-bottom:10px
.el-descriptions--medium:not(.is-bordered) .el-descriptions-item__cell {
padding-bottom: 10px
}
.el-descriptions--small{
font-size:12px
.el-descriptions--small {
font-size: 12px
}
.el-descriptions--small.is-bordered .el-descriptions-item__cell{
padding:8px 10px
.el-descriptions--small.is-bordered .el-descriptions-item__cell {
padding: 8px 10px
}
.el-descriptions--small:not(.is-bordered) .el-descriptions-item__cell{
padding-bottom:8px
.el-descriptions--small:not(.is-bordered) .el-descriptions-item__cell {
padding-bottom: 8px
}
.el-descriptions--mini{
font-size:12px
.el-descriptions--mini {
font-size: 12px
}
.el-descriptions--mini.is-bordered .el-descriptions-item__cell{
padding:6px 10px
.el-descriptions--mini.is-bordered .el-descriptions-item__cell {
padding: 6px 10px
}
.el-descriptions--mini:not(.is-bordered) .el-descriptions-item__cell{
padding-bottom:6px
.el-descriptions--mini:not(.is-bordered) .el-descriptions-item__cell {
padding-bottom: 6px
}
.el-descriptions-item{
vertical-align:top
.el-descriptions-item {
vertical-align: top
}
.el-descriptions-item__container{
display:flex
.el-descriptions-item__container {
display: flex
}
.el-descriptions-item__container .el-descriptions-item__content,.el-descriptions-item__container .el-descriptions-item__label{
display:inline-flex;
align-items:baseline
.el-descriptions-item__container .el-descriptions-item__content,
.el-descriptions-item__container .el-descriptions-item__label {
display: inline-flex;
align-items: baseline
}
.el-descriptions-item__container .el-descriptions-item__content{
flex:1
.el-descriptions-item__container .el-descriptions-item__content {
flex: 1
}
.el-descriptions-item__label.has-colon:after{
content:":";
position:relative;
top:-.5px
.el-descriptions-item__label.has-colon:after {
content: ":";
position: relative;
top: -.5px
}
.el-descriptions-item__label.is-bordered-label{
font-weight:700;
color:#909399;
background:#fafafa
.el-descriptions-item__label.is-bordered-label {
font-weight: 700;
color: #909399;
background: #fafafa
}
.el-descriptions-item__label:not(.is-bordered-label){
margin-right:10px
.el-descriptions-item__label:not(.is-bordered-label) {
margin-right: 10px
}
.el-descriptions-item__content{
word-break:break-word;
overflow-wrap:break-word
.el-descriptions-item__content {
word-break: break-word;
overflow-wrap: break-word
}
.feedBack-box {
.el-dialog__wrapper {
z-index: 3999 !important;
}
}
.feedBack-select-box {
z-index: 4000 !important;
}
.feedBack-box-modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .5;
background: #000;
z-index: 3999;
}
.el-message-box__wrapper {
z-index: 9999 !important;
}
+1 -1
View File
@@ -25,4 +25,4 @@
position: relative;
width: 100%;
height: 100%;
}
}
+36 -10
View File
@@ -1,13 +1,14 @@
$menuText:#909399;
$menuActiveText:#606266;
$subMenuActiveText:#5a5c5f;
$menuText: #909399;
$menuActiveText: #606266;
$subMenuActiveText: #5a5c5f;
$menuBg:#ebebeb;
$menuHover:#dfdede;
$menuBg: #ebebeb;
$menuHover: #dfdede;
$subMenuBg:#e4e4e4;
$subMenuHover:#dfdede;
$subMenuBg: #e4e4e4;
$subMenuHover: #dfdede;
$sideBarWidth: 200px;
#app {
.main-container {
@@ -71,13 +72,17 @@ $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;
}
}
@@ -85,15 +90,36 @@ $sideBarWidth: 200px;
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 {
@@ -216,4 +242,4 @@ $sideBarWidth: 200px;
border-radius: 20px;
}
}
}
}
+1 -1
View File
@@ -45,4 +45,4 @@
.breadcrumb-leave-active {
position: absolute;
}
}
+8 -8
View File
@@ -1,13 +1,13 @@
// sidebar 灰白色
$menuText:#909399;
$menuActiveText:#606266;
$subMenuActiveText:#5a5c5f;
$menuText: #909399;
$menuActiveText: #606266;
$subMenuActiveText: #5a5c5f;
$menuBg:#ebebeb;
$menuHover:#dfdede;
$menuBg: #ebebeb;
$menuHover: #dfdede;
$subMenuBg:#e4e4e4;
$subMenuHover:#dfdede;
$subMenuBg: #e4e4e4;
$subMenuHover: #dfdede;
// sidebar 墨绿色
// $menuText:rgb(206, 203, 203);
@@ -31,4 +31,4 @@ $sideBarWidth: 200px;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
}
+6 -5
View File
@@ -8,7 +8,7 @@ Vue.directive('dialogDrag', {
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = (function() {
const sty = (function () {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
@@ -40,8 +40,9 @@ Vue.directive('dialogDrag', {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
const oldMousemove = document.onmousemove
document.onmousemove = function (e) {
oldMousemove(e)
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let top = e.clientY - disY
@@ -62,8 +63,8 @@ Vue.directive('dialogDrag', {
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = function (e) {
document.onmousemove = oldMousemove
document.onmouseup = null
}
return false
+7 -7
View File
@@ -27,11 +27,11 @@ async function ossGenerateSTS() {
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
Vue.prototype.OSSclient = {
put: function (objectName, object) {
put: function (objectName, object, timestamp = true) {
return new Promise(async (resolve, reject) => {
try {
let _vm = router.default.app
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && timestamp) {
var objectItem = objectName.split('/')
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
objectName = objectItem.join('/')
@@ -40,7 +40,7 @@ async function ossGenerateSTS() {
if (res && res.url) {
resolve({
name: objectName,
url: res.url
url: res.url
})
} else {
reject()
@@ -56,12 +56,12 @@ async function ossGenerateSTS() {
case 'MinIO':
let minioClient = new Minio.Client(Vue.prototype.OSSclientConfig);
Vue.prototype.OSSclient = {
put: function (objectName, object) {
put: function (objectName, object, timestamp = true) {
return new Promise(async (resolve, reject) => {
try {
var name = objectName.split('/')[objectName.split('/').length - 1]
let _vm = router.default.app
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && timestamp) {
var objectItem = objectName.split('/')
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
objectName = objectItem.join('/')
@@ -69,9 +69,9 @@ async function ossGenerateSTS() {
const reader = new FileReader();
reader.onload = (ex) => {
const bufferStream = new stream.PassThrough()
bufferStream.end(Buffer.from(ex.target.result))
bufferStream.end(Buffer.from(ex.target.result))
// minioClient.bucketExists('ecgdata'
minioClient.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function(err,etag) {
minioClient.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function (err, etag) {
if (err) {
console.log(err)
reject()
+21 -2
View File
@@ -29,6 +29,21 @@ service.interceptors.request.use(
service.interceptors.response.use(
response => {
const res = response.data
let contentDisposition = response.headers['content-disposition']
if (contentDisposition) {
if (contentDisposition.includes('zip')) {
let fileName = contentDisposition.split('; ')[1].split('=')[1]
fileName = decodeURI(fileName)
const a = document.createElement('a')
const href = URL.createObjectURL(new Blob([res], { type: response.headers['content-type'] }))
a.download = fileName
a.href = href
a.click()
URL.revokeObjectURL(href)
return true
}
}
let fileReader = new FileReader();
fileReader.onload = function () {
try {
@@ -45,13 +60,17 @@ service.interceptors.response.use(
let contentDisposition = response.headers['content-disposition']
let fileName = ''
if (contentDisposition) {
fileName = contentDisposition.split('; ')[2].split('=')[1].split("\'")[2]
if (contentDisposition.includes('zip')) {
fileName = contentDisposition.split('; ')[1].split('=')[1]
} else {
fileName = contentDisposition.split('; ')[2].split('=')[1].split("\'")[2]
}
fileName = decodeURI(fileName)
}
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: response.headers['content-type'] }))
a.download = fileName
a.href = href
a.click()
+8 -7
View File
@@ -2,6 +2,7 @@ import axios from 'axios'
import { Message, MessageBox, Alert } from 'element-ui'
import store from '@/store'
import router from '@/router'
import WHITELIST from "./whiteList"
import Vue from 'vue'
const ROUTER = require('@/router');
axios.defaults.withCredentials = false
@@ -25,7 +26,7 @@ service.interceptors.request.use(
}
try {
if (eval(process.env.VUE_APP_LOGIN_FOR_PERMISSION)) {
if (!path || path === '/ReviewersResearchForm' || path === '/ReviewersResearch' || path === '/' || path === '/login' || path === '/researchForm' || path === '/researchLogin' || path === '/email-recompose' || path === '/recompose' || path === '/resetpassword' || path === '/error') {
if (!path || WHITELIST.some(item => item === path)) {
return config
}
if (store.state.user.userId !== zzSessionStorage.getItem('userId')) {
@@ -87,9 +88,9 @@ service.interceptors.response.use(
console.log(err)
}
router.push(`/login`)
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
// this.$i18n.locale = 'zh'
// this.setLanguage('zh')
// this.$updateDictionary()
})
}
switch (status) {
@@ -119,9 +120,9 @@ service.interceptors.response.use(
}
store.dispatch('user/logout').then(() => {
router.push(`/login`)
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
// this.$i18n.locale = 'zh'
// this.setLanguage('zh')
// this.$updateDictionary()
})
} else {
Message({
+88
View File
@@ -0,0 +1,88 @@
async function queryWindowManagement() {
return await navigator.permissions.query({ name: 'window-management' });;
}
async function getPermission() {
const permission = await queryWindowManagement();
console.log(permission.state, 'permission.state')
if (permission.state === "granted") { // 已经授权
return true
} else if (permission.state === "prompt") { // 询问是否授权
// 请求授权
if (navigator.permissions.request) {
navigator.permissions.request({ name: 'window-management' })
}
return false
} else if (permission.state === "denied") {
// 权限被拒绝
return false
}
}
function getScreen() {
return new Promise((resolve, reject) => {
let multiScreen = []
if (window.getScreenDetails) {
let getScreensProsime1 = window.getScreenDetails();
getScreensProsime1.then((c) => {
if (c instanceof Array) {
multiScreen = c
} else if (c instanceof Object) {
multiScreen = c.screens
} else {
multiScreen = []
}
resolve(multiScreen)
}).catch((err) => {
reject(err)
});
} else if (window.getScreens) {
let getScreensProsime = window.getScreens();
getScreensProsime.then((c) => {
if (c instanceof Array) {
multiScreen = c
} else if (c instanceof Object) {
multiScreen = c.screens
} else {
multiScreen = []
}
resolve(multiScreen)
}).catch((err) => {
reject(err)
})
}
})
}
export async function openWindow(url, name, Skip = false) {
// 判断浏览器是否兼容
// 高版本的谷歌,edge不支持跨屏,需要降低浏览器版本86.0版
if (!window.getScreens && !window.getScreenDetails) {
console.log('你的浏览器版本不支持多屏展示功能!');
return window.open(url, name);
}
let permission = await getPermission()
if (!permission) {
// alert('使用多屏功能请先进行授权')
if (Skip) {
return window.open(url, name);
}
return false
}
let multiScreen = await getScreen()
console.log(multiScreen, 'multiScreen')
// 判断是否2个屏幕
if (multiScreen.length < 2) {
console.log('请接入多个显示屏!');
return window.open(url, name);
}
console.log(screen, 'screen')
// 获取当前屏幕availLeft信息和所有信息比对,取另一个屏幕数据
let currentAvailLeft = screen.availLeft ? screen.availLeft : '0'
let newCurr = multiScreen.find((t) => t.availLeft != currentAvailLeft)
console.log(newCurr, 'newCurr')
let fulls = ''
for (let key in newCurr) {
fulls += `${key}=${(newCurr[key] || newCurr[key] === 0) ? newCurr[key] : 0},`
}
console.log(fulls, 'fulls')
return window.open(url, name, fulls);
}
+117 -2
View File
@@ -1,7 +1,122 @@
import streamSaver from "streamsaver";
import "streamsaver/examples/zip-stream.js";
import JSZip from 'jszip';
import FileSaver from 'file-saver';
import axios from 'axios'
// import store from '@/store'
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`
function getFile(url) {
return new Promise((resolve, reject) => {
axios.get(url, {
responseType: 'blob',
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
function addFilesRecursively(zip, structure) {
Object.keys(structure).forEach((key) => {
if (typeof structure[key] === "object" && !structure[key].size) {
// 创建子文件夹
const subFolder = zip.folder(key);
addFilesRecursively(subFolder, structure[key]);
} else {
// 添加文件
zip.file(key, structure[key], { binary: true });
}
});
};
function createFloders(obj, arr, r) {
let i = arr.shift()
if (arr.length <= 0) {
obj[i] = r
} else {
if (!obj[i]) {
obj[i] = {}
}
createFloders(obj[i], arr, r)
}
}
function downLoadFileConcurrency(obj, arr, callback) {
return new Promise(resolve => {
let list = arr.splice(0, 6)
let all = []
list.forEach(file => {
let res = getFile(file.url).then(r => {
const arr = file.name.split('/')
createFloders(obj, arr, r)
if (callback) {
callback({
type: 'downLoad',
data: r
})
}
// zip.file(fileName, r, { binary: true });
})
all.push(res)
})
Promise.all(all).then(async () => {
if (arr.length <= 0) {
resolve(true)
} else {
let res = await downLoadFileConcurrency(obj, arr, callback)
resolve(res)
}
}).catch(err => {
if (callback) {
callback({
type: 'error'
})
}
console.log(err)
})
})
}
function zipFilesJsZip(zipName, files, obj = {}, callback) {
return new Promise(async resolve => {
try {
if (callback) {
callback({
type: 'start'
})
}
console.log("同步下载打包开始时间:" + new Date());
files = formatFiles(files)
const zip = new JSZip();
// let all = []
let res = await downLoadFileConcurrency(obj, files, callback)
if (res) {
if (callback) {
callback({
type: 'downLoaded',
})
}
addFilesRecursively(zip, obj)
zip.generateAsync({
type: "blob",
compression: "DEFLATE", // STORE:默认不压缩 DEFLATE:需要压缩
compressionOptions: {
level: 9 // 压缩等级1~9 1压缩速度最快,9最优压缩方式
}
}).then((res) => {
if (callback) {
callback({
type: 'zipEnd',
})
}
console.log("同步下载打包结束时间:" + new Date());
FileSaver.saveAs(res, zipName) // 利用file-saver保存文件
}).catch(err => {
console.log("打包失败", err)
})
}
} catch (err) {
console.log(err)
}
})
}
// 下载文件并压缩
function zipFiles(zipName, files) {
return new Promise((resolve) => {
@@ -99,8 +214,8 @@ function decodeUtf8(bytes) {
str2.pop();
return str2.join("/") + '/' + name;
}
export async function downLoadFile(file, name, type = 'file') {
if (type === 'zip') return await zipFiles(name, file);
export async function downLoadFile(file, name, type = 'file', callback) {
if (type === 'zip') return await zipFilesJsZip(name, file, {}, callback);
return await updateFile(file, name)
}
+2
View File
@@ -0,0 +1,2 @@
const WHITELIST = ['/', "/activate", "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms', '/authorize']
export default WHITELIST
+298
View File
@@ -0,0 +1,298 @@
<template>
<el-form class="authorize_form" ref="activateProjectForm" :model="form" :rules="rules" size="small"
:label-width="isEN ? '200px' : '120px'">
<div class="base-dialog-body">
<p class="title">{{ $t("trials:activate:ApplyMessage") }}</p>
<!-- 单位名称 -->
<el-form-item :label="$t('trials:trials-list:activate:organizationName')">
<el-input v-model="form.HospitalName" />
</el-form-item>
<!-- 机构编码 -->
<el-form-item :label="$t('trials:trials-list:activate:hospitalCode')">
<el-input v-model="form.HospitalCode" />
</el-form-item>
<!-- 项目编号 -->
<el-form-item :label="$t('trials:trials-list:table:trialId')">
<el-input v-model="form.TrialCode" />
</el-form-item>
<!-- 评估标准 -->
<el-form-item :label="$t('trials:trials-list:activate:evaluationCriteria')">
<el-select v-model="form.CriterionTypeList" multiple clearable>
<el-option v-for="item of criterionTypeList" :key="item.Id" :label="item.CriterionName"
:value="item.CriterionType" :title="item.Description" />
</el-select>
</el-form-item>
<!-- 项目码 -->
<el-form-item :label="$t('trials:trials-list:table:trialGuid')">
<el-input v-model="form.TrialId" />
</el-form-item>
<!-- 机器码 -->
<el-form-item :label="$t('trials:trials-list:table:CreateUserId')">
<el-input v-model="form.CreateUserId" />
</el-form-item>
<!-- 购买时长 -->
<el-form-item :label="$t('trials:trials-list:activate:purchaseDuration')">
<el-input-number v-model="form.PurchaseDuration" @change="handleChange" :min="0" :max="100"
step-strictly></el-input-number>
</el-form-item>
<!-- 授权码 -->
<el-form-item :label="$t('trials:trials-list:form:authorizationCode')">
<p v-if="form.Authorization" class="AuthorizationBox">
<span class="Authorization" :title="form.Authorization">{{
form.Authorization
}}</span>
<span class="copy" @click.stop="copy">{{
$t("trials:trials-list:action:copy")
}}</span>
<span class="copy" style="margin-left: 10px" @click.stop="getCode">{{ $t("trials:reading:button:download")
}}</span>
</p>
</el-form-item>
</div>
</el-form>
</template>
<script>
import {
activateTrial,
getTrialAuthorizationCode,
getTrialAuthorizationInfo,
getActivationCodeInfo,
getSystemConfirmedCreiterionList
} from "@/api/trials.js";
import { fileDownload } from "@/utils/uploadZip.js";
export default {
name: "authorize",
data() {
return {
form: {
Authorization: null, // 授权码
Activate: null, // 激活码
TrialId: null,
TrialCode: null,
PurchaseDuration: null,
HospitalName: null,
CriterionTypeList: [],
CreateUserId: null,
HospitalCode: null,
AuthorizationDeadLineDate: null,
},
criterionTypeList: [],
btnLoading: false,
rules: {
Activate: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
},
],
},
isActivate: false,
timer: null,
};
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
}
},
created() {
this.getSystemConfirmedCreiterionList();
// this.getTrialAuthorizationInfo();
},
destroyed() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
},
methods: {
// 购买时长变更
async handleChange() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
this.timer = setTimeout(() => {
this.getTrialAuthorizationCode();
clearTimeout(this.timer);
this.timer = null;
}, 500);
},
// 获取授权信息
async getTrialAuthorizationInfo() {
if (!this.form.TrialId) return
try {
let params = {
TrialId: this.form.TrialId,
};
let res = await getTrialAuthorizationInfo(params);
if (res.IsSuccess) {
Object.keys(this.form).forEach((key) => {
this.form[key] = res.Result[key];
});
this.getTrialAuthorizationCode();
}
} catch (err) {
console.log(err);
}
},
// 获取授权码
async getTrialAuthorizationCode() {
if (!this.form.TrialId) return
let params = {
TrialId: this.form.TrialId,
TrialCode: this.form.TrialCode,
PurchaseDuration: this.form.PurchaseDuration,
HospitalName: this.form.HospitalName,
CriterionTypeList: this.form.CriterionTypeList,
CreateUserId: this.form.CreateUserId,
HospitalCode: this.form.HospitalCode,
};
try {
let res = await getTrialAuthorizationCode(params);
if (res.IsSuccess) {
this.form.Authorization = res.Result;
return true;
}
return false;
} catch (err) {
console.log(err);
return false;
}
},
// 获取阅片标准
async getSystemConfirmedCreiterionList() {
try {
let res = await getSystemConfirmedCreiterionList();
if (res.IsSuccess) {
this.criterionTypeList = res.Result;
}
} catch (err) {
console.log(err);
}
},
// 激活
async handleSave() {
if (!this.isActivate) return;
try {
let validate = this.$refs.activateProjectForm.validate();
if (!validate) return;
let params = {
TrialId: this.data.TrialId,
ActivationCode: this.form.Activate,
};
this.btnLoading = true;
let res = await activateTrial(params);
this.btnLoading = false;
if (res.IsSuccess) {
this.$message.success(
this.$t("trials:trials-list:action:activateSuccessfully")
);
this.$emit("getList");
this.handleCancel();
}
} catch (err) {
this.btnLoading = false;
console.log(err);
}
},
// 复制
copy() {
this.$copyText(this.form.Authorization)
.then((res) => {
// 复制成功
this.$message.success(
this.$t("trials:researchRecord:message:copySuccessfully")
);
})
.catch(() => {
// 复制失败
this.$alert(this.$t("trials:researchRecord:message:copyFailed"));
});
},
// 下载
async getCode() {
fileDownload(
this.form.Authorization,
this.form.TrialCode + "_Request_Code.req"
);
},
// 上传并读取文件
uploadFile(file) {
let input = file.target;
const reader = new FileReader();
reader.readAsText(input.files[0], "utf8"); // input.files[0]为第一个文件
reader.onload = () => {
this.form.Activate = reader.result; // reader.result为获取结果
input.value = null;
};
},
// 获取激活码信息
async getActivationCodeInfo() {
try {
let params = {
ActivationCode: this.form.Activate,
};
let res = await getActivationCodeInfo(params);
if (res.IsSuccess) {
if (res.IsSuccess) {
Object.keys(this.ActivateData).forEach((key) => {
this.ActivateData[key] = res.Result[key];
});
}
this.isActivate = true;
}
} catch (err) {
console.log(err);
}
},
},
};
</script>
<style lang="scss" scoped>
.authorize_form {
width: 60%;
padding: 20px;
}
::v-deep .el-dialog__body {
padding-bottom: 10px;
padding-top: 0;
}
.Authorization {
width: 70%;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.el-form-item__content {
.el-input {
width: 60%;
}
}
.copy {
cursor: pointer;
color: #409eff;
}
.AuthorizationBox {
padding: 0;
margin: 0;
display: flex;
align-items: center;
}
.title {
font-size: 16px;
font-weight: bold;
}
::v-deep .el-form-item__label {
font-weight: bold;
}
</style>
@@ -0,0 +1,273 @@
<template>
<el-form ref="sysTemplateFrom" v-loading="loading" :model="form" label-width="140px" size="small" :rules="rules"
class="upload-temporary-file">
<div class="base-dialog-body">
<el-form-item :label="$t('dictionary:attachment:label:code')" prop="Code">
<el-input v-model="form.Code" :disabled="fileList.length > 0" />
</el-form-item>
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')" prop="BusinessScenarioEnum">
<el-select v-model="form.BusinessScenarioEnum" style="width: 100%" size="small" filterable>
<el-option v-for="item of $d.Common_File_BusinessScenario" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('dictionary:attachment:label:file')">
<div class="upload-container">
<el-upload class="upload-demo" action accept="" :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.FileTypeEnum && form.FileTypeEnum !== 0) || (!form.Code || (form.Code && !codeReg.test(form.Code))))">
<el-button size="small" type="primary"
:disabled="((!form.FileTypeEnum && form.FileTypeEnum !== 0) || (!form.Code || (form.Code && !codeReg.test(form.Code))))"
:loading="btnLoading">Select</el-button>
<!-- <span slot="tip" style="margin-left: 10px" class="el-upload__tip">
(must be in xlsx/xls/doc/docx format)
</span> -->
</el-upload>
</div>
</el-form-item>
<el-form-item :label="$t('dictionary:attachment:label:name')" prop="Name">
<el-input v-model="form.Name" />
</el-form-item>
<el-form-item :label="$t('dictionary:attachment:export:form:nameCN')" prop="NameCN">
<el-input v-model="form.NameCN" />
</el-form-item>
<el-form-item v-if="form.Id !== ''" :label="$t('dictionary:attachment:label:isDeleted')">
<el-radio-group v-model="form.IsDeleted">
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="item.id">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('dictionary:attachment:label:description')">
<el-input v-model="form.Description" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" />
</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.FileTypeEnum && form.FileTypeEnum !== 0)"
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script>
import {
addOrUpdateCommonDocument,
uploadCommonDoc,
Upload,
} from '@/api/dictionary'
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
export default {
name: 'TemplateForm',
props: {
data: {
type: Object,
default() {
return {}
},
},
},
data() {
return {
form: {
Id: '',
Code: '',
FileTypeEnum: 0,
BusinessScenarioEnum: null,
Name: '',
NameCN: '',
Path: '',
Description: '',
IsDeleted: false,
},
codeReg: /^[a-zA-Z_]+$/,
rules: {
Code: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
{
validator: (rule, value, callback) => {
if (value && !this.codeReg.test(value)) {
callback(new Error(this.$t('common:ruleMessage:codeRule')));
} else {
callback();
}
},
trigger: 'blur'
}
],
Name: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
NameCN: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
BusinessScenarioEnum: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
},
fileList: [],
btnLoading: false,
saveBtnLoading: false,
loading: false,
dictionaryList: {},
}
},
mounted() {
this.initForm()
},
methods: {
async initForm() {
await this.getDicData()
if (Object.keys(this.data).length > 0) {
if (this.data.Path) {
this.fileList = [
{
name: this.data.Name,
path: this.data.Path,
url: this.data.Path,
type: this.data.Type,
},
]
}
for (const k in this.form) {
if (this.data.hasOwnProperty(k)) {
this.form[k] = this.data[k]
}
}
}
},
// 获取文件类型下拉框
getDicData() {
this.loading = true
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type'])
.then((res) => {
this.dictionaryList = { ...res.Result }
this.loading = false
})
.catch(() => {
this.loading = false
})
},
beforeUpload(file) {
// 检测文件类型是否符合要求
if (this.checkFileSuffix(file.name)) {
this.fileList = []
return true
} else {
this.$alert(this.$t('dictionary:attachment:export:alert:formatFile'))
return false
}
},
async handleUploadFile(param) {
this.loading = true
this.form.FileName = param.file.name
let extendName = param.file.name
.substring(param.file.name.lastIndexOf('.'))
.toLocaleLowerCase()
let file = await this.fileToBlob(param.file)
let res = await this.OSSclient.put(`/System/Tools/${this.form.Code}${extendName}`, file, false)
this.form.Path = this.$getObjectName(res.url)
this.form.NameCN = param.file.name
this.fileList.push({
name: param.file.name,
path: this.form.Path,
fullPath: this.form.Path,
url: this.form.Path,
})
this.loading = false
this.btnLoading = false
},
fileToBlob(file) {
// 创建 FileReader 对象
const reader = new FileReader()
return new Promise((resolve) => {
// FileReader 添加 load 事件
reader.addEventListener('load', (e) => {
let blob
if (typeof e.target.result === 'object') {
blob = new Blob([e.target.result])
} else {
blob = e.target.result
}
resolve(blob)
})
// FileReader 以 ArrayBuffer 格式 读取 File 对象中数据
reader.readAsArrayBuffer(file)
})
},
handleSave() {
this.$refs.sysTemplateFrom.validate((valid) => {
if (!valid) return
if (!this.form.Name) {
this.$alert(this.$t('dictionary:attachment:message:msg1'))
return
}
this.saveBtnLoading = true
addOrUpdateCommonDocument(this.form)
.then((res) => {
this.saveBtnLoading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success(this.$t('common:message:savedSuccessfully'))
})
.catch(() => {
this.saveBtnLoading = false
})
})
},
handleRemoveFile() {
this.fileList = []
this.form.Path = ''
this.form.NameCN = ''
this.form.Name = ''
},
handlePreview(file) {
if (file.fullPath) {
window.open(file.fullPath, '_blank')
}
},
handleExceed(files, fileList) {
this.$message.warning(this.$t('upload:rule:maxFile1'))
},
checkFileSuffix(fileName) {
return true
var typeArr = ['xls', 'xlsx', 'doc', 'docx']
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>
@@ -0,0 +1,238 @@
<template>
<BaseContainer>
<template slot="search-container">
<el-form :inline="true" size="small">
<!-- 业务场景 -->
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')">
<el-select v-model="searchData.BusinessScenarioEnum" style="width: 150px">
<el-option v-for="item of $d.Common_File_BusinessScenario" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<!-- 文件名称 -->
<el-form-item :label="$t('dictionary:attachment:label:name')">
<el-input v-model="searchData.Name" style="width: 130px" clearable />
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
<el-button type="primary" style="float: right" size="small" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</el-form>
</template>
<template slot="main-container">
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" stripe height="100"
@sort-change="handleSortChange">
<el-table-column type="index" width="40" />
<el-table-column prop="Code" :label="$t('dictionary:attachment:label:code')" show-overflow-tooltip
sortable="custom" />
<!-- 业务场景 -->
<el-table-column prop="BusinessScenarioEnum" :label="$t('dictionary:attachment:label:businessScenario')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
{{
$fd(
'Common_File_BusinessScenario',
scope.row.BusinessScenarioEnum
)
}}
</template>
</el-table-column>
<!-- 文件名称 -->
<el-table-column prop="Name" :label="$t('dictionary:attachment:label:name')" show-overflow-tooltip
sortable="custom" />
<el-table-column prop="NameCN" :label="$t('dictionary:attachment:upload:table:nameCN')" show-overflow-tooltip
sortable="custom" />
<!-- 描述 -->
<el-table-column prop="Description" :label="$t('dictionary:attachment:label:description')"
show-overflow-tooltip />
<!-- 是否废除 -->
<el-table-column prop="IsDeleted" :label="$t('dictionary:attachment:label:isDeleted')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
$fd('YesOrNo', scope.row.IsDeleted)
}}</el-tag>
<el-tag v-else type="primary">{{
$fd('YesOrNo', scope.row.IsDeleted)
}}</el-tag>
</template>
</el-table-column>
<!-- 上传时间 -->
<el-table-column prop="UpdateTime" :label="$t('dictionary:attachment:label:updateTime')" show-overflow-tooltip
sortable="custom" />
<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') }}
</el-button> -->
<el-button type="text" @click="handleDownload(scope.row)">
{{ $t('common:button:download') }}
</el-button>
<el-button type="text" @click="handleEdit(scope.row)">
{{ $t('common:button:edit') }}
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<!-- 新增/编辑 -->
<el-dialog v-if="editDialog.visible" :visible.sync="editDialog.visible" :close-on-click-modal="false"
:title="editDialog.title" width="600px" custom-class="base-dialog-wrapper">
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
</template>
</BaseContainer>
</template>
<script>
import {
getCommonDocumentList,
DownloadCommonDoc,
deleteCommonDocument,
} from '@/api/dictionary'
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import TemplateForm from './TemplateForm'
import { downLoadFile } from '@/utils/stream.js'
const FileTypeEnum = 0
const searchDataDefault = () => {
return {
FileTypeEnum: FileTypeEnum,
BusinessScenarioEnum: null,
Name: '',
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: 'ToolsTemplate',
components: { BaseContainer, Pagination, TemplateForm },
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
currentRow: {},
editDialog: { title: '', visible: false },
loading: false,
}
},
mounted() {
this.getList()
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
},
methods: {
handleDelete(row) {
// 确定删除该模版?
this.$confirm(this.$t('dictionary:attachment:message:msg1')).then(() => {
deleteCommonDocument(row.Id).then(() => {
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.getList()
})
}).catch(() => { })
},
PreviewFile(row) {
let basePath = window.location.origin
if (window.location.protocol !== 'https:') {
basePath = 'https://irc.test.extimaging.com'
}
let data = {
name: row.NameCN,
path: basePath + row.Path,
}
this.$emit('PreviewFile', data)
},
getList() {
this.loading = true
getCommonDocumentList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
// 新增
handleAdd() {
this.editDialog.title = this.$t('common:button:new')
this.currentRow = { FileTypeEnum: FileTypeEnum }
this.editDialog.visible = true
},
// 下载
async handleDownload(row) {
try {
this.loading = true
let fileName = this.isEN ? row.Name : row.NameCN;
let type = fileName
.substring(fileName.lastIndexOf('.'))
.toLocaleLowerCase()
if (!type) {
let extendName = row.Path
.substring(row.Path.lastIndexOf('.'))
.toLocaleLowerCase()
fileName += extendName
}
let res = await downLoadFile(this.OSSclientConfig.basePath + row.Path, fileName)
this.loading = false
} catch (err) {
this.loading = false
}
},
// 编辑
handleEdit(row) {
this.editDialog.title = this.$t('common:button:edit')
this.currentRow = { ...row }
this.editDialog.visible = true
},
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
closeDialog() {
this.editDialog.visible = false
},
// 排序
handleSortChange(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>
::v-deep .search {
display: block;
}
</style>
+13 -8
View File
@@ -1,12 +1,13 @@
<template>
<div class="attachment-wrapper">
<el-tabs v-model="activeTab" @tab-click="clickTab">
<el-tab-pane v-for="item in $d.Common_File_Type.filter(v => v.value !== 3 && v.value !== 4)" :key="item.value" :label="item.label" :name="String(item.value)">
<el-tab-pane v-for="item in $d.Common_File_Type" :key="item.value" :label="item.label" :name="String(item.value)">
<UploadTemplate v-if="activeTab === '1'" />
<ExportTemplate v-if="activeTab === '2'" />
<EmailTemplate v-if="activeTab === '3'" />
<CommonTemplate v-if="activeTab === '4'" />
<SignatureTemplate v-if="activeTab === '5'" />
<ToolsTemplate v-if="activeTab === '0' && item.value == activeTab" />
</el-tab-pane>
</el-tabs>
</div>
@@ -17,6 +18,7 @@ import ExportTemplate from './components/ExportTemplate'
import EmailTemplate from './components/EmailTemplate'
import CommonTemplate from './components/CommonTemplate'
import SignatureTemplate from './components/SignatureTemplate'
import ToolsTemplate from './components/ToolsTemplate'
export default {
name: 'Attachment',
components: {
@@ -24,7 +26,8 @@ export default {
ExportTemplate,
EmailTemplate,
CommonTemplate,
SignatureTemplate
SignatureTemplate,
ToolsTemplate
},
data() {
return {
@@ -46,22 +49,24 @@ export default {
}
</script>
<style lang="scss">
.attachment-wrapper{
.el-tabs{
.attachment-wrapper {
.el-tabs {
height: 100%;
display: flex;
flex-direction: column;
}
.el-tabs__header {
height: 40px;
margin-bottom:5px;
margin-bottom: 5px;
}
.el-tabs__content{
.el-tabs__content {
flex: 1;
.el-tab-pane{
.el-tab-pane {
height: 100%;
}
}
}
</style>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -59,7 +59,9 @@
<el-form-item label="文件名" prop="Name">
<el-input v-model="form.Name" />
</el-form-item>
<el-form-item label="阅片标准: " prop="CriterionTypeEnum">
<el-form-item
:label="$t('trials:auditRecord:table:criterion')"
prop="CriterionTypeEnum">
<el-select
v-model="form.CriterionTypeEnum"
style="width:100%;"
@@ -77,7 +79,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="描述">
@@ -206,7 +208,7 @@ export default {
this.loading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success('保存成功!')
this.$message.success(this.$t('common:message:savedSuccessfully'))
}).catch(() => {
this.loading = false
})
@@ -82,7 +82,7 @@
/>
<el-table-column
prop="CriterionTypeEnum"
label="阅片标准"
:label="$t('trials:auditRecord:table:criterion')"
show-overflow-tooltip
sortable="custom"
>
@@ -1,218 +1,247 @@
<template>
<el-form
ref="emailForm"
v-loading="loading"
:model="form"
label-width="180px"
size="small"
:rules="rules"
>
<el-form ref="emailForm" v-loading="loading" :model="form" label-width="180px" size="small" :rules="rules">
<el-row>
<el-col :span="24">
<!-- Code -->
<el-form-item label="Code: " prop="Code">
<el-input style="width: 300px" v-model="form.Code" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮件主题(CN" prop="EmailTopicCN">
<!-- 邮件主题CN -->
<el-form-item :label="$t('trials:emailManageCfg:table:EmailTopicCN')" prop="EmailTopicCN">
<el-input style="width: 300px" v-model="form.EmailTopicCN" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮件主题(EN" prop="EmailTopic">
<!-- 邮件主题EN -->
<el-form-item :label="$t('trials:emailManageCfg:table:EmailTopic')" prop="EmailTopic">
<el-input style="width: 300px" v-model="form.EmailTopic" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="业务层级" prop="BusinessLevelEnum">
<!-- 邮件延时发送s数 -->
<el-form-item :label="$t('dictionary:email:label:emailDelaySeconds')" prop="EmailDelaySeconds">
<el-input v-model.number="form.EmailDelaySeconds" style="width: 300px" type="number" clearable>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 业务层级 -->
<el-form-item :label="$t('dictionary:email:label:businessLevel')" prop="BusinessLevelEnum">
<el-select v-model="form.BusinessLevelEnum" clearable class="mr">
<el-option
v-for="item of $d.BusinessLevel"
:key="`BusinessLevel${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item of $d.BusinessLevel" :key="`BusinessLevel${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="业务模块" prop="BusinessModuleEnum">
<!-- 业务模块 -->
<el-form-item :label="$t('dictionary:email:label:businessModule')" prop="BusinessModuleEnum">
<el-select v-model="form.BusinessModuleEnum" clearable class="mr">
<el-option
v-for="item of $d.BusinessModule"
:key="`BusinessModule${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item of $d.BusinessModule" :key="`BusinessModule${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="业务场景" prop="BusinessScenarioEnum">
<!-- 业务场景 -->
<el-form-item :label="$t('trials:emailManageCfg:table:BusinessScenarioEnum')" prop="BusinessScenarioEnum">
<el-select v-model="form.BusinessScenarioEnum" clearable class="mr">
<el-option
v-for="item of $d.Email_BusinessScenario"
:key="`BusinessScenarioEnum${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item of $d.Email_BusinessScenario" :key="`BusinessScenarioEnum${item.label}`"
:label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收件人" prop="ToUserTypeList">
<!-- 收件人 -->
<el-form-item :label="$t('trials:emailManageCfg:title:toUserTypeList')" prop="ToUserTypeList">
<el-select v-model="form.ToUserTypeList" clearable multiple class="mr">
<el-option
v-for="item of $d.UserType"
:key="`ToUserTypeList${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item of $d.UserType" :key="`ToUserTypeList${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="抄送人" prop="CopyUserTypeList">
<!-- 抄送人 -->
<el-form-item :label="$t('trials:emailManageCfg:title:copyUserTypeList')" prop="CopyUserTypeList">
<el-select v-model="form.CopyUserTypeList" clearable multiple class="mr">
<el-option
v-for="item of $d.UserType"
:key="`CopyUserTypeList${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item of $d.UserType" :key="`CopyUserTypeList${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="加急状态" prop="EmailUrgentEnum">
<el-select v-model="form.EmailUrgentEnum" @change="(v) => {v === 1 ? form.EmailCron = null : null}" clearable class="mr">
<el-option
v-for="item of $d.EmailUrgent"
:key="`EmailUrgent${item.label}`"
:label="item.label"
:value="item.value"
/>
<!-- 加急状态 -->
<el-form-item :label="$t('dictionary:email:label:IsUrgent')" prop="EmailUrgentEnum">
<el-select v-model="form.EmailUrgentEnum" @change="
(v) => {
v === 1 ? (form.EmailCron = null) : null
}
" clearable class="mr">
<el-option v-for="item of $d.EmailUrgent" :key="`EmailUrgent${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发送周期和时间" v-if="form.EmailUrgentEnum !== 1" prop="EmailCron">
<!-- 发送周期和时间 -->
<el-form-item :label="$t('trials:emailManageCfg:table:EmailCron')" v-if="form.EmailUrgentEnum !== 1"
prop="EmailCron">
<el-input style="width: 300px" readonly v-model="form.EmailCron" />
<el-button type="primary" @click="showDialog">生成 cron</el-button>
<!-- 生成 cron -->
<el-button type="primary" @click="showDialog"> {{ $t('dictionary:email:button:cron') }} </el-button>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否需要回执" prop="IsReturnRequired">
<!-- 是否需要回执 -->
<el-form-item :label="$t('trials:emailManageCfg:title:isReturnRequired')" prop="IsReturnRequired">
<el-radio-group v-model="form.IsReturnRequired">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="`IsReturnRequired${item.value}`">{{
item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否自动发送" prop="IsAutoSend">
<!-- 是否自动发送 -->
<el-form-item :label="$t('trials:emailManageCfg:table:IsAutoSend')" prop="IsAutoSend">
<el-radio-group v-model="form.IsAutoSend">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="`IsAutoSend${item.value}`">{{ item.label
}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="systemLevel">
<!-- 是否区分标准 -->
<el-form-item :label="$t('dictionary:email:button:isDistinguishCriteria')" prop="IsDistinguishCriteria">
<el-radio-group v-model="form.IsDistinguishCriteria" @change="
() => {
form.CriterionTypeEnum = null
}
">
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="`IsDistinguishCriteria${item.value}`">{{
item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否区分标准" prop="IsDistinguishCriteria">
<el-radio-group v-model="form.IsDistinguishCriteria" @change="() => {form.CriterionTypeEnum = null}">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="阅片标准" v-if="form.IsDistinguishCriteria" prop="CriterionTypeEnum">
<el-select v-model="form.CriterionTypeEnum" clearable class="mr">
<el-option
v-for="item of $d.CriterionType"
:key="`CriterionType${item.label}`"
:label="item.label"
:value="item.value"
/>
<el-form-item :label="$t('trials:auditRecord:table:criterion')" v-if="form.IsDistinguishCriteria"
prop="CriterionTypeList">
<el-select v-model="form.CriterionTypeList" clearable class="mr" multiple>
<el-option v-for="item of $d.CriterionType" :key="`CriterionType${item.label}`" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否启用" prop="IsEnable">
<!-- 是否启用 -->
<el-form-item :label="$t('trials:emailManageCfg:table:IsEnable')" prop="IsEnable">
<el-radio-group v-model="form.IsEnable">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="`IsEnable${item.value}`">{{ item.label
}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件(CN" prop="IsEnable">
<el-upload
class="upload-demo"
action
:before-upload="beforeUploadCN"
:http-request="handleUploadFileCN"
:on-preview="handlePreviewCN"
:on-remove="handleRemoveFileCN"
:show-file-list="true"
:limit="1"
:file-list="fileListCN"
>
<el-button size="small" type="primary" :disabled="fileListCN.length > 0">点击上传</el-button>
<!-- 附件(CN -->
<el-form-item :label="$t('trials:emailManageCfg:table:fileListCN')" prop="IsEnable">
<el-upload class="upload-demo" action :before-upload="beforeUploadCN" :http-request="handleUploadFileCN"
:on-preview="handlePreviewCN" :on-remove="handleRemoveFileCN" :show-file-list="true" :limit="1"
:file-list="fileListCN">
<el-button size="small" type="primary" :disabled="fileListCN.length > 0">{{ $t('common:button:upload')
}}</el-button>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件(EN" prop="IsEnable">
<el-upload
class="upload-demo"
action
:before-upload="beforeUploadEN"
:http-request="handleUploadFileEN"
:on-preview="handlePreviewEN"
:on-remove="handleRemoveFileEN"
:show-file-list="true"
:limit="1"
:file-list="fileListEN"
>
<el-button size="small" type="primary" :disabled="fileListEN.length > 0">点击上传</el-button>
<!-- 附件(EN -->
<el-form-item :label="$t('trials:emailManageCfg:table:fileListEN')" prop="IsEnable">
<el-upload class="upload-demo" action :before-upload="beforeUploadEN" :http-request="handleUploadFileEN"
:on-preview="handlePreviewEN" :on-remove="handleRemoveFileEN" :show-file-list="true" :limit="1"
:file-list="fileListEN">
<el-button size="small" type="primary" :disabled="fileListEN.length > 0">{{ $t('common:button:upload')
}}</el-button>
</el-upload>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="邮件内容模版(CN" prop="EmailHtmlContentCN">
<el-input
v-model="form.EmailHtmlContentCN"
type="textarea"
:autosize="{ minRows: 8, maxRows: 8}"
/>
<!-- 邮件内容模版(CN -->
<el-form-item :label="$t('dictionary:email:label:emailHtmlContentCN')" prop="EmailHtmlContentCN"
style="position: relative">
<div class="html_temp">
<prism-editor class="my-editor" v-model="form.EmailHtmlContentCN" :highlight="highlighter" :line-numbers="true"
style="width: 50%;max-height: 500px;"></prism-editor>
<div v-html="form.EmailHtmlContentCN" style="width: 50%;"></div>
</div>
<!-- <el-input v-model="form.EmailHtmlContentCN" type="textarea" :autosize="{ minRows: 8, maxRows: 8 }" />
<el-button :disabled="!form.EmailHtmlContentCN && form.EmailHtmlContent" type="text"
@click="PreviewHTML(form.EmailHtmlContentCN, form.EmailHtmlContent)"
style="position: absolute; left: -50px; top: 30px">
{{ $t('common:button:preview') }}
</el-button> -->
</el-form-item>
<el-form-item label="邮件内容模版(EN" prop="EmailHtmlContent">
<el-input
v-model="form.EmailHtmlContent"
type="textarea"
:autosize="{ minRows: 8, maxRows: 8}"
/>
<!-- 邮件内容模版(EN -->
<el-form-item :label="$t('dictionary:email:label:emailHtmlContent')" prop="EmailHtmlContent"
style="position: relative">
<div class="html_temp">
<prism-editor class="my-editor" v-model="form.EmailHtmlContent" :highlight="highlighter" :line-numbers="true"
style="width: 50%;max-height: 500px;"></prism-editor>
<div v-html="form.EmailHtmlContent" style="width: 50%;"></div>
</div>
<!-- <el-input v-model="form.EmailHtmlContent" type="textarea" :autosize="{ minRows: 8, maxRows: 8 }" />
<el-button :disabled="!form.EmailHtmlContentCN && form.EmailHtmlContent" type="text"
@click="PreviewHTML(form.EmailHtmlContentCN, form.EmailHtmlContent)"
style="position: absolute; left: -50px; top: 30px">
{{ $t('common:button:preview') }}
</el-button> -->
</el-form-item>
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;padding-bottom: 10px">
<el-form-item style="text-align:right;">
<el-button size="small" type="primary" @click="handleSave">Save</el-button>
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px; padding-bottom: 10px">
<el-form-item style="text-align: right">
<el-button size="small" type="primary" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</el-form-item>
</div>
<el-dialog append-to-body title="生成 cron" :visible.sync="showCron">
<vcrontab :hideComponent="['year']" @hide="showCron=false" @fill="crontabFill" :expression="expression"></vcrontab>
<!-- 生成 cron -->
<el-dialog append-to-body :title="$t('dictionary:email:button:cron')" :visible.sync="showCron">
<vcrontab :hideComponent="['year']" @hide="showCron = false" @fill="crontabFill" :expression="expression">
</vcrontab>
</el-dialog>
</el-form>
</template>
<script>
import { Upload, addOrUpdateEmailNoticeConfigList } from '@/api/dictionary'
import vcrontab from 'vcrontab'
import { PrismEditor } from 'vue-prism-editor';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/themes/prism.css';
export default {
props: {
data: {
type: Object,
default() { return {} }
}
default() {
return {}
},
},
systemLevel: {
type: Number,
default() {
return 0
},
},
isDistinguishCriteria: {
type: Boolean,
default() {
return false
},
},
},
components: { vcrontab, PrismEditor },
data() {
return {
expression: '',
@@ -240,37 +269,73 @@ export default {
IsUrgent: true,
IsEnable: true,
IsAutoSend: true,
CriterionTypeEnum: null
CriterionTypeEnum: null,
EmailDelaySeconds: null,
CriterionTypeList: []
},
rules: {
Code: [{ required: true, message: 'Please select', trigger: ['blur'] }],
BusinessScenarioEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailTopicCN: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailTopic: [{ required: true, message: 'Please select', trigger: ['blur'] }],
BusinessLevelEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }],
ToUserTypeList: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailCron: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailUrgentEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailHtmlContentCN: [{ required: true, message: 'Please select', trigger: ['blur'] }],
EmailHtmlContent: [{ required: true, message: 'Please select', trigger: ['blur'] }],
CriterionTypeEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }],
Code: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }],
BusinessScenarioEnum: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
EmailTopicCN: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
EmailTopic: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
BusinessLevelEnum: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
// ToUserTypeList: [
// { required: true, message: 'Please select', trigger: ['blur'] },
// ],
// EmailCron: [
// { required: true, message: 'Please select', trigger: ['blur'] },
// ],
EmailUrgentEnum: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
EmailHtmlContentCN: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
EmailHtmlContent: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
CriterionTypeList: [
{ required: true, type: 'array', message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
},
scenarioOption: [],
fileListCN: [],
fileListEN: [],
loading: false
loading: false,
}
},
mounted() {
this.initForm()
if (this.systemLevel) {
if (this.systemLevel === 1) {
this.form.ToUserTypeList = []
}
this.form.CopyUserTypeList = []
this.form.EmailUrgentEnum = 3
this.form.IsReturnRequired = false
this.form.IsDistinguishCriteria = false
} else {
this.form.IsDistinguishCriteria = this.isDistinguishCriteria
}
},
methods: {
highlighter(code) {
return highlight(code, languages.js);
},
showDialog() {
this.expression = this.form.EmailCron;//传入的 cron 表达式,可以反解析到 UI 上
this.showCron = true;
this.expression = this.form.EmailCron //传入的 cron 表达式,可以反解析到 UI 上
this.showCron = true
},
crontabFill(value) {
this.form.EmailCron = value;
this.form.EmailCron = value
},
handleRemoveFileCN() {
this.form.AttachNameCN = null
@@ -279,7 +344,7 @@ export default {
},
beforeUploadCN() {
if (this.fileListCN.length > 0) {
this.$alert('最多只能传一个附件')
this.$alert(this.$t('trials:emailManageCfg:message:msg1'))
return
}
},
@@ -293,10 +358,15 @@ export default {
const formData = new FormData()
formData.append('file', param.file)
this.form.AttachNameCN = param.file.name
Upload(formData, 3).then(res => {
Upload(formData, 3).then((res) => {
this.form.AttachCNPath = res.Result.FilePath
this.btnLoading = false
this.fileListCN.push({ name: param.file.name, path: res.Result.FilePath, fullPath: res.Result.FullFilePath, url: res.Result.FilePath })
this.fileListCN.push({
name: param.file.name,
path: res.Result.FilePath,
fullPath: res.Result.FullFilePath,
url: res.Result.FilePath,
})
})
},
handleUploadFileEN(param) {
@@ -304,10 +374,15 @@ export default {
const formData = new FormData()
formData.append('file', param.file)
this.form.AttachName = param.file.name
Upload(formData, 3).then(res => {
Upload(formData, 3).then((res) => {
this.form.AttachPath = res.Result.FilePath
this.btnLoading = false
this.fileListEN.push({ name: param.file.name, path: res.Result.FilePath, fullPath: res.Result.FullFilePath, url: res.Result.FilePath })
this.fileListEN.push({
name: param.file.name,
path: res.Result.FilePath,
fullPath: res.Result.FullFilePath,
url: res.Result.FilePath,
})
})
},
handleRemoveFileEN() {
@@ -317,7 +392,7 @@ export default {
},
beforeUploadEN() {
if (this.fileListEN.length > 0) {
this.$alert('最多只能传一个附件')
this.$alert(this.$t('trials:emailManageCfg:message:msg1'))
return
}
},
@@ -334,31 +409,57 @@ export default {
this.form[k] = this.data[k]
}
if (k === 'AttachPath' && this.form[k]) {
this.fileListEN.push({ name: this.data.AttachName, path: this.data.AttachPath, fullPath: this.data.AttachPath, url: this.data.AttachPath })
this.fileListEN.push({
name: this.data.AttachName,
path: this.data.AttachPath,
fullPath: this.data.AttachPath,
url: this.data.AttachPath,
})
}
if (k === 'AttachCNPath' && this.form[k]) {
this.fileListCN.push({ name: this.data.AttachNameCN, path: this.data.AttachCNPath, fullPath: this.data.AttachCNPath, url: this.data.AttachCNPath })
this.fileListCN.push({
name: this.data.AttachNameCN,
path: this.data.AttachCNPath,
fullPath: this.data.AttachCNPath,
url: this.data.AttachCNPath,
})
}
}
console.log(this.fileListEN, this.fileListCN)
this.loading = false
},
// 保存
handleSave() {
this.$refs.emailForm.validate(valid => {
this.$refs.emailForm.validate((valid) => {
if (!valid) return
this.loading = true
addOrUpdateEmailNoticeConfigList(this.form).then(res => {
this.loading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success('Saved successfully')
}).catch(() => {
this.loading = false
})
this.form.systemLevel = this.systemLevel
addOrUpdateEmailNoticeConfigList(this.form)
.then((res) => {
this.loading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success(this.$t('common:message:savedSuccessfully'))
})
.catch(() => {
this.loading = false
})
})
}
}
},
// 预览模板
PreviewHTML(html, htmlEn) {
this.$emit('PreviewHTML', html, htmlEn)
},
},
}
</script>
<style lang="scss" scoped>
.html_temp {
display: flex;
.my-editor {
border: 1px solid #333;
}
}
</style>
@@ -1,172 +1,160 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="是否需要回执:">
<el-select v-model="searchData.IsReturnRequired" clearable style="width:100px;">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" />
<el-form :inline="true" class="base-search-form">
<!-- 是否需要回执 -->
<el-form-item :label="$t('trials:emailManageCfg:title:isReturnRequired')" v-if="!systemLevel">
<el-select v-model="searchData.IsReturnRequired" clearable style="width: 100px">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item label="是否加急:">
<el-select v-model="searchData.IsUrgent" clearable style="width:100px;">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" />
<!-- 是否加急 -->
<el-form-item :label="$t('dictionary:email:label:IsUrgent')" v-if="!systemLevel">
<el-select v-model="searchData.IsUrgent" clearable style="width: 100px">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item label="是否启用:">
<el-select v-model="searchData.IsEnable" clearable style="width:100px;">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" />
<!-- 是否启用 -->
<el-form-item :label="$t('trials:emailManageCfg:table:IsEnable')" v-if="!systemLevel">
<el-select v-model="searchData.IsEnable" clearable style="width: 100px">
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item label="阅片标准:" v-if="isDistinguishCriteria">
<el-select v-model="searchData.CriterionTypeEnum" clearable style="width:100px;">
<el-option v-for="item of $d.CriterionType" :value="item.value" :label="item.label" />
<el-form-item :label="$t('trials:auditRecord:table:criterion')" v-if="isDistinguishCriteria && !systemLevel">
<el-select v-model="searchData.CriterionTypeEnum" clearable style="width: 100px">
<el-option v-for="item of $d.CriterionType" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:emailManageCfg:form:BusinessModule')">
<el-select v-model="searchData.BusinessModuleEnum" clearable style="width: 100px">
<el-option v-for="item of $d.BusinessModule" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:emailManageCfg:form:BusinessScenario')">
<el-select v-model="searchData.BusinessScenarioEnum" clearable style="width: 100px">
<el-option v-for="item of $d.Email_BusinessScenario" :value="item.value" :label="item.label"
:key="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:emailManageCfg:form:ToUserType')">
<el-select v-model="searchData.ToUserType" clearable style="width: 100px">
<el-option v-for="item of UserTypeList" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')" v-if="systemLevel === 1">
<el-select v-model="searchData.EmailUrgentEnum" clearable style="width: 100px">
<el-option v-for="item of $d.EmailUrgent" :value="item.value" :label="item.label" :key="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button type="primary" @click="handleReset">重置</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto;">
<!-- <el-button
<el-form-item>
<el-button type="primary" @click="handleExport">
{{ $t('common:button:export') }}
</el-button>
<!-- <el-button
type="primary"
size="mini"
>
场景配置
</el-button> -->
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
新增
</el-button>
</span>
<el-button type="primary" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
<el-button type="primary" @click="openDrawer" :disabled="multipleSelection.length <= 0">
{{ $t('trials:emailManageCfg:button:batchAudit') }}
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 受试者列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
height="100"
style="width:100%"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="40" />
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" :data="list" stripe height="100" style="width: 100%"
@sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
<!-- <el-table-column type="index" width="40" /> -->
<el-table-column type="selection" width="55">
</el-table-column>
<!-- Code -->
<el-table-column
prop="Code"
:label="$t('trials:emailManageCfg:title:code')"
sortable="custom"
show-overflow-tooltip
width="100"
/>
<el-table-column
v-if="isDistinguishCriteria"
prop="TrialReadingCriterionId"
:label="$t('trials:reviewTrack:table:criterionName')"
show-overflow-tooltip
sortable="custom"
width="120"
>
<el-table-column prop="Code" :label="$t('trials:emailManageCfg:title:code')" sortable="custom"
show-overflow-tooltip min-width="100" />
<el-table-column v-if="isDistinguishCriteria" prop="TrialReadingCriterionId"
:label="$t('trials:reviewTrack:table:criterionName')" show-overflow-tooltip sortable="custom" min-width="120">
<template slot-scope="scope">
{{ scope.row.TrialCriterionName }}
{{scope.row.CriterionTypeList ? scope.row.CriterionTypeList.map(item => $fd('CriterionType', item)).join(', ')
: ''}}
</template>
</el-table-column>
<el-table-column
prop="EmailTopicCN"
label="邮件主题(中文)"
sortable="custom"
show-overflow-tooltip
width="160"
/>
<el-table-column
prop="EmailTopic"
label="邮件主题(英文)"
sortable="custom"
show-overflow-tooltip
width="160"
/>
<el-table-column
prop="BusinessLevelEnum"
label="业务层级"
sortable="custom"
show-overflow-tooltip
width="100">
<!-- 邮件主题中文 -->
<el-table-column prop="EmailTopicCN" :label="$t('trials:emailManageCfg:table:EmailTopicCN')" sortable="custom"
show-overflow-tooltip min-width="160" />
<!-- 邮件主题英文 -->
<el-table-column prop="EmailTopic" :label="$t('trials:emailManageCfg:table:EmailTopic')" sortable="custom"
show-overflow-tooltip min-width="160" />
<!-- 业务层级 -->
<el-table-column prop="BusinessLevelEnum" :label="$t('dictionary:email:label:businessLevel')" sortable="custom"
show-overflow-tooltip min-width="150">
<template slot-scope="scope">
{{ $fd('BusinessLevel',scope.row.BusinessLevelEnum) }}
{{ $fd('BusinessLevel', scope.row.BusinessLevelEnum) }}
</template>
</el-table-column>
<el-table-column
prop="BusinessModuleEnum"
label="业务模块"
sortable="custom"
show-overflow-tooltip
width="100">
<!-- 业务模块 -->
<el-table-column prop="BusinessModuleEnum" :label="$t('dictionary:email:label:businessModule')" sortable="custom"
show-overflow-tooltip min-width="160">
<template slot-scope="scope">
{{ $fd('BusinessModule',scope.row.BusinessModuleEnum) }}
{{ $fd('BusinessModule', scope.row.BusinessModuleEnum) }}
</template>
</el-table-column>
<el-table-column
prop="BusinessScenarioEnum"
label="业务场景"
sortable="custom"
show-overflow-tooltip
width="130"
>
<!-- 业务场景 -->
<el-table-column prop="BusinessScenarioEnum" :label="$t('trials:emailManageCfg:table:BusinessScenarioEnum')"
sortable="custom" show-overflow-tooltip min-width="130">
<template slot-scope="scope">
{{ $fd('Email_BusinessScenario',scope.row.BusinessScenarioEnum) }}
{{ $fd('Email_BusinessScenario', scope.row.BusinessScenarioEnum) }}
</template>
</el-table-column>
<!-- 收件人 -->
<el-table-column
prop="ToUserTypeList"
:label="$t('trials:emailManageCfg:title:toUserTypeList')"
show-overflow-tooltip
width="100"
>
<!-- 收件人v-if="systemLevel !== 1" -->
<el-table-column prop="ToUserTypeList" :label="$t('trials:emailManageCfg:title:toUserTypeList')"
show-overflow-tooltip min-width="100">
<template slot-scope="scope">
{{ scope.row.ToUserTypeList.length > 0?scope.row.ToUserTypeList.map(v => $fd('UserType', v)).join('、'):'' }}
{{
scope.row.ToUserTypeList.length > 0
? scope.row.ToUserTypeList.map((v) => $fd('UserType', v)).join(
'、'
)
: ''
}}
</template>
</el-table-column>
<!-- 抄送人 -->
<el-table-column
prop="CopyUserTypeList"
:label="$t('trials:emailManageCfg:title:copyUserTypeList')"
show-overflow-tooltip
width="100"
>
<!-- 抄送人v-if="!systemLevel" -->
<el-table-column prop="CopyUserTypeList" :label="$t('trials:emailManageCfg:title:copyUserTypeList')"
show-overflow-tooltip min-width="100">
<template slot-scope="scope">
{{ scope.row.CopyUserTypeList.length > 0?scope.row.CopyUserTypeList.map(v => $fd('UserType', v)).join('、'):'' }}
{{
scope.row.CopyUserTypeList.length > 0
? scope.row.CopyUserTypeList.map((v) => $fd('UserType', v)).join(
'、'
)
: ''
}}
</template>
</el-table-column>
<el-table-column
prop="EmailUrgentEnum"
label="加急状态"
sortable="custom"
show-overflow-tooltip
width="100"
>
<!-- 加急状态 -->
<el-table-column prop="EmailUrgentEnum" :label="$t('dictionary:email:label:IsUrgent')" sortable="custom"
show-overflow-tooltip min-width="110">
<template slot-scope="scope">
{{ $fd('EmailUrgent',scope.row.EmailUrgentEnum) }}
{{ $fd('EmailUrgent', scope.row.EmailUrgentEnum) }}
</template>
</el-table-column>
<el-table-column
prop="EmailCron"
label="发送周期和时间"
sortable="custom"
show-overflow-tooltip
width="160"
/>
<!-- 发送周期和时间 -->
<el-table-column prop="EmailCron" :label="$t('trials:emailManageCfg:table:EmailCron')" sortable="custom"
show-overflow-tooltip min-width="180" />
<!-- 附件 -->
<el-table-column
prop="FileName"
:label="$t('trials:emailManageCfg:title:fileName')"
show-overflow-tooltip
width="100"
>
<el-table-column prop="FileName" :label="$t('trials:emailManageCfg:title:fileName')" show-overflow-tooltip
min-width="100" v-if="!systemLevel">
<template slot-scope="scope">
<el-button v-if="scope.row.FilePath" type="text" @click="handlePreview(scope.row.FilePath)">
{{ scope.row.FileName }}
@@ -174,115 +162,171 @@
</template>
</el-table-column>
<!-- 是否需要回执 -->
<el-table-column
prop="IsReturnRequired"
:label="$t('trials:emailManageCfg:title:isReturnRequired')"
show-overflow-tooltip
sortable="custom"
width="140"
>
<el-table-column prop="IsReturnRequired" :label="$t('trials:emailManageCfg:title:isReturnRequired')"
show-overflow-tooltip sortable="custom" min-width="160" v-if="!systemLevel">
<template slot-scope="scope">
<el-tag v-if="scope.row.IsReturnRequired" type="danger">
{{ $fd('YesOrNo', scope.row.IsReturnRequired) }}
</el-tag>
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsReturnRequired) }}</el-tag>
<el-tag v-else type="primary">{{
$fd('YesOrNo', scope.row.IsReturnRequired)
}}</el-tag>
</template>
</el-table-column>
<!-- 是否自动发送 -->
<el-table-column
prop="IsAutoSend"
:label="$t('trials:emailManageCfg:title:isAutoSend')"
show-overflow-tooltip
sortable="custom"
width="160"
>
<el-table-column prop="IsAutoSend" :label="$t('trials:emailManageCfg:title:isAutoSend')" show-overflow-tooltip
sortable="custom" min-width="160" v-if="!systemLevel">
<template slot-scope="scope">
<el-tag v-if="scope.row.IsAutoSend" type="danger">
{{ $fd('YesOrNo', scope.row.IsAutoSend) }}
</el-tag>
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsAutoSend) }}</el-tag>
<el-tag v-else type="primary">{{
$fd('YesOrNo', scope.row.IsAutoSend)
}}</el-tag>
</template>
</el-table-column>
<el-table-column
prop="IsEnable"
:label="$t('trials:emailManageCfg:table:IsEnable')"
show-overflow-tooltip
sortable="custom"
width="160"
>
<el-table-column prop="IsEnable" :label="$t('trials:emailManageCfg:table:IsEnable')" show-overflow-tooltip
sortable="custom" min-width="160" v-if="!systemLevel">
<template slot-scope="scope">
<el-tag v-if="scope.row.IsEnable" type="danger">
{{ $fd('YesOrNo', scope.row.IsEnable) }}
</el-tag>
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsEnable) }}</el-tag>
<el-tag v-else type="primary">{{
$fd('YesOrNo', scope.row.IsEnable)
}}</el-tag>
</template>
</el-table-column>
<!-- 更新时间 -->
<el-table-column
prop="UpdateTime"
:label="$t('trials:emailManageCfg:title:updateTime')"
show-overflow-tooltip
sortable="custom"
width="160"
/>
<el-table-column prop="UpdateTime" :label="$t('trials:emailManageCfg:title:updateTime')" show-overflow-tooltip
sortable="custom" min-width="160" />
<!-- 创建时间 -->
<el-table-column
prop="CreateTime"
:label="$t('trials:emailManageCfg:title:createTime')"
show-overflow-tooltip
sortable="custom"
width="160"
/>
<el-table-column label="Action" width="140" fixed="right">
<el-table-column prop="CreateTime" :label="$t('trials:emailManageCfg:title:createTime')" show-overflow-tooltip
sortable="custom" min-width="160" />
<el-table-column :label="$t('common:action:action')" min-width="180" fixed="right">
<template slot-scope="scope">
<el-button
type="text"
@click="handleEdit(scope.row)"
>
编辑
<el-button type="text" @click="handleEdit(scope.row)">
{{ $t('common:button:edit') }}
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
{{ $t('common:button:delete') }}
</el-button>
<el-button type="text" @click="
preview(scope.row.EmailHtmlContentCN, scope.row.EmailHtmlContent)
">{{ $t('common:button:preview') }}</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<!-- 搜索框 -->
<!-- 修改受试者状态 -->
<el-dialog
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="700px"
fullscreen
custom-class="base-dialog-wrapper"
>
<EmailForm :data="rowData" @closeDialog="closeDialog" @getList="getList" />
<el-dialog v-if="editVisible" :visible.sync="editVisible" :close-on-click-modal="false" :title="title" width="700px"
fullscreen custom-class="base-dialog-wrapper">
<EmailForm :data="rowData" :system-level="systemLevel" :isDistinguishCriteria="isDistinguishCriteria"
@closeDialog="closeDialog" @getList="getList" @PreviewHTML="preview" />
</el-dialog>
<!-- 修改受试者状态 -->
<el-dialog
v-if="attachmentVisible"
:visible.sync="attachmentVisible"
:close-on-click-modal="false"
title="附件"
width="80%"
custom-class="base-dialog-wrapper"
append-to-body
>
<AttachmentList
:business-scenario-enum="rowData.BusinessScenarioEnum"
:is-distinguish-criteria="rowData.IsDistinguishCriteria"
@getList="getList"
/>
<el-dialog v-if="attachmentVisible" :visible.sync="attachmentVisible" :close-on-click-modal="false"
:title="$t('trials:emailManageCfg:title:fileName')" width="80%" custom-class="base-dialog-wrapper" append-to-body>
<AttachmentList :business-scenario-enum="rowData.BusinessScenarioEnum"
:is-distinguish-criteria="rowData.IsDistinguishCriteria" @getList="getList" />
</el-dialog>
<!-- 预览模板 -->
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :close-on-click-modal="false"
:title="$t('common:button:preview')" fullscreen custom-class="base-dialog-wrapper">
<div style="
display: flex;
align-items: flex-start;
justify-content: space-around;
flex-wrap: wrap;
">
<div style="min-width: 50%">
<!-- 邮件内容模版CN -->
<h3>{{ $t('dictionary:email:title:title1') }}</h3>
<div v-html="previewHTML"></div>
</div>
<div style="min-width: 50%">
<!-- 邮件内容模版EN -->
<h3>{{ $t('dictionary:email:title:title2') }}</h3>
<div v-html="previewHTMLEN"></div>
</div>
</div>
</el-dialog>
<el-drawer :title="$t('trials:emailManageCfg:title:audit')" :visible.sync="drawer" direction="rtl" size="80%">
<!-- <div style="width: 800px">
<el-form label-width="100px" @submit.native.prevent size="small" :inline="true" class="demo-form-inline">
<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')">
<el-select v-model="State" clearable filterable @change="handleStateChange">
<el-option v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
</div> -->
<el-table :data="tableData" v-adaptive="{ bottomOffset: 50 }" height="100" style="width: 100%"
@sort-change="handleSortByColumnDrawer">
<!-- Code -->
<el-table-column prop="Code" :label="$t('trials:emailManageCfg:title:code')" sortable="custom"
show-overflow-tooltip min-width="100" />
<el-table-column v-if="isDistinguishCriteria" prop="TrialReadingCriterionId"
:label="$t('trials:reviewTrack:table:criterionName')" show-overflow-tooltip sortable="custom" min-width="120">
<template slot-scope="scope">
{{ $fd('CriterionType', scope.row.CriterionTypeEnum) }}
</template>
</el-table-column>
<!-- 邮件主题中文 -->
<el-table-column prop="EmailTopicCN" :label="$t('trials:emailManageCfg:table:EmailTopicCN')" sortable="custom"
show-overflow-tooltip min-width="160">
<template slot-scope="scope">
<el-input v-model="scope.row.EmailTopicCN" @input="
(e) => {
$set(scope.row, 'EmailTopicCN', e)
}
" size="mini"></el-input>
</template>
</el-table-column>
<!-- 邮件主题(英文) -->
<el-table-column prop="EmailTopic" :label="$t('trials:emailManageCfg:table:EmailTopic')" sortable="custom"
show-overflow-tooltip min-width="160">
<template slot-scope="scope">
<el-input v-model="scope.row.EmailTopic" @input="
(e) => {
$set(scope.row, 'EmailTopic', e)
}
" size="mini"></el-input>
</template>
</el-table-column>
<!-- 业务层级 -->
<el-table-column prop="BusinessLevelEnum" :label="$t('dictionary:email:label:businessLevel')" sortable="custom"
show-overflow-tooltip min-width="150">
<template slot-scope="scope">
{{ $fd('BusinessLevel', scope.row.BusinessLevelEnum) }}
</template>
</el-table-column>
</el-table>
<div style="text-align: right; padding-top: 10px; padding-right: 10px">
<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>
</box-content>
</template>
<script>
import { getEmailNoticeConfigList, deleteEmailNoticeConfig } from '@/api/dictionary'
import {
getEmailNoticeConfigList,
deleteEmailNoticeConfig,
batchUpdateEmail
} from '@/api/dictionary'
import { GetEmailNoticeConfigList_Export } from '@/api/export'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import EmailForm from './EmailForm'
@@ -293,8 +337,14 @@ const searchDataDefault = () => {
IsUrgent: '',
IsEnable: '',
CriterionTypeEnum: null,
BusinessModuleEnum: null,
BusinessScenarioEnum: null,
EmailUrgentEnum: null,
ToUserType: null,
PageIndex: 1,
PageSize: 20
PageSize: 20,
SortField: 'Code',
Asc: true,
}
}
export default {
@@ -305,8 +355,14 @@ export default {
type: Boolean,
default() {
return false
}
}
},
},
systemLevel: {
type: Number,
default() {
return 0
},
},
},
data() {
return {
@@ -318,50 +374,114 @@ export default {
rowData: {},
title: '',
editVisible: false,
attachmentVisible: false
attachmentVisible: false,
previewVisible: false,
previewHTML: null,
previewHTMLEN: null,
multipleSelection: [],
drawer: false,
tableData: []
}
},
computed: {
UserTypeList() {
if (this.systemLevel === 1) {
return this.$d.UserType
} else {
return this.$d.UserType.filter(
(item) => ![7, 31, 32, 21, 26, 27].includes(item.value)
)
}
},
},
mounted() {
this.getList()
},
methods: {
async handleSave() {
try {
let arr = []
this.tableData.forEach(item => {
let obj = {
EmailTopic: item.EmailTopic,
EmailTopicCN: item.EmailTopicCN,
Id: item.Id
}
arr.push(obj)
})
this.drawer = false
let res = await batchUpdateEmail(arr)
if (res.IsSuccess) {
this.$message.success(this.$t('trials:emailManageCfg:message:auditSuccess'))
this.getList()
}
} catch (err) {
console.log(err)
}
},
// 排序
handleSortByColumnDrawer(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])
)
}
},
openDrawer() {
this.tableData = []
this.multipleSelection.forEach(item => {
let obj = Object.assign({}, item)
this.tableData.push(obj)
})
this.drawer = true
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 获取受试者列表
getList() {
this.loading = true
this.searchData.IsDistinguishCriteria = this.isDistinguishCriteria
getEmailNoticeConfigList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => { this.loading = false })
this.searchData.systemLevel = this.systemLevel
getEmailNoticeConfigList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
// 新增
handleAdd() {
this.rowData = {}
this.title = '新增'
this.title = this.$t('common:button:new')
this.editVisible = true
},
// 编辑
handleEdit(row) {
this.rowData = { ...row }
this.title = '编辑'
this.title = this.$t('common:button:edit')
this.editVisible = true
},
// 删除
handleDelete(row) {
this.$confirm(this.$t('trials:staffResearch:message:confirmDel'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
deleteEmailNoticeConfig(row.Id)
.then(res => {
if (res.IsSuccess) {
this.getList()
this.$message.success('删除成功!')
}
})
distinguishCancelAndClose: true,
}).then(() => {
deleteEmailNoticeConfig(row.Id).then((res) => {
if (res.IsSuccess) {
this.getList()
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
})
})
},
handleDetail(row) {
this.rowData = { ...row }
@@ -391,7 +511,24 @@ export default {
// 关闭新增、编辑框
closeDialog() {
this.editVisible = false
}
}
},
preview(html, htmlEN) {
this.previewHTML = html
this.previewHTMLEN = htmlEN
this.previewVisible = true
},
// 导出
handleExport() {
// this.searchData.IsDistinguishCriteria = this.isDistinguishCriteria
// this.searchData.systemLevel = this.systemLevel
// return GetEmailNoticeConfigList_Export(this.searchData)
return GetEmailNoticeConfigList_Export(this.searchData)
},
},
}
</script>
<style lang="scss" scoped>
.box-body .search .base-search-form .el-form-item {
margin-bottom: 10px;
}
</style>
+52 -26
View File
@@ -2,24 +2,48 @@
<box-content>
<el-tabs v-model="activeTab" type="border-card">
<!-- 通用 -->
<el-tab-pane
:label="$t('trials:emailManageCfg:title:commom')"
name="0"
>
<EmailList v-if="activeTab === '0'" :is-distinguish-criteria="false"></EmailList>
<el-tab-pane :label="$t('trials:emailManageCfg:title:commom')" name="0">
<EmailList
v-if="activeTab === '0'"
:is-distinguish-criteria="false"
:system-level="0"
></EmailList>
</el-tab-pane>
<!-- 标准相关 -->
<el-tab-pane
:label="$t('trials:emailManageCfg:title:criterions')"
name="1"
>
<EmailList v-if="activeTab === '1'" :is-distinguish-criteria="true"></EmailList>
<EmailList
v-if="activeTab === '1'"
:is-distinguish-criteria="true"
:system-level="0"
></EmailList>
</el-tab-pane>
<!-- 系统相关 -->
<el-tab-pane :label="$t('trials:emailManageCfg:title:system')" name="2">
<EmailList
v-if="activeTab === '2'"
:is-distinguish-criteria="false"
:system-level="1"
></EmailList>
</el-tab-pane>
<!-- 系统相关-分角色 -->
<!-- <el-tab-pane :label="$t('trials:emailManageCfg:title:systemDisRole')" name="3">
<EmailList
v-if="activeTab === '3'"
:is-distinguish-criteria="false"
:system-level="2"
></EmailList>
</el-tab-pane> -->
</el-tabs>
</box-content>
</template>
<script>
import { getEmailNoticeConfigList, deleteEmailNoticeConfig } from '@/api/dictionary'
import {
getEmailNoticeConfigList,
deleteEmailNoticeConfig,
} from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import EmailList from './components/EmailList'
@@ -29,7 +53,7 @@ const searchDataDefault = () => {
IsUrgent: '',
IsEnable: '',
PageIndex: 1,
PageSize: 20
PageSize: 20,
}
}
export default {
@@ -45,7 +69,7 @@ export default {
rowData: {},
title: '',
editVisible: false,
attachmentVisible: false
attachmentVisible: false,
}
},
mounted() {
@@ -55,11 +79,15 @@ export default {
// 获取受试者列表
getList() {
this.loading = true
getEmailNoticeConfigList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => { this.loading = false })
getEmailNoticeConfigList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
// 新增
handleAdd() {
@@ -77,17 +105,15 @@ export default {
handleDelete(row) {
this.$confirm(this.$t('trials:staffResearch:message:confirmDel'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
deleteEmailNoticeConfig(row.Id)
.then(res => {
if (res.IsSuccess) {
this.getList()
this.$message.success('删除成功!')
}
})
distinguishCancelAndClose: true,
}).then(() => {
deleteEmailNoticeConfig(row.Id).then((res) => {
if (res.IsSuccess) {
this.getList()
this.$message.success('删除成功!')
}
})
})
},
handleDetail(row) {
this.rowData = { ...row }
@@ -117,7 +143,7 @@ export default {
// 关闭新增、编辑框
closeDialog() {
this.editVisible = false
}
}
},
},
}
</script>
+3 -3
View File
@@ -11,9 +11,9 @@
<el-input v-model="password.Email" disabled />
</el-form-item>
<!-- 用户名 -->
<el-form-item :label="$t('recompose:form:role')" prop="UserType">
<!-- <el-form-item :label="$t('recompose:form:role')" prop="UserType">
<el-input v-model="password.UserType" disabled />
</el-form-item>
</el-form-item> -->
<!-- 用户名 -->
<el-form-item :label="$t('recompose:form:userName')" prop="NewUserName">
<el-input v-model="password.NewUserName" />
@@ -99,7 +99,7 @@ export default {
this.password.UserId = this.$route.query.UserId
this.password.NewUserName = this.$route.query.UserName
this.password.Email = this.$route.query.Email
this.password.UserType = this.$route.query.UserType
// this.password.UserType = this.$route.query.UserType
this.password.access_token = this.$route.query.access_token
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
+11 -5
View File
@@ -220,9 +220,14 @@ export default {
if (!this.users || this.users.length <= 0) return ''
let str = ''
this.users.forEach((item, index) => {
str += `${item.UserName}(${item.UserType})`
if (index < this.users.length - 1) {
str += '; '
if (index === 0) {
str += `${item.UserName}(`
}
if (index === this.users.length - 1) {
str += `${item.UserTypeShortName})`
} else {
str += `${item.UserTypeShortName}`
}
})
return str
@@ -291,7 +296,7 @@ export default {
this.formLoading = false;
this.users = res.Result;
if (this.users && this.users.length > 0) {
this.form.UserId = this.users[0].UserId
this.form.UserId = this.users[0].IdentityUserId
}
this.isVerify = true;
this.$message.success(this.$t("passwordReset:button:verifySuccess"));
@@ -327,7 +332,8 @@ export default {
obj.sendDisabled = true;
obj.sendTitle = `${this.$t(
"passwordReset:button:wait"
)}(${countdown}s)`;
)
} (${countdown}s)`;
countdown--;
// eslint-disable-next-line no-self-assign
countdown = countdown;
+103 -85
View File
@@ -125,7 +125,7 @@
</span>
</el-dialog>
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
@save="loginByRole" />
@save="loginByRole" @cancel="cancel" />
</div>
</template>
@@ -237,62 +237,11 @@ export default {
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
loginByRole(row) {
let { UserId, UserTypeId } = row
if (this.$store.state.user.userId === UserId) {
this.toggleRoleVisible = false
this.toggleRoleLoading = false
return false
}
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { UserId, UserTypeId })
.then((res) => {
if (res) {
this.$store
.dispatch('permission/generateRoutes')
.then(async (res) => {
if (res && res.length > 0) {
resetRouter()
await this.$store.dispatch('global/getNoticeList')
this.$router.addRoutes(res)
this.toggleRoleLoading = false
if (this.loginType === 'DevOps') {
this.$router.replace({ path: res[0].path })
return
}
if (this.hasPermi(['role:radmin'])) {
this.$router.replace({ path: res[0].path })
return
}
if (
this.hasPermi(['role:pm', 'role:oa', 'role:admin', 'role:dev'])
) {
history.replaceState(null, null, '/trials/trials-inspection')
history.go(0)
} else {
history.replaceState(null, null, '/trials/trials-list')
history.go(0)
}
this.toggleRoleVisible = false
this.toggleRoleLoading = false
this.$EventBus.$emit('reload')
} else {
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
this.toggleRoleLoading = false
this.$message.warning(this.$t('login:message:login2'))
}
})
.catch((err) => {
this.toggleRoleLoading = false
})
} else {
this.toggleRoleLoading = false
}
})
.catch(() => {
this.toggleRoleLoading = false
})
cancel() {
this.showCode = true
this.loading = false
this.toggleRoleLoading = false
// this.toggleRoleVisible = false
},
// 置换token
async TJUserLoginInfo(Token) {
@@ -385,7 +334,10 @@ export default {
this.$store
.dispatch('user/login', this.loginForm)
.then((res) => {
if (!res) {
if (res.BasicInfo.LoginState === 2) {
this.$message.warning(this.$t('login:message:login4'))
}
if (res.BasicInfo.IsFirstAdd) {
// 当前用户为首次登录,请先修改密码之后再次登录
this.$message.success(this.$t('login:message:login1'))
setTimeout(() => {
@@ -394,39 +346,105 @@ export default {
})
}, 500)
return
} else if (res.BasicInfo.NeedChangePassWord) {
// 请先修改密码后再登录!
this.$alert(
this.$t('login:message:login3'),
this.$t('common:title:warning'),
{
callback: (action) => {
this.$router.push({
path: `/recompose?userName=${this.loginForm.username}`,
})
return
},
}
)
return
}
this.$store.dispatch('permission/generateRoutes').then((res) => {
this.loading = false
if (res && res.length > 0) {
this.$store.dispatch('global/getNoticeList')
this.$router.addRoutes(res)
if (this.loginType === 'DevOps') {
this.$router.replace({ path: res[0].path })
return
}
if (this.hasPermi(['role:radmin'])) {
this.$router.replace({ path: res[0].path })
return
}
if (
this.hasPermi(['role:pm', 'role:oa', 'role:admin', 'role:dev'])
) {
this.$router.replace({ path: '/trials/trials-inspection' })
} else if (this.hasPermi(['role:oa'])) {
this.$router.replace({ path: '/system' })
} else {
this.$router.replace({ path: '/trials' })
}
} else {
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
this.$message.warning(this.$t('login:message:login2'))
}
})
zzSessionStorage.removeItem('userId')
zzSessionStorage.removeItem('identityUserId')
this.changeRoleLogin()
})
.catch(() => {
this.loading = false
})
},
changeRoleLogin() {
if (
Array.isArray(this.$store.state.user.roles) &&
this.$store.state.user.roles.length === 1
) {
this.loginByRole(this.$store.state.user.roles[0].Id)
return
}
if (
Array.isArray(this.$store.state.user.roles) &&
this.$store.state.user.roles.filter((item) => item.IsUserRoleDisabled)
.length ===
this.$store.state.user.roles.length - 1
) {
let role = this.$store.state.user.roles.find(
(item) => !item.IsUserRoleDisabled
)
this.loginByRole(role.Id)
return
}
return (this.toggleRoleVisible = true)
},
loginByRole(userRoleId) {
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { userRoleId })
.then((res) => {
this.toggleRoleLoading = false
if (res) {
this.$store
.dispatch('permission/generateRoutes')
.then((res) => {
this.loading = false
if (res && res.length > 0) {
this.$store.dispatch('global/getNoticeList')
this.$router.addRoutes(res)
// if (this.LoginState === 2) {
// this.$message.warning(this.$t('login:message:login4'))
// }
if (this.loginType === 'DevOps') {
this.$router.replace({ path: res[0].path })
return
}
if (this.hasPermi(['role:radmin'])) {
this.$router.replace({ path: res[0].path })
return
}
if (
this.hasPermi(['role:pm', 'role:sa', 'role:admin', 'role:dev', 'role:ga'])
) {
history.replaceState(null, null, '/trials/trials-inspection')
history.go(0)
} else {
history.replaceState(null, null, '/trials/trials-list')
history.go(0)
}
} else {
this.toggleRoleLoading = false
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
this.$message.warning(this.$t('login:message:login2'))
}
})
.catch((err) => {
this.toggleRoleLoading = false
})
} else {
this.toggleRoleLoading = false
}
})
.catch((err) => {
this.showCode = true
this.loading = false
this.toggleRoleLoading = false
})
},
onSuccess() {
this.isShow = false
this.loginIn()
+47 -57
View File
@@ -1,75 +1,40 @@
<template>
<div style="display: flex; justify-content: center">
<div
style="
<div style="
width: 600px;
text-align: center;
border: 1px solid #e6e6e6;
margin-top: 40px;
padding: 10px;
"
>
<div
class="trial-myinfo-head"
style="font-size: 30px; line-height: 120px"
>
">
<div class="trial-myinfo-head" style="font-size: 30px; line-height: 120px">
<!-- 首次登录修改密码 -->
{{ $t("recompose:title:init") }}
</div>
<el-form
ref="passwordForm"
v-loading="loading"
label-position="right"
:model="password"
:rules="passwordFormRules"
label-width="120px"
>
<el-form ref="passwordForm" v-loading="loading" label-position="right" :model="password"
:rules="passwordFormRules" label-width="120px">
<!-- 邮箱 -->
<el-form-item :label="$t('recompose:form:EMail')" prop="EMail">
<el-input v-model="password.EMail" disabled />
</el-form-item>
<!-- 用户名 -->
<el-form-item :label="$t('recompose:form:userName')" prop="NewUserName">
<el-input v-model="password.NewUserName" />
</el-form-item>
<!-- 旧密码 -->
<el-form-item
:label="$t('recompose:form:oldPassword')"
prop="OldPassWord"
>
<el-input
v-model="password.OldPassWord"
type="password"
show-password
auto-complete="new-password"
/>
<el-form-item :label="$t('recompose:form:oldPassword')" prop="OldPassWord">
<el-input v-model="password.OldPassWord" type="password" show-password auto-complete="new-password" />
</el-form-item>
<!-- 新密码 -->
<el-form-item
:label="$t('recompose:form:newPassword')"
prop="NewPassWord"
>
<el-input
v-model="password.NewPassWord"
type="password"
show-password
auto-complete="new-password"
/>
<el-form-item :label="$t('recompose:form:newPassword')" prop="NewPassWord">
<el-input v-model="password.NewPassWord" type="password" show-password auto-complete="new-password" />
</el-form-item>
<!-- 确认密码 -->
<el-form-item
:label="$t('recompose:form:confirmPassword')"
prop="ConfirmPassWord"
>
<el-input
v-model="password.ConfirmPassWord"
type="password"
show-password
auto-complete="new-password"
/>
<el-form-item :label="$t('recompose:form:confirmPassword')" prop="ConfirmPassWord">
<el-input v-model="password.ConfirmPassWord" type="password" show-password auto-complete="new-password" />
</el-form-item>
<!-- 检验码 -->
<el-form-item
:label="$t('trials:researchForm:form:checkCode')"
prop="CheckCode"
:maxlength="6"
>
<el-form-item :label="$t('trials:researchForm:form:checkCode')" prop="CheckCode" :maxlength="6">
<el-input v-model="password.CheckCode" type="number" />
</el-form-item>
<el-form-item style="text-align: right">
@@ -95,6 +60,7 @@ export default {
return {
password: {
NewUserName: null,
EMail: null
},
passwordFormRules: {
NewUserName: [
@@ -136,6 +102,21 @@ export default {
message: this.$t("recompose:tip:inputCheckCode"),
trigger: "blur",
},
{
validator: (rule, value, callback) => {
const regex = /^[1-9]\d{5}$/;
if (
value &&
(String(value).includes('.') ||
!regex.test(String(value)))
) {
callback(new Error(this.$t('recompose:tip:inputCheckCode')))
} else {
callback()
}
},
trigger: 'blur',
},
],
},
userId: null,
@@ -143,10 +124,15 @@ export default {
};
},
mounted() {
this.$set(this.password, "NewUserName", this.$route.query.userName);
if (!this.password.NewUserName) {
let token = zzSessionStorage.getItem('TokenKey')
if (!token) {
// 该页面只提供给首次进入系统的用户使用
this.$alert(this.$t("recompose:message:warning"));
// this.$alert(this.$t("recompose:message:warning"));
return this.$router.push({ path: '/login', replace: true })
}
this.password.EMail = zzSessionStorage.getItem('my_EMail')
if (this.$route.query.userName !== this.password.EMail) {
this.$set(this.password, "NewUserName", this.$route.query.userName);
}
},
methods: {
@@ -159,9 +145,9 @@ export default {
} else {
this.$router.push(`/login`);
}
this.$i18n.locale = "zh";
this.setLanguage("zh");
this.$updateDictionary();
// this.$i18n.locale = "zh";
// this.setLanguage("zh");
// this.$updateDictionary();
},
save() {
this.$refs.passwordForm.validate((valid) => {
@@ -207,12 +193,14 @@ export default {
.reset-wrapper {
padding: 20px;
}
.reset-wrapper .el-page-header {
line-height: 50px;
border: 1px solid #ebeef5;
border-radius: 4px;
background-color: #fff;
}
.reset-wrapper .box-wrapper {
width: 60%;
margin: 20px auto;
@@ -224,6 +212,7 @@ export default {
.is-error {
margin-bottom: 40px;
}
input:-webkit-autofill {
-webkit-text-fill-color: #ededed !important;
box-shadow: 0 0 0px 1000px transparent inset !important;
@@ -231,6 +220,7 @@ input:-webkit-autofill {
background-image: none;
transition: background-color 50000s ease-in-out 0s;
}
input {
background-color: transparent;
caret-color: #fff;
+36 -10
View File
@@ -1,15 +1,15 @@
<template>
<div class="share-image-container">
<div class="share-image-banner">
<h2 style="text-align:center;">IRC Management System</h2>
<h2 style="text-align:center;">{{ $t('trials:trials:title:eics') }}</h2>
<el-card shadow="hover">
<h4>请输入提取码</h4>
<h4>{{ $t('trials:studyList:message:message7') }}</h4>
<el-form ref="validateForm" :inline="true" :rules="rules" :model="form">
<el-form-item label="" prop="ExtractionCode">
<el-input v-model="form.ExtractionCode" style="width:400px;" />
<el-input v-model="form.ExtractionCode" :max-length="100" style="width:400px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button type="primary" @click="onSubmit">{{ $t('common:button:submit') }}</el-button>
</el-form-item>
</el-form>
</el-card>
@@ -18,6 +18,7 @@
</template>
<script>
import { verifyShareImage } from '@/api/share'
import { mapMutations } from 'vuex'
export default {
data() {
return {
@@ -25,16 +26,34 @@ export default {
form: { ExtractionCode: '' },
rules: {
ExtractionCode: [
{ required: true, message: '请输入提取码', trigger: 'blur' },
{ min: 4, max: 6, message: '长度在 4 到 6 个字符', trigger: 'blur' }
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur,change' },
{
validator: (rule, value, callback) => {
if (value) {
if (value.length !== 4) {
callback(new Error(this.$t('trials:studyList:message:length4')));
}
if (!(/^[a-z0-9]+$/.test(value))) {
callback(new Error(this.$t('trials:studyList:message:testError')));
}
callback();
}
callback();
}
}
]
}
}
},
created() {
this.resourceId = this.$route.query.id
localStorage.setItem('location', this.location)
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
onSubmit() {
this.$refs['validateForm'].validate((valid) => {
if (valid) {
@@ -49,16 +68,22 @@ export default {
verifyShareImage(this.resourceId, this.form.ExtractionCode).then(res => {
loading.close()
if (res.IsSuccess) {
zzSessionStorage.clear()
this.$store.dispatch('user/setToken', res.Result.Token)
zzSessionStorage.setItem('studyId', res.Result.StudyId)
zzSessionStorage.setItem('TokenKey', res.Result.Token)
this.$store.dispatch('user/setToken', zzSessionStorage.getItem('TokenKey'))
// zzSessionStorage.setItem('studyId', res.Result.StudyId)
// zzSessionStorage.setItem('TokenKey', res.Result.Token)
// this.$store.dispatch('user/setToken', zzSessionStorage.getItem('TokenKey'))
// 跳转
// this.$router.push({
// name: 'showdicoms',
// query: { type: 'Share' }
// })
this.$router.push({ path: `/showdicom?studyId=${res.Result.StudyId}&TokenKey=${res.Result.Token}&type=Share` })
const userString = decodeURIComponent(escape(window.atob(res.Result.Token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))))
const user = JSON.parse(userString)
zzSessionStorage.setItem('userTypeEnum', user.userTypeEnum)
this.$router.push({ path: `${res.Result.RouteUrl}&TokenKey=${res.Result.Token}` })
}
}).catch(() => { loading.close() })
}
@@ -69,7 +94,8 @@ export default {
</script>
<style lang="scss" scoped>
.share-image-container {
padding:50px;
padding: 50px;
.share-image-banner {
height: 500px;
width: 600px;
@@ -250,7 +250,7 @@ export default {
{
type: 'number',
min: 0,
max: 365,
// max: 365,
message: this.$t('common:ruleMessage:PacsSearchMaxDaysPattern'),
trigger: 'blur',
},
+93 -59
View File
@@ -1,69 +1,79 @@
<template>
<div class="hospital">
<el-form ref="hospitalForm" size="small" :model="hospital" :rules="hospitalFormRules" label-width="150px"
style="width: 800px">
<el-card class="Basic" shadow="never" size="small">
<el-form-item :label="$t('system:hospital:name')" prop="HospitalName">
<el-input v-model.trim="hospital.HospitalName" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:code')" prop="HospitalCode">
<el-input v-model.trim="hospital.HospitalCode" :disabled="disabled || hasPermi(['role:oa'])"
clearable />
</el-form-item>
<el-tabs v-model="activeTab" style="position: relative;height: 100%;">
<el-tab-pane name="hospital" :label="$t('system:hospital:tab:hospital')">
<div class="hospital">
<el-form ref="hospitalForm" size="small" :model="hospital" :rules="hospitalFormRules"
label-width="150px" style="width: 800px">
<el-card class="Basic" shadow="never" size="small">
<el-form-item :label="$t('system:hospital:name')" prop="HospitalName">
<el-input v-model.trim="hospital.HospitalName" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:code')" prop="HospitalCode">
<el-input v-model.trim="hospital.HospitalCode" :disabled="disabled || hasPermi(['role:sa'])"
clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:aliasName')" prop="HospitalAliasName">
<el-input v-model="hospital.HospitalAliasName" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:aliasName')" prop="HospitalAliasName">
<el-input v-model="hospital.HospitalAliasName" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:country')" prop="Country">
<el-input v-model="hospital.Country" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:province')" prop="Province">
<el-input v-model="hospital.Province" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:city')" prop="City">
<el-input v-model="hospital.City" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:address')" prop="Address">
<el-input v-model="hospital.Address" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:phone')" prop="Phone">
<el-input v-model="hospital.Phone" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:trialKeepCount')" prop="TrialKeepCount">
<el-input v-model="hospital.TrialKeepCount" :disabled="disabled || hasPermi(['role:sa'])"
type="number" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:isCanConnectInternet')"
v-hasPermi="['system:hospital:connectInternet']">
<el-switch v-model="hospital.IsCanConnectInternet" active-color="#13ce66"
inactive-color="#ff4949" :active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)" :disabled="disabled">
</el-switch>
</el-form-item>
<el-form-item :label="$t('system:hospital:logo')" prop="HospitalLogoPath">
<upload-logo :path.sync="hospital.HospitalLogoPath" :disabled="disabled" />
</el-form-item>
</el-card>
<el-form-item v-if="status === 'default' && hasPermi(['system:hospital:edit'])">
<el-button type="primary" size="small" style="margin: 10px 15px" :loading="btnLoading"
:disabled="btnLoading" @click="handleSave">{{ $t("system:hospital:save") }}</el-button>
</el-form-item>
</el-form>
<div class="btnBox" v-if="status !== 'default'">
<el-button type="primary" size="small" style="margin: 10px 15px" :loading="btnLoading"
:disabled="btnLoading" @click="handleSave">{{ $t("system:hospital:save") }}</el-button>
<el-button type="primary" size="small" style="margin: 10px 15px" @click="handleCancel">{{
$t("common:button:cancel") }}</el-button>
</div>
</div>
</el-tab-pane>
<el-tab-pane name="group" :label="$t('system:hospital:tab:group')">
<group-list v-if="activeTab === 'group'" />
</el-tab-pane>
</el-tabs>
<el-form-item :label="$t('system:hospital:country')" prop="Country">
<el-input v-model="hospital.Country" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:province')" prop="Province">
<el-input v-model="hospital.Province" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:city')" prop="City">
<el-input v-model="hospital.City" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:address')" prop="Address">
<el-input v-model="hospital.Address" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:phone')" prop="Phone">
<el-input v-model="hospital.Phone" :disabled="disabled" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:trialKeepCount')" prop="TrialKeepCount">
<el-input v-model="hospital.TrialKeepCount" :disabled="disabled || hasPermi(['role:oa'])"
type="number" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:isCanConnectInternet')"
v-hasPermi="['system:hospital:connectInternet']">
<el-switch v-model="hospital.IsCanConnectInternet" active-color="#13ce66" inactive-color="#ff4949"
active-text="" inactive-text="" :disabled="disabled">
</el-switch>
</el-form-item>
<el-form-item :label="$t('system:hospital:logo')" prop="HospitalLogoPath">
<upload-logo :path.sync="hospital.HospitalLogoPath" :disabled="disabled" />
</el-form-item>
</el-card>
<el-form-item v-if="status === 'default' && hasPermi(['system:hospital:edit'])">
<el-button type="primary" size="small" style="margin: 10px 15px" :loading="btnLoading"
:disabled="btnLoading" @click="handleSave">{{ $t("system:hospital:save") }}</el-button>
</el-form-item>
</el-form>
<div class="btnBox" v-if="status !== 'default'">
<el-button type="primary" size="small" style="margin: 10px 15px" :loading="btnLoading"
:disabled="btnLoading" @click="handleSave">{{ $t("system:hospital:save") }}</el-button>
<el-button type="primary" size="small" style="margin: 10px 15px" @click="handleCancel">{{
$t("common:button:cancel") }}</el-button>
</div>
</div>
</template>
<script>
import { getHospital } from "@/api/hospital.js";
import { addOrUpdateHIRHospital } from '@/api/admin'
import uploadLogo from "./uploadLogo.vue";
import groupList from "./groupList.vue";
export default {
name: "systemHospital",
components: { "upload-logo": uploadLogo },
components: { "upload-logo": uploadLogo, groupList },
props: {
status: {
type: String,
@@ -78,6 +88,7 @@ export default {
},
data() {
return {
activeTab: 'hospital',
hospital: {
HospitalName: null,
HospitalAliasName: null,
@@ -95,16 +106,16 @@ export default {
},
hospitalFormRules: {
HospitalName: [
{ required: true, message: "请输入医院名称", trigger: "blur" },
{ required: true, message: 'Please specify', trigger: "blur" },
],
HospitalCode: [
{ required: true, message: "请输入医院编码", trigger: "blur" },
{ required: true, message: 'Please specify', trigger: "blur" },
],
// HospitalLogoPath: [
// { required: true, message: "请上传医院logo", trigger: "blur" },
// ],
TrialKeepCount: [
{ required: true, message: "请输入未激活项目数", trigger: "blur" },
{ required: true, message: 'Please specify', trigger: "blur" },
],
// HospitalAliasName: [
// { required: true, message: "请输入医院别称", trigger: "blur" },
@@ -140,6 +151,11 @@ export default {
},
},
methods: {
clickTab(tab, event) {
this.activeTab = tab
console.log(this.activeTab)
// this.$router.push({ path: `/dictionary/template?tabActive=${tab.name}` });
},
async handleSave() {
if (this.btnLoading) return;
try {
@@ -184,6 +200,24 @@ export default {
margin-bottom: 40px;
}
::v-deep .el-tabs__header {
position: absolute;
top: 0;
left: 0;
z-index: 999;
width: 100%;
}
::v-deep .el-tabs__content {
padding-top: 50px;
height: 100%;
}
::v-deep .el-tab-pane {
height: 100%;
}
.hospital {
width: 100%;
height: 100%;
@@ -0,0 +1,310 @@
<template>
<div class="groupList">
<div ref="leftContainer">
<el-form :inline="true">
<el-form-item :label="$t('system:hospital:group:Code')" prop="Code">
<el-input v-model="searchData.Code" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:Name')" prop="Name">
<el-input v-model="searchData.Name" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:Affiliation')" prop="Affiliation">
<el-input v-model="searchData.Affiliation" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:ContactName')" prop="ContactName">
<el-input v-model="searchData.ContactName" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:ContactPhone')" prop="ContactPhone">
<el-input v-model="searchData.ContactPhone" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:State')" prop="IsEnable">
<el-select v-model="searchData.IsEnable" size="small" clearable style="width:100px">
<el-option v-for="item in $d.IsEnable" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">
{{ $t('common:button:search') }}
</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">
{{ $t('common:button:add') }}
</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 65 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'CreateTime', order: 'descending' }">
<el-table-column type="index" width="50" />
<el-table-column :label="$t('system:hospital:group:Code')" prop="Code" min-width="80"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:Name')" prop="Name" min-width="120"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:CallingAE')" prop="CallingAE" min-width="100"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:Affiliation')" prop="Affiliation" min-width="120"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:ContactName')" prop="ContactName" min-width="120"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:ContactPhone')" prop="ContactPhone" min-width="120"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:group:IdentityUserIdList')" prop="IdentityUserIdList"
min-width="80" show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<span>{{scope.row.GAUserList && scope.row.GAUserList.length > 0
? scope.row.GAUserList.map(item => item.UserName).join(", ") : ''}}</span>
</template>
</el-table-column>
<el-table-column :label="$t('system:hospital:group:State')" prop="IsEnable" show-overflow-tooltip>
<template slot-scope="scope">
<el-tag :type="!scope.row.IsEnable ? 'danger' : ''">
<span>{{ $fd("IsEnable", scope.row.IsEnable) }}</span>
</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('system:hospital:table:createTime')" prop="CreateTime" min-width="150"
sortable="custom" show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:updateTime')" prop="UpdateTime" min-width="150"
sortable="custom" show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" fixed="right" prop="" min-width="200"
show-overflow-tooltip>
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit-outline" @click="handleEdit(scope.row)">
{{ $t('common:button:edit') }}
</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination" style="text-align: right; margin-top: 5px">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</div>
</div>
<el-dialog top="3vh" :title="status === 'edit' ? $t('common:action:edit') : $t('common:button:new')" :visible.sync="visible" width="450px"
:close-on-click-modal="false" :close-on-press-escape="false" :append-to-body="true">
<el-form ref="hospitalGroupForm" size="small" :model="from" :rules="rules" label-width="100px">
<el-form-item :label="$t('system:hospital:group:Code')" prop="Code">
<el-input v-model.trim="from.Code" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:Name')" prop="Name">
<el-input v-model.trim="from.Name" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:CallingAE')" prop="CallingAE">
<el-input v-model.trim="from.CallingAE" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:Affiliation')" prop="Affiliation">
<el-input v-model="from.Affiliation" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:ContactName')" prop="ContactName">
<el-input v-model="from.ContactName" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:ContactPhone')" prop="ContactPhone">
<el-input v-model="from.ContactPhone" clearable />
</el-form-item>
<el-form-item :label="$t('system:hospital:group:IdentityUserIdList')" prop="IdentityUserIdList"
v-if="status === 'edit'">
<el-select ref="userType" v-model="from.IdentityUserIdList" size="small" placeholder="Please select"
multiple style="width: 100%">
<template v-for="user of GAUserList">
<el-option :key="user.Id" :label="user.UserName" :value="user.Id">
<span>{{ user.UserName }}</span>
<i style=" color: #F56C6C;float:right;margin-top: 10px;" class="el-icon-warning"
v-if="user.IsGACurrentHospitalDisabled || user.IsGARoleDisabled || user.IsUserDisabled"
:title="$t('system:hospital:group:tip:userDisabled')" />
</el-option>
</template>
</el-select>
</el-form-item>
<el-form-item :label="$t('system:hospital:group:State')" prop="IsEnable">
<el-switch v-model="from.IsEnable" :active-value="true" :inactive-value="false" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel" size="small">{{ $t('common:button:cancel') }}</el-button>
<el-button type="primary" size="small" @click="handleSave" :loading="loading">{{
$t('common:button:save')
}}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getHospitalGroupPageList, deleteHospitalGroup, addOrUpdateHospitalGroup, getGAUserList } from '@/api/admin'
import Pagination from '@/components/Pagination'
const searchDataDefault = () => {
return {
Name: null,
ContactPhone: null,
ContactName: null,
Code: null,
Affiliation: null,
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: "groupList",
components: { Pagination },
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
visible: false,
from: {
Id: null,
Affiliation: null,
Code: null,
ContactName: null,
ContactPhone: null,
Name: null,
IsEnable: true,
CallingAE: null,
IdentityUserIdList: []
},
rules: {
// Affiliation: [
// { required: true, message: 'Please specify', trigger: 'blur' },
// ],
Code: [
{ required: true, message: 'Please specify', trigger: 'blur' },
],
// ContactName: [
// { required: true, message: 'Please specify', trigger: 'blur' },
// ],
// ContactPhone: [
// { required: true, message: 'Please specify', trigger: 'blur' },
// ],
Name: [
{ required: true, message: 'Please specify', trigger: 'blur' },
],
// CallingAE: [
// { required: true, message: 'Please specify', trigger: 'blur' },
// ],
// IdentityUserIdList: [
// { required: true, type: 'array', message: 'Please select', trigger: 'blur' },
// ],
},
GAUserList: [],
status: 'add'
}
},
mounted() {
this.getList()
},
methods: {
async handleSave() {
try {
let validate = await this.$refs.hospitalGroupForm.validate()
if (!validate) return false
this.loading = true
let res = await addOrUpdateHospitalGroup(this.from)
this.loading = false
if (res.IsSuccess) {
this.$message.success(this.$t("common:message:savedSuccessfully"))
this.handleCancel()
this.getList()
}
} catch (err) {
console.log(err)
this.loading = false
}
},
handleCancel() {
this.visible = false
Object.keys(this.from).forEach(key => {
this.from[key] = null
})
this.from.IdentityUserIdList = []
},
async getGAUserList(HospitalGroupId) {
try {
let data = {
HospitalGroupId
}
let res = await getGAUserList(data)
if (res.IsSuccess) {
this.GAUserList = res.Result
}
} catch (err) {
console.log(err)
}
},
getList() {
this.loading = true
getHospitalGroupPageList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
handleAdd() {
// this.getGAUserList()
Object.keys(this.from).forEach(key => {
this.from[key] = null
})
this.from.IdentityUserIdList = []
this.status = 'add'
this.visible = true
},
handleEdit(row) {
this.getGAUserList(row.Id)
this.status = 'edit'
Object.keys(this.from).forEach(key => {
this.from[key] = row[key]
})
this.visible = true
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
handleDelete(row) {
this.$confirm(this.$t('system:hospital:message:handleDelete'), {
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => {
this.loading = true
deleteHospitalGroup(row.Id)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(
this.$t('common:message:deletedSuccessfully')
)
}
})
.catch(() => {
this.loading = false
})
})
},
//
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></style>
@@ -22,10 +22,10 @@
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">
查询
{{ $t('common:button:search') }}
</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">
新增
{{ $t('common:button:new') }}
</el-button>
</el-form-item>
</el-form>
@@ -37,9 +37,8 @@
<el-table-column :label="$t('system:hospital:table:hospitalAliasName')" prop="HospitalAliasName"
min-width="120" show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:hospital:table:country')" prop="Country" show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:city')" prop="City" show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:province')" prop="Province" show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:city')" prop="City" show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:address')" prop="Address" min-width="150"
show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:phone')" prop="Phone" min-width="150"
@@ -63,7 +62,7 @@
<el-table-column :label="$t('system:hospital:table:updateTime')" prop="UpdateTime" min-width="150"
show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" fixed="right" prop="" min-width="200"
<el-table-column :label="$t('common:action:action')" fixed="right" prop="" min-width="250"
show-overflow-tooltip>
<template slot-scope="scope">
<el-button size="mini" :disabled="scope.row.IsDefault" type="text" icon="el-icon-circle-check"
@@ -84,10 +83,10 @@
@pagination="getList" />
</div>
</div>
<el-dialog top="3vh" :title="status === 'edit' ? '编辑' : '新增'" :visible.sync="visible" width="850px">
<el-dialog top="3vh" :title="status === 'edit' ? $t('common:action:edit') : $t('common:button:new')"
:visible.sync="visible" :fullscreen="true">
<system-hospital v-if="visible" :status="status" :rowData="rowData" @getList="getList" @close="close" />
</el-dialog>
</div>
</template>
<script>
@@ -134,7 +133,7 @@ export default {
type: 'warning',
distinguishCancelAndClose: true,
}).then(async () => {
let res = await updateDefaultHospital({HirHospitalId:row.Id})
let res = await updateDefaultHospital({ HirHospitalId: row.Id })
if (res.IsSuccess) {
this.getList()
}
@@ -179,7 +178,7 @@ export default {
},
//
handleDelete(row) {
this.$confirm('是否确认删除?', {
this.$confirm(this.$t('system:hospital:message:handleDelete'), {
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => {
@@ -1,40 +1,21 @@
<template>
<div class="upload-container">
<el-upload
class="upload-demo"
:class="{ uploadDisabled: fileList.length > 0 ? true : false }"
action
:http-request="uploadFile"
:before-upload="beforeUpload"
:file-list="fileList"
:on-preview="handlePreview"
:on-remove="remove"
:limit="1"
:on-exceed="handleExceed"
accept=".png,.jpg,.jpeg"
v-if="!disabled"
list-type="picture-card"
>
<el-upload class="upload-demo" :class="{ uploadDisabled: fileList.length > 0 ? true : false }" action
:http-request="uploadFile" :before-upload="beforeUpload" :file-list="fileList" :on-preview="handlePreview"
:on-remove="remove" :limit="1" :on-exceed="handleExceed" accept=".png,.jpg,.jpeg" list-type="picture-card">
<!-- <el-button size="small" type="primary" :disabled="btnDisabled"
>上传</el-button
>
<span slot="tip" class="el-upload__tip">(只能上传png/jpg/jpeg文件)</span> -->
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{ file }">
<img
class="el-upload-list__item-thumbnail"
:src="`${OSSclientConfig.basePath}${file.url}`"
alt=""
crossorigin="anonymous"
/>
<img class="el-upload-list__item-thumbnail" :src="`${OSSclientConfig.basePath}${file.url}`" alt=""
crossorigin="anonymous" />
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
<span class="el-upload-list__item-delete" @click="handleRemove(file)" v-if="!disabled">
<i class="el-icon-delete"></i>
</span>
</span>
@@ -50,12 +31,7 @@
<span>{{ fileList.length > 0 ? fileList[0].name : "" }}</span>
</p> -->
<el-dialog :visible.sync="dialogVisible">
<img
width="70%"
:src="`${OSSclientConfig.basePath}${dialogImageUrl}`"
crossorigin="anonymous"
alt=""
/>
<img width="70%" :src="`${OSSclientConfig.basePath}${dialogImageUrl}`" crossorigin="anonymous" alt="" />
</el-dialog>
</div>
</template>
@@ -101,6 +77,7 @@ export default {
},
methods: {
remove(file, fileList) {
if (this.disabled) return false
this.$emit("update:path", null);
},
fileToBlob(file) {
@@ -160,8 +137,8 @@ export default {
const isValidFile = this.fileValid(file.name, ["png", "jpg", "jpeg"]);
if (isValidFile) {
this.fileList = [];
} else {
this.$alert("请上传PNG/JPG/JPEG文件");
} else { //PNG/JPG/JPEG
this.$alert(this.$t("system:hospital:uploadLog:verificationFormat"));
return false;
}
},
@@ -186,6 +163,7 @@ export default {
this.dialogVisible = true;
},
handleRemove(file) {
if (this.disabled) return false
this.fileList = [];
this.$emit("update:path", null);
},
@@ -198,24 +176,30 @@ export default {
width: 80px;
height: 30px;
}
.upload-container .el-form-item__label {
font-size: 12px;
}
.upload-container .el-upload-list__item {
font-size: 12px;
}
.logoAMessage {
font-size: 12px;
cursor: pointer;
}
.upload-container .uploadDisabled .el-upload--picture-card {
display: none;
}
.upload-container .el-upload--picture-card {
width: 150px;
height: 150px;
line-height: 150px;
}
.upload-container .el-upload-list--picture-card .el-upload-list__item {
width: 150px;
height: 150px;
+126 -134
View File
@@ -1,153 +1,127 @@
<template>
<base-model :config="model_cfg">
<template slot="dialog-body">
<el-form
ref="batcnAddForm"
v-loading="loading"
:model="form"
size="small"
>
<el-form-item label="国际化类型" prop="InternationalizationType">
<el-form ref="batcnAddForm" v-loading="loading" :model="form" size="small" :rules="rules">
<el-form-item :label="$t('system:l18n:search:InternationalizationType')" prop="InternationalizationType">
<el-radio-group v-model="form.InternationalizationType">
<el-radio
v-for="item of $d.InternationalizationType"
:key="'InternationalizationType'+item.value"
:label="item.value"
>{{ item.label }}</el-radio>
<el-radio v-for="item of $d.InternationalizationType" :key="'InternationalizationType' + item.value"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="状态" prop="State">
<el-form-item :label="$t('system:l18n:search:State')" prop="State">
<el-radio-group v-model="form.State">
<el-radio
v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState'+item.value"
:label="item.value"
>{{ item.label }}</el-radio>
<el-radio v-for="item of $d.InternationalizationKeyState" :key="'InternationalizationKeyState' + item.value"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-table
:data="form.AddList"
style="width: 100%"
height="300"
>
<el-table-column
prop=""
label="功能模块/服务名"
>
<el-form-item :label="$t('system:l18n:search:PublishVersion')" prop="PublishLogId">
<el-select v-model="form.PublishLogId" clearable filterable>
<el-option v-for="item in PublishVersionList" :key="item.Id" :label="item.Version" :value="item.Id" />
</el-select>
</el-form-item>
<el-table :data="form.AddList" style="width: 100%" height="300">
<el-table-column prop="" :label="$t('system:l18n:search:Module')">
<template slot-scope="scope">
<el-form-item
label=""
:prop="`AddList.${scope.$index}.Description`"
:rules="[
{ required: true,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
{ max: 200, message: `${$t('common:ruleMessage:maxLength')} 200` }
]"
>
<el-input
v-model="scope.row.Description"
type="textarea"
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item label="" :prop="`AddList.${scope.$index}.Module`" :rules="[
{
max: 200,
message: `${$t('common:ruleMessage:maxLength')} 200`,
trigger: ['change', 'blur'],
},
]">
<el-input v-model="scope.row.Module" type="textarea" maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop=""
label="标识"
>
<el-table-column prop="" :label="$t('system:l18n:search:Code')">
<template slot-scope="scope">
<el-form-item
label=""
:prop="`AddList.${scope.$index}.Code`"
:rules="[
{ required: true,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
{ max: 200, message: `${$t('common:ruleMessage:maxLength')} 200` }
]"
>
<el-input
v-model="scope.row.Code"
type="textarea"
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item label="" :prop="`AddList.${scope.$index}.Code`" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: ['change', 'blur'],
},
{
max: 200,
message: `${$t('common:ruleMessage:maxLength')} 200`,
},
]">
<el-input v-model="scope.row.Code" type="textarea" maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop=""
label="中文值"
>
<el-table-column prop="" :label="$t('system:l18n:search:ValueCN')">
<template slot-scope="scope">
<el-form-item
label=""
:prop="`AddList.${scope.$index}.ValueCN`"
:rules="[
{ required: true,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
{ max: 1000, message: `${$t('common:ruleMessage:maxLength')} 1000` }
]"
>
<el-input
v-model="scope.row.ValueCN"
type="textarea"
maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item label="" :prop="`AddList.${scope.$index}.ValueCN`" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: ['change', 'blur'],
},
{
max: 1000,
message: `${$t('common:ruleMessage:maxLength')} 1000`,
},
]">
<el-input v-model="scope.row.ValueCN" type="textarea" maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop=""
label="英文值"
>
<el-table-column prop="" :label="$t('system:l18n:search:Value')">
<template slot-scope="scope">
<el-form-item
label=""
:prop="`AddList.${scope.$index}.Value`"
:rules="[
{ required: true,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
{ max: 1000, message: `${$t('common:ruleMessage:maxLength')} 1000` }
]"
>
<el-input
v-model="scope.row.Value"
type="textarea"
maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item label="" :prop="`AddList.${scope.$index}.Value`" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: ['change', 'blur'],
},
{
max: 1000,
message: `${$t('common:ruleMessage:maxLength')} 1000`,
},
]">
<el-input v-model="scope.row.Value" type="textarea" maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
align="right"
width="100"
>
<el-table-column prop="" :label="$t('system:l18n:search:Description')">
<template slot-scope="scope">
<el-form-item label="" :prop="`AddList.${scope.$index}.Description`" :rules="[
{
max: 200,
message: `${$t('common:ruleMessage:maxLength')} 200`,
trigger: ['change', 'blur'],
},
]">
<el-input v-model="scope.row.Description" type="textarea" maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="right" width="100">
<template slot="header">
<!-- 新增 -->
<el-button
size="small"
type="primary"
icon="el-icon-plus"
@click="handleAdd"
>{{ $t('common:button:new') }}</el-button>
<el-button size="small" type="primary" @click="handleAdd">{{ $t('common:button:new') }}</el-button>
</template>
<template slot-scope="scope">
<!-- 删除 -->
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.$index)"
>{{ $t('common:button:delete') }}</el-button>
<el-button type="text" @click="handleDelete(scope.$index)">{{ $t('common:button:delete') }}</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</template>
<template slot="dialog-footer">
<el-button size="small" type="primary" @click="handleCancle">取消</el-button>
<el-button size="small" type="primary" @click="handleSave">保存</el-button>
<el-button size="small" type="primary" @click="handleCancle">{{
$t('common:button:cancel')
}}</el-button>
<el-button size="small" type="primary" @click="handleSave">{{
$t('common:button:save')
}}</el-button>
</template>
</base-model>
</template>
@@ -158,7 +132,8 @@ const formDataDefault = () => {
return {
State: 0,
InternationalizationType: 1,
AddList: []
PublishLogId: null,
AddList: [],
}
}
export default {
@@ -168,30 +143,47 @@ export default {
return {
loading: false,
form: formDataDefault(),
model_cfg: { visible: false, showClose: true, width: '800px', title: '', appendToBody: true }
model_cfg: {
visible: false,
showClose: true,
width: '800px',
title: '',
appendToBody: true,
},
rules: {
PublishLogId: [
{
required: true,
message: this.$t('system:l18n:rule:selectPublishLogId'),
trigger: 'blur',
},
],
},
PublishVersionList: [],
}
},
mounted() {
},
mounted() { },
methods: {
openDialog(title, data) {
openDialog(title, data, options = []) {
this.PublishVersionList = options
this.model_cfg.visible = true
this.model_cfg.title = title
this.form = formDataDefault()
},
handleSave() {
this.$refs.batcnAddForm.validate(valid => {
this.$refs.batcnAddForm.validate((valid) => {
if (!valid) return
this.loading = true
batchAddInternationalization(this.form).then(res => {
this.loading = false
this.$message.success('保存成功!')
this.model_cfg.visible = false
this.$emit('getList')
}).catch(() => {
this.loading = false
})
batchAddInternationalization(this.form)
.then((res) => {
this.loading = false
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.model_cfg.visible = false
this.$emit('getList')
})
.catch(() => {
this.loading = false
})
})
},
handleCancle() {
@@ -202,17 +194,17 @@ export default {
Description: '',
Code: '',
ValueCN: '',
Value: ''
Value: '',
})
},
handleDelete(index) {
this.$confirm('是否确认删除?', {
this.$confirm(this.$t('system:l18n:confirm:delete'), {
type: 'warning',
distinguishCancelAndClose: true
distinguishCancelAndClose: true,
}).then(() => {
this.form.AddList.splice(index, 1)
})
}
}
},
},
}
</script>
+125 -79
View File
@@ -1,70 +1,49 @@
<template>
<base-model :config="model_cfg">
<template slot="dialog-body">
<el-form
ref="i18nForm"
v-loading="loading"
:model="form"
:rules="rules"
label-width="130px"
size="small"
>
<el-form-item label="国际化类型" prop="InternationalizationType">
<el-form ref="i18nForm" v-loading="loading" :model="form" :rules="rules" label-width="130px" size="small">
<el-form-item :label="$t('system:l18n:search:InternationalizationType')" prop="InternationalizationType"
v-if="status !== 'batch'">
<el-radio-group v-model="form.InternationalizationType">
<el-radio
v-for="item of $d.InternationalizationType"
:key="'InternationalizationType'+item.value"
:label="item.value"
>{{ item.label }}</el-radio>
<el-radio v-for="item of $d.InternationalizationType" :key="'InternationalizationType' + item.value"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="功能模块/服务名" prop="Description">
<el-input
v-model="form.Description"
type="textarea"
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item :label="$t('system:l18n:search:Module')" prop="Module" v-if="status !== 'batch'">
<el-input v-model="form.Module" type="textarea" maxlength="200" :autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
<el-form-item label="标识" prop="Code">
<el-input
v-model="form.Code"
type="textarea"
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item :label="$t('system:l18n:search:Code')" prop="Code" v-if="status !== 'batch'">
<el-input v-model="form.Code" type="textarea" maxlength="200" :autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
<el-form-item label="中文值" prop="ValueCN">
<el-input
v-model="form.ValueCN"
type="textarea"
maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item :label="$t('system:l18n:search:ValueCN')" prop="ValueCN" v-if="status !== 'batch'">
<el-input v-model="form.ValueCN" type="textarea" maxlength="1000" :autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
<el-form-item label="英文值" prop="Value">
<el-input
v-model="form.Value"
type="textarea"
maxlength="1000"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<el-form-item :label="$t('system:l18n:search:Value')" prop="Value" v-if="status !== 'batch'">
<el-input v-model="form.Value" type="textarea" maxlength="1000" :autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
<el-form-item label="状态" prop="State">
<el-form-item :label="$t('system:l18n:search:State')" prop="State">
<el-radio-group v-model="form.State">
<el-radio
v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState'+item.value"
:label="item.value"
>{{ item.label }}</el-radio>
<el-radio v-for="item of $d.InternationalizationKeyState" :key="'InternationalizationKeyState' + item.value"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('system:l18n:search:Description')" prop="Description" v-if="status !== 'batch'">
<el-input v-model="form.Description" type="textarea" maxlength="200" :autosize="{ minRows: 2, maxRows: 4 }" />
</el-form-item>
<el-form-item :label="$t('system:l18n:search:PublishVersion')" prop="PublishLogId">
<el-select v-model="form.PublishLogId" clearable filterable>
<el-option v-for="item in PublishVersionList" :key="item.Id" :label="item.Version" :value="item.Id" />
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<el-button size="small" type="primary" @click="handleCancle">取消</el-button>
<el-button size="small" type="primary" @click="handleSave">保存</el-button>
<el-button size="small" type="primary" @click="handleCancle">{{
$t('common:button:cancel')
}}</el-button>
<el-button size="small" type="primary" @click="handleSave">{{
$t('common:button:save')
}}</el-button>
</template>
</base-model>
</template>
@@ -76,10 +55,12 @@ const formDataDefault = () => {
Id: null,
State: 0,
Description: null,
Module: null,
Code: null,
Value: null,
ValueCN: null,
InternationalizationType: 1
InternationalizationType: 1,
PublishLogId: null,
}
}
export default {
@@ -87,40 +68,95 @@ export default {
components: { BaseModel },
data() {
return {
status: 'add', // add update batch
loading: false,
form: formDataDefault(),
rules: {
State: [
{ required: true, message: '请选择', trigger: 'blur' }
{
required: true,
message: this.$t('system:l18n:rule:selectState'),
trigger: 'blur',
},
],
Module: [
{
max: 200,
message: `${this.$t('common:ruleMessage:maxLength')} 200`,
trigger: 'blur',
},
],
Description: [
{ required: true, message: '请注明', trigger: 'blur' },
{ max: 200, message: `${this.$t('common:ruleMessage:maxLength')} 200` }
{
max: 200,
message: `${this.$t('common:ruleMessage:maxLength')} 200`,
trigger: 'blur',
},
],
Code: [
{ required: true, message: '请注明', trigger: 'blur' },
{ max: 200, message: `${this.$t('common:ruleMessage:maxLength')} 200` }
{
required: true,
message: this.$t('system:l18n:rule:inputCode'),
trigger: 'blur',
},
{
max: 200,
message: `${this.$t('common:ruleMessage:maxLength')} 200`,
},
],
Value: [
{ required: true, message: '请注明', trigger: 'blur' },
{ max: 1000, message: `${this.$t('common:ruleMessage:maxLength')} 1000` }
{
required: true,
message: this.$t('system:l18n:rule:inputValue'),
trigger: 'blur',
},
{
max: 1000,
message: `${this.$t('common:ruleMessage:maxLength')} 1000`,
},
],
ValueCN: [
{ required: true, message: '请注明', trigger: 'blur' },
{ max: 1000, message: `${this.$t('common:ruleMessage:maxLength')} 1000` }
{
required: true,
message: this.$t('system:l18n:rule:inputValueCN'),
trigger: 'blur',
},
{
max: 1000,
message: `${this.$t('common:ruleMessage:maxLength')} 1000`,
},
],
InternationalizationType: [
{ required: true, message: '请选择', trigger: 'blur' }
]
{
required: true,
message: this.$t('system:l18n:rule:selectInternationalizationType'),
trigger: 'blur',
},
],
PublishLogId: [
{
required: true,
message: this.$t('system:l18n:rule:selectPublishLogId'),
trigger: 'blur',
},
],
},
model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true }
model_cfg: {
visible: false,
showClose: true,
width: '600px',
title: '',
appendToBody: true,
},
PublishVersionList: [],
}
},
mounted() {
},
mounted() { },
methods: {
openDialog(title, data) {
openDialog(title, data, options = [], status) {
this.PublishVersionList = options
this.loading = false
this.status = status
this.model_cfg.visible = true
this.model_cfg.title = title
if (Object.keys(data).length > 0) {
@@ -134,22 +170,32 @@ export default {
}
},
handleSave() {
this.$refs.i18nForm.validate(valid => {
this.$refs.i18nForm.validate((valid) => {
if (!valid) return
this.loading = true
addOrUpdateInternationalization(this.form).then(res => {
this.loading = false
this.$message.success('保存成功!')
this.model_cfg.visible = false
this.$emit('getList')
}).catch(() => {
this.loading = false
})
if (this.status === 'batch') {
return this.$emit('batch', this.form)
}
addOrUpdateInternationalization(this.form)
.then((res) => {
this.loading = false
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.model_cfg.visible = false
this.$emit('getList')
})
.catch(() => {
this.loading = false
})
})
},
handleCancle() {
this.model_cfg.visible = false
}
}
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-select {
width: 100%;
}
</style>
+276 -218
View File
@@ -2,156 +2,118 @@
<div class="log">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item label="国际化类型">
<el-select
v-model="searchData.InternationalizationType"
clearable
filterable
style="width:130px;"
>
<el-option
v-for="item of $d.InternationalizationType"
:key="'InternationalizationType'+item.value"
:label="item.label"
:value="item.value"
/>
<el-form-item :label="$t('system:l18n:search:InternationalizationType')">
<el-select v-model="searchData.InternationalizationType" clearable filterable style="width: 130px">
<el-option v-for="item of $d.InternationalizationType" :key="'InternationalizationType' + item.value"
:label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="功能模块/服务名">
<el-input
v-model="searchData.Description"
size="small"
clearable
style="width:130px;"
/>
<el-form-item :label="$t('system:l18n:search:Module')">
<el-input v-model="searchData.Module" clearable style="width: 130px" />
</el-form-item>
<el-form-item label="标识">
<el-input
v-model="searchData.Code"
size="small"
clearable
style="width:130px;"
/>
<el-form-item :label="$t('system:l18n:search:Code')">
<el-input v-model="searchData.Code" clearable style="width: 130px" />
</el-form-item>
<el-form-item label="中文值">
<el-input
v-model="searchData.ValueCN"
size="small"
clearable
style="width:130px;"
/>
<el-form-item :label="$t('system:l18n:search:ValueCN')">
<el-input v-model="searchData.ValueCN" clearable style="width: 130px" />
</el-form-item>
<el-form-item label="英文值">
<el-input
v-model="searchData.Value"
size="small"
style="width:130px;"
clearable
/>
<el-form-item :label="$t('system:l18n:search:Value')">
<el-input v-model="searchData.Value" style="width: 130px" clearable />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchData.State" clearable filterable style="width:130px;">
<el-option
v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState'+item.value"
:label="item.label"
:value="item.value"
/>
<el-form-item :label="$t('system:l18n:search:State')">
<el-select v-model="searchData.State" clearable filterable style="width: 130px">
<el-option v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('system:l18n:search:Description')">
<el-input v-model="searchData.Description" clearable style="width: 130px" />
</el-form-item>
<el-form-item :label="$t('system:l18n:search:PublishVersion')">
<el-select v-model="searchData.PublishLogId" clearable filterable style="width: 130px">
<el-option v-for="item in PublishVersionList" :key="item.Id" :label="item.Version" :value="item.Id" />
</el-select>
</el-form-item>
<el-form-item :label="$t('system:l18n:form:createTime')">
<el-date-picker v-model="datetimerange_createTime" type="datetimerange"
:default-time="['00:00:00', '23:59:59']" :start-placeholder="$t('system:l18n:search:beginTime')"
:end-placeholder="$t('system:l18n:search:endTime')" value-format="yyyy-MM-dd HH:mm:ss"
@change="(val) => handleDatetimeChange(val, 'createTime')" style="width: 250px" />
</el-form-item>
<el-form-item :label="$t('system:l18n:form:uploadTime')">
<el-date-picker v-model="datetimerange_updateTime" type="datetimerange"
:default-time="['00:00:00', '23:59:59']" :start-placeholder="$t('system:l18n:search:beginTime')"
:end-placeholder="$t('system:l18n:search:endTime')" value-format="yyyy-MM-dd HH:mm:ss"
@change="(val) => handleDatetimeChange(val, 'updateTime')" style="width: 250px" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
查询
<el-button type="primary" icon="el-icon-search" @click="getList">
{{ $t('common:button:search') }}
</el-button>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>
新增
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleBatchAdd"
>
批量新增
<el-button type="primary" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
<el-button type="primary" @click="handleBatchAdd">
{{ $t('system:l18n:button:batchAdd') }}
</el-button>
<el-button type="primary" :disabled="selectTableList.length <= 0" @click="handleBatchUpdate">
{{ $t('system:l18n:button:batchUpdate') }}
</el-button>
<el-button type="primary" :disabled="selectTableList.length <= 0" @click="handleBatchUpdateToChange">
{{ $t('system:l18n:button:batchEdit') }}
</el-button>
<el-button type="primary" @click="exportTable">
{{ $t('common:button:export') }}
</el-button>
</el-form-item>
</el-form>
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
height="100"
:data="list"
class="table"
@sort-change="handleSortByColumn"
>
<el-table-column
type="index"
width="50"
/>
<el-table-column
label="国际化类型"
prop="InternationalizationType"
width="120"
show-overflow-tooltip
sortable="custom"
>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn" @selection-change="handleSelectionChange"><el-table-column type="selection"
width="50" />
<el-table-column type="index" width="50" />
<el-table-column :label="$t('system:l18n:search:InternationalizationType')" prop="InternationalizationType"
width="120" show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<el-tag v-if="scope.row.InternationalizationType === 0" type="primary">
{{ $fd('InternationalizationType', scope.row.InternationalizationType) }}
{{
$fd(
'InternationalizationType',
scope.row.InternationalizationType
)
}}
</el-tag>
<el-tag v-else-if="scope.row.InternationalizationType === 1" type="warning">
{{ $fd('InternationalizationType', scope.row.InternationalizationType) }}
{{
$fd(
'InternationalizationType',
scope.row.InternationalizationType
)
}}
</el-tag>
<el-tag v-else>
{{ $fd('InternationalizationType', scope.row.InternationalizationType) }}
{{
$fd(
'InternationalizationType',
scope.row.InternationalizationType
)
}}
</el-tag>
</template>
</el-table-column>
<el-table-column
label="功能模块/服务名"
prop="Description"
min-width="100"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="标识"
prop="Code"
min-width="150"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="中文值"
prop="ValueCN"
min-width="150"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="英文值"
prop="Value"
min-width="150"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="状态"
prop="State"
width="100"
show-overflow-tooltip
sortable="custom"
>
<el-table-column :label="$t('system:l18n:search:Module')" prop="Module" min-width="140" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:l18n:search:Code')" prop="Code" min-width="150" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:l18n:search:ValueCN')" prop="ValueCN" min-width="150" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:l18n:search:Value')" prop="Value" min-width="150" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:l18n:search:State')" prop="State" width="100" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<el-tag v-if="scope.row.State === 0" type="danger">
{{ $fd('InternationalizationKeyState', scope.row.State) }}
@@ -164,61 +126,43 @@
</el-tag>
</template>
</el-table-column>
<el-table-column
label="更新时间"
prop="UpdateTime"
width="150"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="操作"
fixed="right"
prop=""
min-width="120"
show-overflow-tooltip
>
<el-table-column :label="$t('system:l18n:search:Description')" prop="Description" min-width="110"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:l18n:search:PublishVersion')" prop="Version" min-width="100"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:l18n:form:uploadTime')" prop="UpdateTime" width="150" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:l18n:form:createTime')" prop="CreateTime" width="150" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('common:action:action')" fixed="right" prop="" min-width="120"
show-overflow-tooltip>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>
编辑
<el-button type="text" @click="handleEdit(scope.row)">
{{ $t('common:button:edit') }}
</el-button>
<el-button
:disabled="scope.row.State === 1"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>
删除
<el-button :disabled="scope.row.State === 1" type="text" @click="handleDelete(scope.row)">
{{ $t('common:button:delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination" style="text-align: right;margin-top:5px;">
<pagination
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<div class="pagination" style="text-align: right; margin-top: 5px">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</div>
<i18n-form
ref="i18nForm"
@getList="getList"
/>
<i18n-form ref="i18nForm" @getList="getList" @batch="batch" />
<BatchAddForm ref="batcnAddForm" @getList="getList" />
</div>
</div>
</template>
<script>
import { getInternationalizationList, deleteInternationalization } from '@/api/admin'
import {
getInternationalizationList,
deleteInternationalization,
getPublishVersionSelect,
batchUpdateInternationalInfo,
} from '@/api/admin'
import { GetInternationalizationList_Export } from '@/api/export'
import Pagination from '@/components/Pagination'
import I18nForm from './components/I18nForm.vue'
import BatchAddForm from './components/BatchAddForm.vue'
@@ -230,10 +174,16 @@ const searchDataDefault = () => {
ValueCN: null,
InternationalizationType: null,
State: null,
Module: null,
PublishLogId: null,
Asc: true,
SortField: '',
PageIndex: 1,
PageSize: 20
PageSize: 20,
BeginCreateTime: null,
EndCreatTime: null,
BeginUpdateTime: null,
EndUpdateTime: null,
}
}
export default {
@@ -245,60 +195,136 @@ export default {
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false
loading: false,
PublishVersionList: [],
selectTableList: [],
datetimerange_createTime: [],
datetimerange_updateTime: [],
}
},
mounted() {
this.getList()
this.getPublishVersionSelect()
this.$EventBus.$on('il8nUpdate', (data) => {
this.getList()
})
},
methods: {
//
async getPublishVersionSelect() {
try {
let res = await getPublishVersionSelect()
if (res.IsSuccess) {
this.PublishVersionList = res.Result
}
} catch (err) {
console.log(err)
}
},
getList() {
this.loading = true
getInternationalizationList(this.searchData).then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
getInternationalizationList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
//
handleBatchUpdate() {
this.$nextTick(() => {
this.$refs['i18nForm'].openDialog(
this.$t('system:l18n:button:batchUpdate'),
{},
this.PublishVersionList,
'batch'
)
})
},
//
handleBatchUpdateToChange() {
this.$openI18n(this.selectTableList)
},
async batch(row) {
let { PublishLogId, State } = row
let data = {
PublishLogId,
State,
IdList: this.selectTableList.map((item) => item.Id),
}
try {
let res = await batchUpdateInternationalInfo(data)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:updatedSuccessfully'))
this.getList()
this.$nextTick(() => {
this.$refs['i18nForm'].handleCancle()
})
}
} catch (err) {
console.log(err)
}
},
handleAdd() {
this.$nextTick(() => {
this.$refs['i18nForm'].openDialog('新增', {})
this.$refs['i18nForm'].openDialog(
this.$t("common:button:new"),
{},
this.PublishVersionList,
'add'
)
})
},
handleBatchAdd() {
this.$nextTick(() => {
this.$refs['batcnAddForm'].openDialog('批量新增', {})
this.$refs['batcnAddForm'].openDialog(
this.$t("system:l18n:button:batchAdd"),
{},
this.PublishVersionList
)
})
},
handleEdit(row) {
this.$nextTick(() => {
this.$refs['i18nForm'].openDialog('编辑', row)
this.$refs['i18nForm'].openDialog(
this.$t("common:button:edit"),
row,
this.PublishVersionList,
'update'
)
})
},
//
handleReset() {
this.searchData = searchDataDefault()
this.datetimerange_createTime = []
this.datetimerange_updateTime = []
this.getList()
},
//
handleDelete(row) {
this.$confirm('是否确认删除?', {
this.$confirm(this.$t("system:l18n:confirm:delete"), {
type: 'warning',
distinguishCancelAndClose: true
distinguishCancelAndClose: true,
}).then(() => {
this.loading = true
deleteInternationalization(row.Id)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(
this.$t('common:message:deletedSuccessfully')
)
}
})
.catch(() => {
this.loading = false
})
})
.then(() => {
this.loading = true
deleteInternationalization(row.Id)
.then(res => {
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
}).catch(() => { this.loading = false })
})
},
//
handleSortByColumn(column) {
@@ -310,35 +336,67 @@ export default {
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
}
}
},
//
handleSelectionChange(val) {
this.selectTableList = val
},
handleDatetimeChange(val, key) {
if (val) {
if (key === 'createTime') {
this.searchData.BeginCreateTime = val[0]
this.searchData.EndCreatTime = val[1]
}
if (key === 'updateTime') {
this.searchData.BeginUpdateTime = val[0]
this.searchData.EndUpdateTime = val[1]
}
} else {
if (key === 'createTime') {
this.searchData.BeginCreateTime = ''
this.searchData.EndCreatTime = ''
}
if (key === 'updateTime') {
this.searchData.BeginUpdateTime = ''
this.searchData.EndUpdateTime = ''
}
}
},
exportTable() {
return GetInternationalizationList_Export(this.searchData)
},
},
}
</script>
<style lang="scss">
.log {
height: 100%;
box-sizing: border-box;
.log {
height: 100%;
box-sizing: border-box;
display: flex;
padding: 10px;
border-radius: 5px;
.left {
display: flex;
padding: 10px;
border-radius: 5px;
.left {
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
}
}
</style>
+103
View File
@@ -0,0 +1,103 @@
<template>
<base-model v-if="config.visible" :config="config">
<template slot="dialog-body">
<el-table :data="curData" border style="width: 100%" size="small">
<el-table-column prop="key" :label="$t('system:loginLog:table:cfgItem')" show-overflow-tooltip />
<el-table-column prop="value" :label="$t('system:loginLog:table:cfgVal')" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.prop === 'HospitalGroupList'">{{
Array.isArray(scope.row.value) ? scope.row.value.map(item => item.Name).join(", ") : ''
}}</span>
<span v-else-if="scope.row.prop !== 'UserRoleList'">{{
scope.row.value
}}</span>
<template v-else>
<div v-for="item in scope.row.value" :key="item.UserTypeEnum" style="margin: 0">
{{ item.UserTypeShortName
}}{{ $t('system:loginLog:form:symbol')
}}{{ $fd('IsEnable', !item.IsUserRoleDisabled) }}
</div>
</template>
</template>
</el-table-column>
</el-table>
</template>
<template slot="dialog-footer">
<el-button type="primary" @click="config.visible = false">
{{ $t('common:button:confirm') }}
</el-button>
</template>
</base-model>
</template>
<script>
import BaseModel from '@/components/BaseModel'
export default {
components: { BaseModel },
props: {
JsonObj: {
type: String,
default: '',
},
config: {
type: Object,
default: () => {
return {
visible: false,
title: this.$t('system:loginLog:dialog:title'),
width: '500px',
top: '10vh',
appendToBody: true,
bodyStyle: `min-height: 100px; max-height: 650px;overflow-y: auto;padding: 10px;border: 1px solid #e0e0e0;`,
}
},
},
},
data() {
return {
curKeys: [
'UserName',
'FirstName',
'LastName',
'EMail',
'Phone',
'Status',
'HospitalGroupList',
'OrganizationName',
'PositionName',
'DepartmentName',
'UserRoleList',
],
}
},
computed: {
curDataArr() {
if (!this.curData) return []
return Object.keys(this.curData)
},
curData() {
if (!this.JsonObj) return []
let obj = JSON.parse(this.JsonObj)
let curData = []
Object.keys(obj).forEach((key) => {
if (this.curKeys.includes(key)) {
let o = {
key: this.$t(`system:loginLog:form:${key}`),
value: obj[key],
prop: key,
}
if (key === 'Status') {
o.value = this.$fd('IsEnable', !!obj[key])
}
curData.push(o)
}
})
return curData
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-form-item__label {
font-weight: bold;
}
</style>
+185 -156
View File
@@ -2,179 +2,155 @@
<div class="log">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item
label="操作类型"
prop="OptType"
>
<el-select v-model="searchData.OptType" clearable style="width:120px;">
<el-option
v-for="item of $d.UserOptType"
:key="'UserOptType' + item.label"
:value="item.value"
:label="item.label"
/>
<el-form-item :label="$t('system:loginLog:label:OptType')" prop="OptType">
<el-select v-model="searchData.OptTypeList" clearable style="width: 200px" multiple :collapse-tags="true">
<el-option v-for="item of $d.UserOptType" :key="'UserOptType' + item.label" :value="item.value"
:label="item.label" />
</el-select>
</el-form-item>
<el-form-item
label="IP"
prop="IP"
>
<el-input
v-model="searchData.IP"
size="small"
clearable
style="width:120px;"
/>
<el-form-item label="IP" prop="IP">
<el-input v-model="searchData.IP" size="small" clearable style="width: 120px" />
</el-form-item>
<el-form-item
label="错误用户名"
prop="LoginFaildName"
>
<el-input
v-model="searchData.LoginFaildName"
size="small"
clearable
style="width:120px;"
/>
<el-form-item :label="$t('system:loginLog:label:LoginFaildName')" prop="LoginFaildName">
<el-input v-model="searchData.LoginFaildName" size="small" clearable style="width: 120px" />
</el-form-item>
<el-form-item
label="创建时间"
>
<el-date-picker
v-model="datetimerange"
type="datetimerange"
range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
@change="handleDatetimeChange"
/>
<el-form-item :label="$t('system:loginLog:table:LoginUserName')" prop="LoginFaildName">
<el-input v-model="searchData.LoginUserName" size="small" clearable style="width: 120px" />
</el-form-item>
<!-- <el-form-item :label="$t('system:loginLog:table:LoginUserType')" prop="LoginUserTypeEnum">
<el-select v-model="searchData.LoginUserTypeEnum" clearable style="width: 120px">
<el-option v-for="item of $d.UserType" :key="'UserType' + item.label" :value="item.value"
:label="item.label" />
</el-select>
</el-form-item> -->
<el-form-item :label="$t('system:loginLog:label:IsLoginUncommonly')" prop="IsLoginUncommonly ">
<el-select v-model="searchData.IsLoginUncommonly" clearable style="width: 120px">
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
</el-select>
</el-form-item>
<el-form-item :label="$t('system:loginLog:label:CreateTime')">
<el-date-picker v-model="datetimerange" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss"
range-separator="-" :start-placeholder="$t('system:loginLog:placeholder:startTime')"
:end-placeholder="$t('system:loginLog:placeholder:endTime')" :default-time="['00:00:00', '23:59:59']"
@change="handleDatetimeChange" style="width: 380px" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="getList"
>
查询
<el-button type="primary" icon="el-icon-search" @click="getList">
{{ $t('common:button:search') }}
</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
height="100"
:data="list"
class="table"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'CreateTime', order: 'descending' }"
>
<el-table-column
type="index"
width="50"
/>
<el-table-column
label="操作类型"
prop="OptType"
min-width="90"
show-overflow-tooltip
sortable="custom"
>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn">
<el-table-column type="index" width="50">
<template slot-scope="scope">
{{ $fd('UserOptType',scope.row.OptType) }}
<span style="
display: flex;
align-items: center;
justify-content: flex-end;
">
<el-tooltip class="item" effect="dark" :content="$t('system:loginLog:label:IsLoginUncommonly')"
placement="top" style="margin-right: 3px" v-if="scope.row.IsIgnoreUncommonly">
<i v-if="scope.row.IsLoginUncommonly" class="el-icon-warning icon-i icon-success"></i>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="$t('system:loginLog:label:IsLoginUncommonly')"
placement="top" style="margin-right: 3px" v-else-if="scope.row.IsLoginUncommonly">
<i v-if="scope.row.IsLoginUncommonly" class="el-icon-warning icon-i"
@click.stop="setIsIgnoreUncommonly(scope.row)"></i>
</el-tooltip>
<span>{{ scope.$index + 1 }}</span>
</span>
</template>
</el-table-column>
<el-table-column
label="IP"
prop="IP"
min-width="90"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
label="错误用户名"
<el-table-column :label="$t('system:loginLog:table:OptType')" prop="OptType" min-width="150"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
{{ $fd('UserOptType', scope.row.OptType) }}
</template>
</el-table-column>
<el-table-column label="IP" prop="IP" min-width="150" sortable="custom" show-overflow-tooltip />
<el-table-column :label="$t('trials:loginLog:table:IPRegion')" prop="IPRegion" min-width="120"
show-overflow-tooltip sortable="custom" />
<!-- <el-table-column
:label="$t('system:loginLog:table:LoginFaildName')"
prop="LoginFaildName"
min-width="90"
min-width="180"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="用户名"
prop="LoginUserName"
min-width="90"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
label="用户类型"
/> -->
<el-table-column :label="$t('system:loginLog:table:LoginUserName')" prop="ActionUserName" min-width="140"
show-overflow-tooltip sortable="custom" />
<el-table-column :label="$t('system:loginLog:table:Aetionlserlype')" prop="ActionUserType" min-width="100"
show-overflow-tooltip sortable="custom" />
<!-- <el-table-column
:label="$t('system:loginLog:table:LoginUserType')"
prop="LoginUserTypeEnum"
min-width="90"
min-width="120"
sortable="custom"
show-overflow-tooltip
>
<template slot-scope="scope">
{{ $fd('UserType',scope.row.LoginUserTypeEnum) }}
{{ $fd("UserType", scope.row.LoginUserTypeEnum) }}
</template>
</el-table-column>
<el-table-column
label="操作用户名"
prop="OptUserName"
min-width="90"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
label="操作用户类型"
</el-table-column> -->
<el-table-column :label="$t('system:loginLog:table:OptUserName')" prop="TargetIdentityUserName" min-width="200"
sortable="custom" show-overflow-tooltip />
<!-- <el-table-column
:label="$t('system:loginLog:table:OptUserType')"
prop="OptUserTypeEnum"
min-width="90"
min-width="200"
sortable="custom"
show-overflow-tooltip
>
<template slot-scope="scope">
{{ $fd('UserType',scope.row.OptUserTypeEnum) }}
{{ $fd("UserType", scope.row.OptUserTypeEnum) }}
</template>
</el-table-column> -->
<el-table-column :label="$t('system:loginLog:table:detail')" min-width="120" show-overflow-tooltip>
<template slot-scope="scope">
<el-button v-if="scope.row.JsonObj" type="text" @click="handleOpenDialog(scope.row)">
<span>{{ $t('system:loginLog:message:detail') }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column
label="创建时间"
prop="CreateTime"
min-width="90"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column :label="$t('system:loginLog:table:CreateTime')" prop="CreateTime" min-width="180"
sortable="custom" show-overflow-tooltip />
</el-table>
<div class="pagination" style="text-align: right;margin-top:5px;">
<pagination
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<div class="pagination" style="text-align: right; margin-top: 5px">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</div>
</div>
<detail :config="config" :JsonObj="JsonObj" />
</div>
</template>
<script>
import { getUserLogList } from '@/api/user'
import { getUserLogList, setIsIgnoreUncommonly } from '@/api/user'
import Pagination from '@/components/Pagination'
import detail from './detail.vue'
import moment from 'moment'
const searchDataDefault = () => {
return {
OptType: null,
OptTypeList: [],
Ip: '',
LoginFaildName: '',
IsLoginUncommonly: null,
LoginUserName: '',
LoginUserTypeEnum: null,
BeginDate: '',
EndDate: '',
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 20
PageSize: 20,
}
}
export default {
components: { Pagination },
components: { Pagination, detail },
data() {
return {
moment,
@@ -182,22 +158,61 @@ export default {
list: [],
total: 0,
loading: false,
datetimerange: []
datetimerange: [],
config: {
visible: false,
title: this.$t('system:loginLog:dialog:title'),
width: '500px',
top: '10vh',
},
JsonObj: null,
}
},
mounted() {
this.getList()
},
methods: {
//
async setIsIgnoreUncommonly(row) {
try {
let confirm = await this.$confirm(this.$t("system:loginLog:confirmMessage:setIsIgnoreUncommonly"))
if (!confirm) return false
let data = {
IsIgnoreUncommonly: true,
Id: row.Id
}
this.loading = true
let res = await setIsIgnoreUncommonly(data)
this.loading = false
if (res.IsSuccess) {
this.getList()
}
} catch (err) {
this.loading = false
console.log(err)
}
},
handleOpenDialog(row) {
if (!row.JsonObj)
return this.$message.warning(this.$t('system:loginLog:message:noJSON'))
this.config.title = this.$t('system:loginLog:dialog:title').replace(
'xxx',
this.$fd('UserOptType', row.OptType)
)
this.JsonObj = row.JsonObj
this.config.visible = true
},
getList() {
this.loading = true
getUserLogList(this.searchData).then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
getUserLogList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
handleDatetimeChange(val) {
if (val) {
@@ -210,6 +225,7 @@ export default {
},
//
handleReset() {
this.datetimerange = []
this.searchData = searchDataDefault()
this.getList()
},
@@ -223,35 +239,48 @@ export default {
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
}
}
},
},
}
</script>
<style lang="scss">
.log {
height: 100%;
box-sizing: border-box;
.log {
height: 100%;
box-sizing: border-box;
display: flex;
padding: 10px;
border-radius: 5px;
.left {
display: flex;
padding: 10px;
border-radius: 5px;
.left {
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
}
.icon-i {
color: #f56c6c;
cursor: pointer;
}
.icon-success {
color: #67C23A
}
}
</style>
+1 -1
View File
@@ -460,7 +460,7 @@ export default {
if (this.hasPermi(["role:admin"])) {
arr = [1];
}
if (this.hasPermi(["role:oa"])) {
if (this.hasPermi(["role:sa"])) {
arr = [1, 2];
}
if (this.hasPermi(["role:pm"])) {
+28 -38
View File
@@ -2,62 +2,46 @@
<div class="role">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item label="关键字">
<el-input
v-model="queryParams.SearchFilter"
placeholder="请输入关键字"
clearable
size="small"
@keyup.enter.native="getList"
/>
<el-form-item :label="$t('il8n:search:keyword')">
<el-input v-model="queryParams.SearchFilter" placeholder="" clearable size="small"
@keyup.enter.native="getList" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="queryParams.GroupId" placeholder="角色组" clearable size="small">
<el-option
v-for="item of dict.type.UserTypeGroup"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-form-item :label="$t('il8n:table:state')">
<el-select v-model="queryParams.GroupId" placeholder="" clearable size="small">
<el-option v-for="item of dict.type.UserTypeGroup" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">搜索</el-button>
<el-button v-hasPermi="['system:role:add']" type="primary" icon="el-icon-plus" size="mini" @click="handleAddRole">新增</el-button>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">{{
$t('system:dicom:search:search') }}</el-button>
<el-button v-hasPermi="['system:role:add']" type="primary" icon="el-icon-plus" size="mini"
@click="handleAddRole">{{ $t('common:button:new') }}</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" v-adaptive="{bottomOffset:30}" size="small" height="100" :data="list" class="table">
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 30 }" size="small" height="100" :data="list"
class="table">
<el-table-column type="index" width="50" />
<el-table-column label="User Type" prop="UserTypeName" min-width="220" show-overflow-tooltip />
<el-table-column label="Shortname" prop="UserTypeShortName" min-width="120" show-overflow-tooltip />
<el-table-column label="Group" prop="Note" min-width="80" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.UserTypeGroupList.map(v => {return v.GroupName}).toString() }}
{{scope.row.UserTypeGroupList.map(v => { return v.GroupName }).toString()}}
</template>
</el-table-column>
<el-table-column label="PermissionStr" prop="PermissionStr" min-width="100" show-overflow-tooltip />
<el-table-column label="User Type Enum" prop="UserTypeEnum" min-width="100" show-overflow-tooltip>
<template slot-scope="scope">
{{ $fd('UserType',scope.row.UserTypeEnum) }}
{{ $fd('UserType', scope.row.UserTypeEnum) }}
</template>
</el-table-column>
<el-table-column label="Description" prop="Description" min-width="220" show-overflow-tooltip />
<el-table-column label="Action" width="280" v-if="hasPermi(['system:role:edit','system:role:delete'])">
<!-- <el-table-column label="Description" prop="Description" min-width="220" show-overflow-tooltip /> -->
<el-table-column label="Action" width="280" v-if="hasPermi(['system:role:edit', 'system:role:delete'])">
<template slot-scope="scope">
<el-button
v-hasPermi="['system:role:edit']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleEditRole(scope.row)"
>Edit</el-button>
<el-button
v-hasPermi="['system:role:delete']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteRole(scope.row)"
>Delete</el-button>
<el-button v-hasPermi="['system:role:edit']" size="mini" type="text" icon="el-icon-edit"
@click="handleEditRole(scope.row)">{{ $t('common:action:edit') }}</el-button>
<el-button v-hasPermi="['system:role:delete']" size="mini" type="text" icon="el-icon-delete"
@click="handleDeleteRole(scope.row)">{{ $t('common:button:delete') }}</el-button>
</template>
</el-table-column>
</el-table>
@@ -167,32 +151,38 @@ export default {
display: flex;
padding: 10px;
border-radius: 5px;
.left {
display: flex;
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
}
.right {
width: 0;
flex-grow: 6;
overflow-y: auto;
border-right: 1px solid #ccc;
}
.selected-row{
.selected-row {
background-color: cadetblue;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ export default {
message: this.$t("trials:adRules:message:msg7"),
type: "success",
});
let msg = this.$t("system:userlist:message:ResetPassword2");
let msg = this.$IsCanConnectInternet ? this.$t("system:userlist:message:ResetPassword3") : this.$t("system:userlist:message:ResetPassword2");
msg = msg.replace("xxx", params("userName"));
msg = msg.replace("yyy", params("email"));
this.$alert(decodeURIComponent(msg));
+352 -245
View File
@@ -2,96 +2,117 @@
<el-form ref="userForm" size="small" :model="user" :rules="userFormRules" label-width="150px" style="width: 800px">
<el-card class="Basic" shadow="never" size="small">
<div slot="header" class="clearfix">
<span>{{ $t("system:userlist:title:Information") }}</span>
<span>{{ $t('system:userlist:title:Information') }}</span>
</div>
<el-form-item v-if="user.UserCode" :label="$t('system:userlist:table:S/N')" prop="UserCode">
<el-input v-model="user.UserCode" disabled />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:UserName')" class="my_new_pwd" prop="UserName">
<el-input v-model="user.UserName" clearable />
<el-input v-model="user.UserName" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:LastName')" prop="LastName">
<el-input v-model="user.LastName" clearable />
<el-input v-model="user.LastName" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:FirstName')" prop="FirstName">
<el-input v-model="user.FirstName" clearable />
<el-input v-model="user.FirstName" />
</el-form-item>
<!-- <el-form-item
:label="$t('system:userlist:table:Gender')"
prop="Sex"
style="margin-right: 40px"
>
<el-radio-group v-model="user.Sex">
<el-radio :label="1">Male</el-radio>
<el-radio :label="0">Female</el-radio>
</el-radio-group>
</el-form-item> -->
<!--:disabled="!!user.UserCode"-->
<el-form-item :label="$t('system:userlist:table:Email')" prop="EMail">
<el-input v-model="user.EMail" clearable />
<el-input v-model="user.EMail" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Phone')" prop="Phone">
<el-input v-model="user.Phone" clearable />
<el-input v-model="user.Phone" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:HospitalGroupIdList')"
:prop="hasPermi(['role:ga']) ? 'groups' : ''" v-if="type === 0">
<div style="display: flex; align-items: center">
<el-select ref="userType" v-model="user.groups" size="small" placeholder="Please select" multiple
style="width: 100%" :disabled="user.CanEditUserType === false || type === 1" @change="handleChangeGroup">
<template v-for="group of hospitalGroupList">
<el-option :key="group.Id" :label="group.Name" :value="group.Id" />
</template>
</el-select>
</div>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:HospitalGroupIdList')"
:prop="hasPermi(['role:ga']) ? 'groups' : ''" v-else>
<div style="display: flex; align-items: center">
<el-select ref="userType" v-model="groups" size="small" placeholder="Please select" multiple
style="width: 100%" :disabled="user.CanEditUserType === false || type === 1" @change="handleChangeGroup">
<template v-for="group of hospitalGroupList">
<el-option :key="group.Id" :label="group.Name" :value="group.Id" />
</template>
</el-select>
<el-button type="primary" size="small" style="margin-left: 5px" v-if="type === 1" @click.stop="openGroupList">
{{ $t('system:userlist:button:groups') }}
</el-button>
</div>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:UserType')" prop="Roles" v-if="type === 0">
<div style="display: flex; align-items: center">
<el-select ref="userType" v-model="user.Roles" size="small" placeholder="Please select" multiple
style="width: 100%" :disabled="user.CanEditUserType === false || type === 1" @change="handleChange">
<template v-for="userType of userTypeOptions">
<el-option :key="userType.Id" :label="userType.UserType" :value="userType.Id" />
</template>
</el-select>
</div>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:UserType')" prop="userTypeId" v-else>
<div style="display: flex; align-items: center">
<el-select ref="userType" v-model="Roles" size="small" placeholder="Please select" multiple
style="width: 100%" :disabled="user.CanEditUserType === false || type === 1" @change="handleChange">
<template v-for="userType of userTypeOptions">
<el-option :key="userType.Id" :label="userType.UserType" :value="userType.Id" />
</template>
</el-select>
<el-button type="primary" size="small" style="margin-left: 5px" v-if="type === 1" @click.stop="openRoleList">
{{ $t('system:userlist:button:roles') }}
</el-button>
</div>
</el-form-item>
<el-form-item label="" v-if="!$IsCanConnectInternet">
<span>{{ $t('system:userlist:tip:defaultPassword') }}</span>
</el-form-item>
<el-form-item v-if="type == 1" :label="$t('system:userlist:table:Disable')">
<el-switch v-model="user.Status" :active-value="1" :inactive-value="0" />
</el-form-item>
<!-- <el-form-item label="IsTestUser:">
<el-switch v-model="user.IsTestUser" />
</el-form-item> -->
<el-form-item :label="$t('system:userlist:table:UserType')" prop="UserTypeId">
<el-select ref="userType" v-model="user.UserTypeId" size="small" placeholder="" style="width: 100%"
:disabled="user.CanEditUserType === false" clearable @change="userTypeChange">
<template v-for="(userType, key) of userTypeOptions">
<el-option :key="key" :label="userType.UserType" :value="userType.Id" />
</template>
</el-select>
</el-form-item>
<el-form-item label="">
<span>{{ $t('system:userlist:tip:defaultPassword') }}</span>
</el-form-item>
<!-- <el-form-item
:label="$t('trials:researchForm:form:checkCode')"
prop="checkCode"
v-if="!IsCanConnectInternet"
>
<el-input v-model="user.checkCode" type="number" />
<span style="color: red"
>请输入校验码用于用户首次登录重置密码时的校验</span
>
</el-form-item> -->
</el-card>
<el-card class="Affiliation" shadow="never" style="margin-top: 10px" size="small">
<div slot="header" class="clearfix">
<span>{{ $t("system:userlist:title:Affiliation") }}</span>
<span>{{ $t('system:userlist:title:Affiliation') }}</span>
</div>
<el-form-item prop="IsZhiZhun">
<el-radio-group v-model="user.IsZhiZhun" @change="OrgnizationTypeChanged" :disabled="IsZhiZhunDisabled">
<el-radio-group v-model="user.IsZhiZhun" @change="OrgnizationTypeChanged">
<el-radio :label="true">{{
$t("system:userlist:title:Internal")
$t('system:userlist:title:Internal')
}}</el-radio>
<el-radio :label="false">{{
$t("system:userlist:title:External")
$t('system:userlist:title:External')
}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:OrganizationName')">
<el-input v-model="user.OrganizationName" :disabled="user.IsZhiZhun === true" clearable />
<el-form-item v-show="user.IsZhiZhun === false" :label="$t('system:userlist:table:OrganizationName')">
<el-input v-model="user.OrganizationName" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Department')" prop="DepartmentName">
<el-input v-model="user.DepartmentName" clearable />
<el-input v-model="user.DepartmentName" />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Position')" prop="PositionName">
<el-input v-model="user.PositionName" clearable />
<el-input v-model="user.PositionName" />
</el-form-item>
</el-card>
<el-form-item>
<el-button type="primary" size="small" :disabled="isDisabled" style="margin: 10px 15px" @click="handleSave">{{
$t("passwordReset:button:submit") }}</el-button>
$t('common:button:save') }}</el-button>
</el-form-item>
<roleList v-if="visible" :visible.sync="visible" :userId="userId" :list="userRoleList"
:userTypeOptions="userTypeOptions" @getRoleList="getRoleList" />
<groupList v-if="group_visible" :visible.sync="group_visible" :userId="userId" :list="userGroupList"
:hospitalGroupList="hospitalGroupList" @getGroupList="getGroupList" />
</el-form>
</template>
<script>
@@ -100,250 +121,336 @@ import {
addUser,
updateUser,
getUserTypeListByUserType,
} from "@/api/admin.js";
import { getHospital } from "@/api/hospital.js";
getHospitalGroupList
} from '@/api/admin.js'
import roleList from './roleList.vue'
import groupList from './groupList.vue'
export default {
name: "UserInfo",
name: 'UserInfo',
props: {
userId: { type: String, default: "" },
},
data() {
var validatePassword = (rule, value, callback) => {
var lang = zzSessionStorage.getItem("lang")
? zzSessionStorage.getItem("lang")
: "zh";
/* eslint-disable */
var reg1 = /^[a-zA-Z0-9_]{4,16}$/; //8
console.log(!reg1.test(value));
if (!reg1.test(value)) {
callback(
lang === "zh"
? new Error(
"1)新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;"
)
: new Error(
"For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed."
)
);
} else {
callback();
}
};
return {
user: {
UserName: "",
LastName: "",
FirstName: "",
Sex: "9",
EMail: "",
Phone: "",
UserTypeId: "",
IsZhiZhun: "",
OrganizationName: "",
DepartmentName: "",
PositionName: "",
IsTestUser: false,
verifyCode: "",
checkCode: "",
},
userFormRules: {
checkCode: [
{
required: true,
message: "Please Input",
trigger: ["blur", "change"],
},
],
UserName: [
{ required: true, validator: validatePassword, trigger: "blur" },
],
UserTypeId: [
{
required: true,
message: "Please Select",
trigger: ["blur", "change"],
},
],
IsZhiZhun: [
{
required: true,
message: "Please Select",
trigger: ["blur", "change"],
},
],
OrganizationName: [
{ required: true, message: "Please specify", trigger: "blur" },
],
LastName: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 50, message: "The maximum length is 50" },
],
FirstName: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 50, message: "The maximum length is 50" },
],
Phone: [
{
max: 20,
min: 7,
message: "The length is 7 to 20",
trigger: ["blur"],
},
],
EMail: [
{
required: true,
message: "Please input the email address",
trigger: "blur",
},
{
type: "email",
message: "Please input the correct email address",
trigger: ["blur"],
},
{ max: 50, message: "The maximum length is 50" },
],
Sex: [{ required: true, message: "Please specify", trigger: "blur" }],
Status: [
{ required: true, message: "Please specify", trigger: "blur" },
],
DepartmentName: [{ max: 50, message: "The maximum length is 50" }],
PositionName: [{ max: 50, message: "The maximum length is 50" }],
},
userTypeOptions: [],
isDisabled: false,
type: 0, // 10
IsCanConnectInternet: true, //
hospitalName: null, //
IsZhiZhunDisabled: false,
};
userId: { type: String, default: '' },
},
components: { roleList, groupList },
created() {
if (this.userId !== "") {
this.type = 1;
this.getUserTypeList()
if (this.userId !== '') {
this.getUserInfo()
this.type = 1
} else {
this.type = 0;
this.type = 0
}
this.getUserTypeList();
this.getInfo();
this.getHospitalGroupList()
},
methods: {
//
userTypeChange() {
this.AffiliationChange();
},
//
AffiliationChange(isFirstInfo = false) {
if (this.user.UserTypeId) {
let name = this.getUserType(this.user.UserTypeId);
if (["PM", "PI", "SR", "OA"].includes(name)) {
if (!isFirstInfo) {
this.user.IsZhiZhun = true;
this.user.OrganizationName = this.hospitalName;
}
if (this.user.IsZhiZhun) {
// this.IsZhiZhunDisabled = true;
}
return;
}
if (!isFirstInfo) {
this.user.IsZhiZhun = false;
this.user.OrganizationName = null;
}
this.IsZhiZhunDisabled = false;
}
},
getUserType(id) {
let obj = this.userTypeOptions.find((item) => item.Id === id);
return obj.UserTypeShortName;
},
//
async getInfo() {
async getHospitalGroupList() {
try {
let res = await getHospital();
let res = await getHospitalGroupList({})
if (res.IsSuccess) {
this.IsCanConnectInternet = res.Result.IsCanConnectInternet;
this.hospitalName = res.Result.HospitalName;
this.hospitalGroupList = res.Result
}
} catch (err) {
console.log(err);
console.log(err)
}
},
getGroupList() {
this.user.HospitalGroupList = []
this.groups = []
this.user.groups = []
this.userGroupList.forEach(item => {
this.user.HospitalGroupList.push(Object.assign({}, item))
if (!item.IsDisabled) {
this.groups.push(item.HospitalGroupId)
this.user.groups.push(item.HospitalGroupId)
}
})
},
openGroupList() {
this.userGroupList = []
this.user.HospitalGroupList.forEach((item) => {
this.userGroupList.push(Object.assign({}, item))
})
this.group_visible = true
},
handleChangeGroup(val) {
this.user.HospitalGroupList = []
val.forEach((item) => {
let data = this.hospitalGroupList.find((d) => d.Id === item)
this.user.HospitalGroupList.push({
HospitalGroupId: data.Id,
Name: data.Name,
IsDisabled: false,
})
})
},
openRoleList() {
this.userRoleList = []
this.user.UserRoleList.forEach((item) => {
this.userRoleList.push(Object.assign({}, item))
})
this.visible = true
},
handleChange(val) {
this.user.UserRoleList = []
val.forEach((item) => {
let data = this.userTypeOptions.find((d) => d.Id === item)
this.user.UserRoleList.push({
UserTypeEnum: data.UserTypeEnum,
UserTypeId: data.Id,
IsUserRoleDisabled: false,
})
})
},
updateQueryParam(param, newValue, wurl) {
// URL
let url = wurl || window.location.href
//
let regex = new RegExp('([?&])' + param + '=.*?(&|$)')
let separator = url.indexOf('?') !== -1 ? '&' : '?'
//
if (regex.test(url)) {
return url.replace(regex, '$1' + param + '=' + newValue + '$2')
} else {
return url + separator + param + '=' + newValue
}
},
handleSave() {
this.$refs.userForm.validate((valid) => {
if (valid) {
this.isDisabled = true;
this.isDisabled = true
const selectedUserType = this.userTypeOptions.filter(
(item) => item.Id === this.user.UserTypeId
);
)
// let newUrl = this.updateQueryParam('userName', this.user.UserName)
// newUrl = this.updateQueryParam('email', this.user.EMail, newUrl)
// window.history.pushState({ path: newUrl }, '', newUrl)
if (selectedUserType.length > 0) {
this.user.UserTypeEnum = selectedUserType[0].UserTypeEnum;
this.user.UserTypeEnum = selectedUserType[0].UserTypeEnum
}
this.user.BaseUrl = `${location.protocol}//${location.host}/login`;
this.user.RouteUrl = `${location.protocol}//${location.host}/email-recompose`;
this.user.BaseUrl = `${location.protocol}//${location.host}/login`
this.user.RouteUrl = `${location.protocol}//${location.host}/email-recompose`
if (this.user.Id) {
if (this.user.IsZhiZhun) {
this.user.OrganizationName = this.hospitalName;
}
updateUser(this.user)
.then((res) => {
this.isDisabled = false;
this.$message.success(this.$t('common:message:savedSuccessfully'));
this.isDisabled = false
this.$message.success('Updated successfully')
})
.catch(() => {
this.isDisabled = false;
});
this.isDisabled = false
})
} else {
addUser(this.user)
.then((res) => {
this.isDisabled = false;
this.user.Id = res.Result.Id;
this.user.UserCode = res.Result.UserCode;
this.$emit("getUserId", res.Result.Id);
this.$message.success("Added successfully");
this.$router.push({ path: "/system/user/list" });
this.isDisabled = false
this.user.Id = res.Result.Id
this.user.UserCode = res.Result.UserCode
this.$emit('getUserId', res.Result.Id)
this.$message.success('Added successfully')
this.$router.push({ path: '/system/user/list' })
})
.catch(() => {
this.isDisabled = false;
});
this.isDisabled = false
})
}
}
});
})
},
getUserTypeList() {
getUserTypeListByUserType(0).then((res) => {
let arr = [2, 4, 5, 8, 9, 12, 14, 35];
if (this.hasPermi(["role:sa"])) {
arr = [4, 5, 8, 9, 12, 14, 35];
}
if (this.hasPermi(["role:ga"])) {
arr = [4, 5, 8, 9, 12, 35];
}
if (res.IsSuccess) {
let arr = [2, 4, 5, 8, 9, 12, 14];
if (this.hasPermi(["role:oa"])) {
arr = [4, 5, 8, 9, 12, 14];
}
this.userTypeOptions = []
this.userTypeOptions = res.Result.map((item) => {
if (arr.includes(item.UserTypeEnum)) {
return item;
}
}).filter((item) => item);
if (this.type === 1) {
this.getUserInfo();
}
}
});
})
},
getUserInfo() {
getUser(this.userId).then((res) => {
this.user = res.Result;
this.user.Status = parseFloat(this.user.Status);
this.AffiliationChange(true);
});
getUser({
IdentityUserId: this.userId,
}).then((res) => {
this.user = res.Result
this.Roles = []
this.user.Roles = []
this.user.UserRoleList = []
this.groups = []
this.user.groups = []
res.Result.AccountList.forEach((item) => {
if (!item.IsUserRoleDisabled) {
this.Roles.push(item.UserTypeId)
this.user.Roles.push(item.UserTypeId)
}
this.user.UserRoleList.push({
UserTypeEnum: item.UserTypeEnum,
UserTypeId: item.UserTypeId,
IsUserRoleDisabled: item.IsUserRoleDisabled,
UserTypeShortName: item.UserTypeShortName,
})
})
res.Result.HospitalGroupList.forEach(item => {
if (!item.IsDisabled) {
this.groups.push(item.HospitalGroupId)
this.user.groups.push(item.HospitalGroupId)
}
})
})
},
getRoleList() {
getUser({
IdentityUserId: this.userId,
}).then((res) => {
this.Roles = []
this.user.Roles = []
this.user.UserRoleList = []
res.Result.AccountList.forEach((item) => {
if (!item.IsUserRoleDisabled) {
this.Roles.push(item.UserTypeId)
this.user.Roles.push(item.UserTypeId)
}
this.user.UserRoleList.push({
UserTypeEnum: item.UserTypeEnum,
UserTypeId: item.UserTypeId,
IsUserRoleDisabled: item.IsUserRoleDisabled,
UserTypeShortName: item.UserTypeShortName,
})
})
})
},
OrgnizationTypeChanged(val) {
if (val) {
this.user.OrganizationName = this.hospitalName;
} else {
this.user.OrganizationName = "";
}
this.user.OrganizationName = ''
},
},
};
data() {
var validatePassword = (rule, value, callback) => {
var lang = zzSessionStorage.getItem('lang')
? zzSessionStorage.getItem('lang')
: 'zh'
/* eslint-disable */
var reg1 = /^[a-zA-Z0-9_]{4,16}$/ //8
if (!reg1.test(value)) {
callback(
lang === 'zh'
? new Error(
'1)新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
)
: new Error(
'For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
)
)
} else {
callback()
}
}
return {
userRoleList: [],
userGroupList: [],
Roles: [],
groups: [],
user: {
Roles: [],
UserRoleList: [],
UserName: '',
LastName: '',
FirstName: '',
Sex: '',
EMail: '',
Phone: '',
UserTypeId: '',
IsZhiZhun: '',
OrganizationName: '',
DepartmentName: '',
PositionName: '',
HospitalGroupList: [],
groups: [],
IsTestUser: false,
},
visible: false,
group_visible: false,
userFormRules: {
UserName: [
{ required: true, validator: validatePassword, trigger: 'blur' },
],
Roles: [
{
required: true,
type: 'array',
message: 'Please Select',
trigger: ['blur', 'change'],
},
],
groups: [
{
required: true,
type: 'array',
message: 'Please Select',
trigger: ['blur', 'change'],
},
],
IsZhiZhun: [
{
required: true,
message: 'Please Select',
trigger: ['blur', 'change'],
},
],
OrganizationName: [
{ required: true, message: 'Please specify', trigger: 'blur' },
],
LastName: [
{ required: true, message: 'Please specify', trigger: 'blur' },
{ max: 50, message: 'The maximum length is 50' },
],
FirstName: [
{ required: true, message: 'Please specify', trigger: 'blur' },
{ max: 50, message: 'The maximum length is 50' },
],
Phone: [
{
max: 20,
min: 7,
message: 'The length is 7 to 20',
trigger: ['blur'],
},
],
EMail: [
{
required: true,
message: 'Please input the email address',
trigger: 'blur',
},
{
// type: 'email',
pattern: new RegExp(this.$reg().EmailRegexStr),
message: 'Please input the correct email address',
trigger: ['blur'],
},
{ max: 50, message: 'The maximum length is 50' },
],
Sex: [{ required: true, message: 'Please specify', trigger: 'blur' }],
Status: [
{ required: true, message: 'Please specify', trigger: 'blur' },
],
DepartmentName: [{ max: 50, message: 'The maximum length is 50' }],
PositionName: [{ max: 50, message: 'The maximum length is 50' }],
},
userTypeOptions: [],
hospitalGroupList: [],
isDisabled: false,
type: 0, // 10
}
},
}
</script>
<style scoped>
::v-deep .is-error.my_new_pwd {
@@ -0,0 +1,162 @@
<template>
<el-dialog v-if="visible" :visible.sync="visible" v-dialogDrag width="540px" :close-on-click-modal="false"
:close-on-press-escape="false" append-to-body :title="$t('system:userlist:button:groups')"
:before-close="cancel">
<el-button size="mini" type="primary" @click.stop="openAdd" style="float: right">
{{ $t('common:button:new') }}
</el-button>
<el-table :data="list" style="width: 100%" max-height="300px" v-loading="loading">
<el-table-column type="index" width="40" />
<el-table-column prop="Name" :label="$t('system:userlist:roleList:table:groupName')" />
<el-table-column prop="IsDisabled" :label="$t('system:userlist:roleList:table:groupIsDisabled')">
<template slot-scope="scope">
<span> {{ $fd('IsEnable', !scope.row.IsDisabled) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" min-width="120px">
<template slot-scope="scope">
<el-button size="mini" type="text" :disabled="scope.row.IsDisabled"
@click.stop="scope.row.IsDisabled = true">
{{ $fd('IsEnable', false) }}
</el-button>
<el-button size="mini" type="text" :disabled="!scope.row.IsDisabled"
@click.stop="scope.row.IsDisabled = false">
{{ $fd('IsEnable', true) }}
</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer">
<!-- 保存 -->
<el-button type="primary" :loading="loading" size="small" @click="save">
{{ $t('common:button:confirm') }}
</el-button>
<!-- 取消 -->
<el-button size="small" @click="cancel">
{{ $t('common:button:cancel') }}
</el-button>
</div>
<el-dialog v-if="addVisible" :visible.sync="addVisible" v-dialogDrag :close-on-click-modal="false"
:close-on-press-escape="false" append-to-body width="540px"
:title="$t('system:userlist:groupList:addTitle')">
<el-form ref="addForm" :model="form" :rules="rule" label-width="80px">
<el-form-item :label="$t('system:userlist:table:groupName')">
<el-select v-model="form.groups" size="small" placeholder="" multiple style="width: 100%">
<template v-for="item of groupList">
<el-option :key="item.Id" :label="item.Name" :value="item.Id" />
</template>
</el-select>
</el-form-item>
</el-form>
<div slot="footer">
<!-- 保存 -->
<el-button type="primary" size="small" @click="saveAdd">
{{ $t('common:button:confirm') }}
</el-button>
<!-- 取消 -->
<el-button size="small" @click="addVisible = false">
{{ $t('common:button:cancel') }}
</el-button>
</div>
</el-dialog>
</el-dialog>
</template>
<script>
import { updateUserHospitalGroupInfo } from '@/api/admin.js'
export default {
name: 'groupList',
props: {
userId: { type: String, default: '' },
visible: {
type: Boolean,
default: false,
},
list: {
type: Array,
default: () => {
return []
},
},
hospitalGroupList: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {
addVisible: false,
loading: false,
form: {
groups: [],
},
rule: {
groups: [
{
required: true,
message: 'Please Select',
trigger: ['blur', 'change'],
},
],
},
}
},
computed: {
groupList() {
let arr = this.list.map((item) => item.HospitalGroupId)
return this.hospitalGroupList.filter(
(item) =>
!arr.includes(item.Id)
)
},
},
methods: {
cancel() {
this.$emit('update:visible', false)
},
openAdd() {
this.form.groups = []
this.addVisible = true
},
async save() {
try {
let data = {
Id: this.userId,
HospitalGroupList: this.list,
}
this.loading = true
let res = await updateUserHospitalGroupInfo(data)
this.loading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:updatedSuccessfully'))
this.$emit('update:visible', false)
this.$emit('getGroupList')
}
} catch (err) {
this.loading = false
console.log(err)
}
},
async saveAdd() {
try {
let validate = await this.$refs.addForm.validate()
if (!validate) return
let arr = this.hospitalGroupList.filter((item) =>
this.form.groups.includes(item.Id)
)
arr.forEach((item) => {
this.list.push({
HospitalGroupId: item.Id,
IsDisabled: false,
Name: item.Name,
})
})
this.addVisible = false
} catch (err) {
console.log(err)
}
},
},
}
</script>
@@ -0,0 +1,166 @@
<template>
<el-dialog v-if="visible" :visible.sync="visible" v-dialogDrag width="540px" :close-on-click-modal="false"
:close-on-press-escape="false" append-to-body :title="$t('system:userlist:roleList:title')" :before-close="cancel">
<el-button size="mini" type="primary" @click.stop="openAdd" style="float: right">
{{ $t('common:button:new') }}
</el-button>
<el-table :data="list" style="width: 100%" max-height="300px" v-loading="loading">
<el-table-column type="index" width="40" />
<el-table-column prop="UserTypeShortName" :label="$t('system:userlist:roleList:table:UserTypeShortName')" />
<el-table-column prop="IsUserRoleDisabled" :label="$t('system:userlist:roleList:table:IsUserRoleDisabled')">
<template slot-scope="scope">
<span> {{ $fd('IsEnable', !scope.row.IsUserRoleDisabled) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" min-width="120px">
<template slot-scope="scope" v-if="checkRole(scope.row.UserTypeEnum)">
<el-button size="mini" type="text" :disabled="scope.row.IsUserRoleDisabled"
@click.stop="scope.row.IsUserRoleDisabled = true">
{{ $fd('IsEnable', false) }}
</el-button>
<el-button size="mini" type="text" :disabled="!scope.row.IsUserRoleDisabled"
@click.stop="scope.row.IsUserRoleDisabled = false">
{{ $fd('IsEnable', true) }}
</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer">
<!-- 保存 -->
<el-button type="primary" :loading="loading" size="small" @click="save">
{{ $t('common:button:confirm') }}
</el-button>
<!-- 取消 -->
<el-button size="small" @click="cancel">
{{ $t('common:button:cancel') }}
</el-button>
</div>
<el-dialog v-if="addVisible" :visible.sync="addVisible" v-dialogDrag :close-on-click-modal="false"
:close-on-press-escape="false" append-to-body width="540px" :title="$t('system:userlist:roleList:addTitle')">
<el-form ref="addForm" :model="form" :rules="rule" label-width="80px">
<el-form-item :label="$t('system:userlist:table:UserType')">
<el-select v-model="form.roles" size="small" placeholder="" multiple style="width: 100%">
<template v-for="item of roleList">
<el-option :key="item.Id" :label="item.UserType" :value="item.Id" />
</template>
</el-select>
</el-form-item>
</el-form>
<div slot="footer">
<!-- 保存 -->
<el-button type="primary" size="small" @click="saveAdd">
{{ $t('common:button:confirm') }}
</el-button>
<!-- 取消 -->
<el-button size="small" @click="addVisible = false">
{{ $t('common:button:cancel') }}
</el-button>
</div>
</el-dialog>
</el-dialog>
</template>
<script>
import { updateUserRoleInfo } from '@/api/admin.js'
export default {
name: 'roleList',
props: {
userId: { type: String, default: '' },
visible: {
type: Boolean,
default: false,
},
list: {
type: Array,
default: () => {
return []
},
},
userTypeOptions: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {
addVisible: false,
loading: false,
form: {
roles: [],
},
rule: {
roles: [
{
required: true,
message: 'Please Select',
trigger: ['blur', 'change'],
},
],
},
}
},
computed: {
roleList() {
let arr = this.list.map((item) => item.UserTypeId)
return this.userTypeOptions.filter(
(item) =>
!arr.includes(item.Id)
)
},
},
methods: {
checkRole(UserTypeEnum) {
if (this.hasPermi(['role:ga']) && [14, 2].includes(UserTypeEnum)) return false
if (this.hasPermi(['role:sa']) && [2].includes(UserTypeEnum)) return false
return true
},
cancel() {
this.$emit('update:visible', false)
},
openAdd() {
this.form.roles = []
this.addVisible = true
},
async save() {
try {
let data = {
Id: this.userId,
UserRoleList: this.list,
}
this.loading = true
let res = await updateUserRoleInfo(data)
this.loading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:updatedSuccessfully'))
this.$emit('update:visible', false)
this.$emit('getRoleList')
}
} catch (err) {
this.loading = false
console.log(err)
}
},
async saveAdd() {
try {
let validate = await this.$refs.addForm.validate()
if (!validate) return
let arr = this.userTypeOptions.filter((item) =>
this.form.roles.includes(item.Id)
)
arr.forEach((item) => {
this.list.push({
UserTypeEnum: item.UserTypeEnum,
UserTypeId: item.Id,
IsUserRoleDisabled: false,
UserTypeShortName: item.UserTypeShortName,
})
})
this.addVisible = false
} catch (err) {
console.log(err)
}
},
},
}
</script>
+392 -146
View File
@@ -1,74 +1,152 @@
<template>
<box-content>
<div class="search" style="position: relative">
<SearchForm
size="mini"
:that="this"
:search-data="searchData"
:search-form="searchForm"
:search-handle="searchHandle"
@search="handleSearch"
@reset="handleReset"
@new="handleAddUser"
/>
<SearchForm size="mini" :that="this" :search-data="searchData" :search-form="searchForm"
:search-handle="searchHandle" @search="handleSearch" @reset="handleReset" @new="handleAddUser"
@group="hadleAddGroup" />
</div>
<base-table
v-loading="loading"
:columns="columns"
:list="users"
:search-data="searchData"
:total="total"
@getList="getList"
@editCb="handleEditUser"
@deleteCb="handleDeleteUser"
@sortByColumn="sortByColumn"
>
<base-table v-loading="loading" :columns="columns" :list="users" :search-data="searchData" :total="total"
@getList="getList" @editCb="handleEditUser" @deleteCb="handleDeleteUser" @sortByColumn="sortByColumn">
<!-- 选择自定义slot -->
<template slot="tip-slot" slot-scope="{ scope }">
<i v-if="
diffTime(scope.row.LastLoginTime) >= 90 &&
diffTime(scope.row.LastChangePassWordTime) >= 90
" class="el-icon-warning" style="color: #f56c6c"
:title="$t('system:userlist:tip:overTimeAndoverTimePassWord')" />
<i v-else-if="diffTime(scope.row.LastLoginTime) >= 90" class="el-icon-warning" style="color: #f56c6c"
:title="$t('system:userlist:tip:overTime')" />
<i v-else-if="diffTime(scope.row.LastChangePassWordTime) >= 90" class="el-icon-warning" style="color: #f56c6c"
:title="$t('system:userlist:tip:overTimePassWord')" />
</template>
<template slot="genderSlot" slot-scope="{ scope }">
{{ scope.row.Sex ? "Male" : "Female" }}
{{ scope.row.Sex ? 'Male' : 'Female' }}
</template>
<template slot="HospitalGroupListSlot" slot-scope="{ scope }">
{{
Array.isArray(scope.row.HospitalGroupList) &&
scope.row.HospitalGroupList.length > 0
? scope.row.HospitalGroupList.map((item) => item.Name).join(', ')
: ''
}}
</template>
<template slot="UserTypeSlot" slot-scope="{ scope }">
{{
Array.isArray(scope.row.UserRoleList) &&
scope.row.UserRoleList.length > 0
? scope.row.UserRoleList.filter((item) => !item.IsUserRoleDisabled)
.map((item) => item.UserTypeShortName)
.join(', ')
: ''
}}
</template>
<template slot="roleSlot" slot-scope="{ scope }">
{{ scope.row.RoleNameList.map((role) => role.RoleName).join(",") }}
{{scope.row.RoleNameList.map((role) => role.RoleName).join(', ')}}
</template>
<template slot="isZhiZhunSlot" slot-scope="{ scope }">
{{
scope.row.IsZhiZhun
? $t("system:userlist:table:InternalOrExternal:Internal")
: $t("system:userlist:table:InternalOrExternal:External")
? $t('system:userlist:table:InternalOrExternal:Internal')
: $t('system:userlist:table:InternalOrExternal:External')
}}
</template>
<template slot="isTestUserSlot" slot-scope="{ scope }">
{{
scope.row.IsTestUser
? $t("system:userlist:table:IsTestUser:Yes")
: $t("system:userlist:table:IsTestUser:No")
? $t('system:userlist:table:IsTestUser:Yes')
: $t('system:userlist:table:IsTestUser:No')
}}
</template>
<template slot="statusSlot" slot-scope="{ scope }">
{{
scope.row.Status
? $t("system:userlist:table:Status:Enable")
: $t("system:userlist:table:Status:Disable")
? $t('system:userlist:table:Status:Enable')
: $t('system:userlist:table:Status:Disable')
}}
</template>
</base-table>
<base-model v-if="config.visible" :config="config">
<template slot="dialog-body">
<el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('system:userlist:table:Email')">
<el-input v-model="EMail" clearable />
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Email')" v-show="false">
<el-input v-model="EMail" />
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleGroupSearch">
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleGroupReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
<el-form v-loading="groupLoading" size="small" :model="userInfo" label-width="80px" style="margin-top: 30px;"
v-show="userInfo.Id">
<el-form-item :label="$t('system:userlist:table:UserName')">
<span>{{ userInfo.UserName }}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:LastName')">
<span>{{ userInfo.LastName }}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:FirstName')">
<span>{{ userInfo.FirstName }}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Email')">
<span>{{ userInfo.EMail }}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:Phone')">
<span>{{ userInfo.Phone }}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:UserType')">
<span>{{
Array.isArray(userInfo.AccountList) ? userInfo.AccountList.map(item =>
item.UserTypeShortName).join(",") : ''
}}</span>
</el-form-item>
<el-form-item :label="$t('system:userlist:table:HospitalGroupIdList')">
<el-select v-model="userInfo.HospitalGroupIdList" size="small" placeholder="Please select" multiple
style="width: 100%">
<template v-for="group of hospitalGroupList">
<el-option :key="group.Id" :label="group.Name" :value="group.Id" />
</template>
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<!-- 取消 -->
<el-button size="small" type="primary" @click="config.visible = false">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button size="small" type="primary" @click="addGroup" :loading="groupLoading" :disabled="!userInfo.Id">
{{ $t("common:button:confirm") }}
</el-button>
</template>
</base-model>
</box-content>
</template>
<script>
import { getUserList, getUserTypeList, deleteSysUser } from "@/api/admin";
import { getUserList, getUserTypeList, deleteSysUser, getHospitalGroupList, getUserByEmail, updateUserHospitalGroupInfo } from "@/api/admin";
// import { searchForm, searchHandle, columns } from './list'
import BoxContent from "@/components/BoxContent";
import SearchForm from "@/components/BaseForm/search-form";
import BaseTable from "@/components/BaseTable";
import tableMixins from "@/mixins/table";
import moment from 'moment'
import BaseModel from '@/components/BaseModel'
//
//
const searchDataDefault = () => {
return {
UserName: null,
Phone: null,
EMail:null,
EMail: null,
OrganizationName: null,
UserState: null,
UserType: null,
@@ -84,220 +162,313 @@ const searchDataDefault = () => {
};
export default {
name: "UserList",
components: { BoxContent, SearchForm, BaseTable },
components: { BoxContent, SearchForm, BaseTable, BaseModel },
mixins: [tableMixins],
data() {
return {
searchData: searchDataDefault(),
config: {
visible: false,
title: this.$t('system:userlist:dialogTitle:addGroup'),
width: '800px',
appendToBody: true
},
EMail: '',
userInfo: {},
hospitalGroupList: [],
groupLoading: false,
columns: [
{ type: "index" },
{ type: 'tip', slot: 'tip-slot' },
{ type: 'index' },
{
prop: "UserCode",
label: this.$t("system:userlist:table:S/N"),
prop: 'UserCode',
label: this.$t('system:userlist:table:S/N'),
width: 100,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "UserName",
label: this.$t("system:userlist:table:UserName"),
prop: 'UserName',
label: this.$t('system:userlist:table:UserName'),
minWidth: 100,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "RealName",
label: this.$t("system:userlist:table:RealName"),
prop: 'FullName',
label: this.$t('system:userlist:table:RealName'),
minWidth: 120,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
// {
// prop: 'Sex',
// label: this.$t('system:userlist:table:Gender'),
// hidden: true,
// slot: 'genderSlot',
// minWidth: 100,
// sortable: 'custom',
// showOverflowTooltip: true
// },
{
prop: "Sex",
label: this.$t("system:userlist:table:Gender"),
hidden: true,
slot: "genderSlot",
minWidth: 100,
sortable: "custom",
showOverflowTooltip: true,
},
{
prop: "Phone",
label: this.$t("system:userlist:table:Phone"),
prop: 'Phone',
label: this.$t('system:userlist:table:Phone'),
minWidth: 120,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "EMail",
label: this.$t("system:userlist:table:Email"),
prop: 'EMail',
label: this.$t('system:userlist:table:Email'),
minWidth: 150,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "OrganizationName",
label: this.$t("system:userlist:table:Organization"),
prop: 'OrganizationName',
label: this.$t('system:userlist:table:Organization'),
minWidth: 130,
showOverflowTooltip: true,
},
{
prop: "UserType",
label: this.$t("system:userlist:table:UserType"),
prop: 'HospitalGroupId',
label: this.$t('system:userlist:table:HospitalGroupList'),
minWidth: 100,
sortable: "custom",
slot: 'HospitalGroupListSlot',
// sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "IsZhiZhun",
label: this.$t("system:userlist:table:InternalOrExternal"),
prop: 'UserType',
label: this.$t('system:userlist:table:UserType'),
minWidth: 100,
slot: 'UserTypeSlot',
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: 'IsZhiZhun',
label: this.$t('system:userlist:table:InternalOrExternal'),
hidden: true,
slot: "isZhiZhunSlot",
slot: 'isZhiZhunSlot',
minWidth: 140,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
// {
// prop: 'IsTestUser',
// label: this.$t('system:userlist:table:IsTestUser'),
// hidden: true,
// slot: 'isTestUserSlot',
// minWidth: 120,
// sortable: 'custom',
// showOverflowTooltip: true,
// },
{
prop: "Status",
label: this.$t("system:userlist:table:Status"),
prop: 'Status',
label: this.$t('system:userlist:table:Status'),
hidden: true,
slot: "statusSlot",
slot: 'statusSlot',
minWidth: 100,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: "CreateTime",
label: this.$t("system:userlist:table:createTime"),
prop: 'LastLoginTime',
label: this.$t('system:userlist:table:LastLoginTime'),
minWidth: 200,
sortable: "custom",
sortable: 'custom',
showOverflowTooltip: true,
},
{
type: "operate",
label: this.$t("common:action:action"),
prop: 'LastChangePassWordTime',
label: this.$t('system:userlist:table:LastChangePassWordTime'),
minWidth: 250,
sortable: 'custom',
showOverflowTooltip: true,
},
{
prop: 'CreateTime',
label: this.$t('system:userlist:table:createTime'),
minWidth: 200,
sortable: 'custom',
showOverflowTooltip: true,
},
{
type: 'operate',
label: this.$t('common:action:action'),
minWidth: 100,
fixed: 'right',
operates: [
{
name: this.$t("common:button:edit"),
type: "primary",
emitKey: "editCb",
name: this.$t('common:button:edit'),
type: 'text',
emitKey: 'editCb',
},
// {
// name: this.$t("common:button:delete"),
// type: "danger",
// emitKey: "deleteCb",
// name: this.$t('common:button:delete'),
// type: 'danger',
// emitKey: 'deleteCb',
// },
],
},
],
searchForm: [
{
type: "Input",
label: this.$t("system:userlist:label:UserName"),
prop: "UserName",
width: "120px",
placeholder: "",
type: 'Input',
label: this.$t('system:userlist:label:UserName'),
prop: 'UserName',
width: '120px',
placeholder: '',
},
{
type: "Input",
label: this.$t("system:userlist:label:RealName"),
prop: "RealName",
width: "120px",
placeholder: "",
type: 'Input',
label: this.$t('system:userlist:label:RealName'),
prop: 'RealName',
width: '120px',
placeholder: '',
},
{
type: "Input",
label: this.$t("system:userlist:label:Phone"),
prop: "Phone",
width: "120px",
placeholder: "",
type: 'Input',
label: this.$t('system:userlist:label:Phone'),
prop: 'Phone',
width: '120px',
placeholder: '',
},
{
type: "Input",
label: this.$t("system:userlist:label:EMail"),
prop: "EMail",
width: "120px",
placeholder: "",
type: 'Input',
label: this.$t('system:userlist:label:EMail'),
prop: 'EMail',
width: '120px',
placeholder: '',
},
{
type: "Input",
label: this.$t("system:userlist:label:Organization"),
prop: "OrganizationName",
width: "120px",
placeholder: "",
type: 'Input',
label: this.$t('system:userlist:label:Organization'),
prop: 'OrganizationName',
width: '120px',
placeholder: '',
},
{
type: "Select",
label: this.$t("system:userlist:label:InternalOrExternal"),
prop: "IsZhiZhun",
width: "150px",
type: 'Select',
label: this.$t('system:userlist:label:InternalOrExternal'),
prop: 'IsZhiZhun',
width: '100px',
options: [
{
label: this.$t(
"system:userlist:label:InternalOrExternal:Internal"
'system:userlist:label:InternalOrExternal:Internal'
),
value: true,
},
{
label: this.$t(
"system:userlist:label:InternalOrExternal:External"
'system:userlist:label:InternalOrExternal:External'
),
value: false,
},
],
props: { label: "label", value: "value" },
change: (scope) => "",
placeholder: "",
props: { label: 'label', value: 'value' },
change: (scope) => '',
placeholder: '',
},
// {
// type: 'Select',
// label: this.$t('system:userlist:label:IsTestUser'),
// prop: 'IsTestUser',
// width: '100px',
// options: [
// {
// label: this.$t('system:userlist:label:IsTestUser:Yes'),
// value: true,
// },
// {
// label: this.$t('system:userlist:label:IsTestUser:No'),
// value: false,
// },
// ],
// props: { label: 'label', value: 'value' },
// change: (scope) => '',
// placeholder: '',
// },
{
type: "Select",
label: this.$t("system:userlist:label:Status"),
prop: "UserState",
width: "150px",
type: 'Select',
label: this.$t('system:userlist:label:Status'),
prop: 'UserState',
width: '100px',
options: [
{ label: this.$t("system:userlist:label:Status:Enable"), value: 1 },
{ label: this.$t('system:userlist:label:Status:Enable'), value: 1 },
{
label: this.$t("system:userlist:label:Status:Disable"),
label: this.$t('system:userlist:label:Status:Disable'),
value: 0,
},
],
props: { label: "label", value: "value" },
change: (scope) => "",
placeholder: "",
props: { label: 'label', value: 'value' },
change: (scope) => '',
placeholder: '',
},
{
type: "Select",
label: this.$t("system:userlist:label:UserType"),
prop: "UserType",
width: "150px",
type: 'Select',
label: this.$t('system:userlist:label:HospitalGroupList'),
prop: 'HospitalGroupId',
width: '100px',
options: [], //
props: { label: "UserType", value: "Id" }, //
placeholder: "",
props: { label: 'Name', value: 'Id' }, //
placeholder: '',
},
{
type: "Daterange",
label: this.$t("system:userlist:label:CreateTime"),
prop: "CreateTimeArr",
width: "400px",
placeholder: "",
type: 'Select',
label: this.$t('system:userlist:label:UserType'),
prop: 'UserType',
width: '100px',
options: [], //
props: { label: 'UserType', value: 'Id' }, //
placeholder: '',
},
{
type: 'Daterange',
label: this.$t('system:userlist:label:LastLoginTime'),
prop: 'LastLoginTimeArr',
width: '400px',
placeholder: '',
},
{
type: 'Daterange',
label: this.$t('system:userlist:label:LastChangePassWordTime'),
prop: 'LastChangePassWordTimeArr',
width: '400px',
placeholder: '',
},
{
type: 'Daterange',
label: this.$t('system:userlist:label:CreateTime'),
prop: 'CreateTimeArr',
width: '400px',
placeholder: '',
},
],
searchHandle: [
{
label: this.$t("common:button:reset"),
type: "primary",
emitKey: "reset",
label: this.$t('common:button:search'),
type: 'primary',
emitKey: 'search',
icon: 'el-icon-search',
},
{
label: this.$t("common:button:search"),
type: "primary",
emitKey: "search",
label: this.$t('common:button:reset'),
type: 'primary',
emitKey: 'reset',
icon: 'el-icon-refresh-left',
},
{
label: this.$t("common:button:new"),
type: "primary",
emitKey: "new",
label: this.$t('common:button:new'),
type: 'primary',
emitKey: 'new',
},
{
label: this.$t('system:userlist:button:addGroup'),
type: 'primary',
emitKey: 'group',
},
],
userTypeOptions: [],
@@ -309,8 +480,83 @@ export default {
created() {
this.getList();
this.getInfo();
this.getHospitalGroupList()
},
methods: {
async addGroup() {
try {
let HospitalGroupList = []
if (Array.isArray(this.userInfo.HospitalGroupIdList) && this.userInfo.HospitalGroupIdList.length > 0) {
this.hospitalGroupList.forEach(item => {
if (this.userInfo.HospitalGroupIdList.includes(item.Id)) {
HospitalGroupList.push({
HospitalGroupId: item.Id,
IsDisabled: false
})
}
})
}
let data = {
Id: this.userInfo.Id,
HospitalGroupList: HospitalGroupList,
}
this.groupLoading = true
let res = await updateUserHospitalGroupInfo(data)
this.groupLoading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:updatedSuccessfully'))
this.config.visible = false
this.getList()
}
} catch (err) {
this.groupLoading = false
console.log(err)
}
},
async handleGroupSearch() {
try {
let params = {
EMail: this.EMail,
PageSize: 1000,
PageIndex: 1,
}
this.userInfo = {}
this.groupLoading = true
let res = await getUserByEmail(params)
this.groupLoading = false
if (res.IsSuccess) {
this.userInfo = res.Result || {}
this.userInfo.HospitalGroupIdList = []
}
} catch (err) {
this.groupLoading = false
console.log(err)
}
},
handleGroupReset() {
this.EMail = ''
this.handleGroupSearch()
},
hadleAddGroup() {
this.userInfo = {}
this.EMail = ''
this.config.visible = true
},
diffTime(time) {
return moment(new Date()).diff(time, 'days')
},
async getHospitalGroupList() {
try {
let res = await getHospitalGroupList({})
if (res.IsSuccess) {
this.hospitalGroupList = res.Result
const index = this.findItemIndex("HospitalGroupId");
this.$set(this.searchForm[index], "options", this.hospitalGroupList);
}
} catch (err) {
console.log(err)
}
},
//
getList() {
this.loading = true;
@@ -348,7 +594,7 @@ export default {
if (this.hasPermi(["role:admin"])) {
arr = [1];
}
if (this.hasPermi(["role:oa"])) {
if (this.hasPermi(["role:sa"])) {
arr = [1, 2];
}
if (this.hasPermi(["role:pm"])) {
@@ -1,36 +1,23 @@
<template>
<div>
<div class="search">
<p class="line">{{ $t("trials:inspection:message:confirmVisit") }}</p>
<p class="line" v-if="showTitle">{{ $t("trials:inspection:message:confirmVisit") }}</p>
<div class="form">
<el-form :inline="true" class="base-search-form">
<!-- 检查日期 -->
<el-form-item :label="$t('trials:uploadedDicoms:table:studyDate')">
<el-date-picker
v-model="dateValue"
type="datetimerange"
range-separator="-"
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
:default-time="['00:00:00', '23:59:59']"
>
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button
type="primary"
icon="el-icon-search"
@click="handleSearch"
>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t("common:button:search") }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t("common:button:reset") }}
</el-button>
</el-form-item>
@@ -41,11 +28,8 @@
{{ $t("trials:seletctedReviews:timeline:confirmation") }}
</el-button> -->
<!--确认提交v-if="visitStatus === 'submit'"-->
<el-button
type="primary"
:loading="btnLoading2"
@click="confirmSubmit"
>
<el-button type="primary" :loading="btnLoading2" :disabled="tableSelectData.length <= 0"
@click="confirmSubmit">
{{ $t("trials:inspection:button:confirmAndSubmit") }}
</el-button>
</div>
@@ -53,137 +37,53 @@
</div>
<!--可加入项目列表-->
<!--:header-cell-style="{ background: '#f9f9f9' }"-->
<el-table
ref="confirmVisitList"
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
highlight-current-row
@select="handleSelect"
@selection-change="handleSelectChange"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'StudyTime', order: 'ascending' }"
>
<el-table-column
type="selection"
align="center"
:selectable="
(row) => row.SubjectVisitId && Number(row.SubmitState) <= 1
"
width="45"
/>
<el-table ref="confirmVisitList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
height="100" highlight-current-row @select="handleSelect" @selection-change="handleSelectChange"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'StudyTime', order: 'ascending' }">
<el-table-column type="selection" align="center" :selectable="(row) => row.SubjectVisitId && Number(row.SubmitState) <= 1
" width="45" />
<el-table-column type="index" width="40" />
<!--患者编号-->
<el-table-column
align="center"
prop="PatientIdStr"
:label="$t('trials:uploadDicomList:table:pId')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="PatientIdStr" :label="$t('trials:uploadDicomList:table:pId')"
show-overflow-tooltip min-width="140" sortable="custom"></el-table-column>
<!--患者姓名-->
<el-table-column
align="center"
prop="PatientName"
:label="$t('trials:uploadDicomList:table:patientName')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="PatientName" :label="$t('trials:uploadDicomList:table:patientName')"
show-overflow-tooltip min-width="140" sortable="custom"></el-table-column>
<!--检查描述-->
<el-table-column
align="center"
prop="Description"
:label="$t('trials:inspection:table:studyDescription')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="Description" :label="$t('trials:inspection:table:studyDescription')"
show-overflow-tooltip min-width="140" sortable="custom"></el-table-column>
<!--检查类型-->
<el-table-column
align="center"
prop="Modalities"
:label="$t('trials:audit:table:modality')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="Modalities" :label="$t('trials:audit:table:modality')" show-overflow-tooltip
min-width="140" sortable="custom"></el-table-column>
<!--序列数-->
<el-table-column
align="center"
prop="SeriesCount"
:label="$t('trials:audit:table:seriesCount')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="SeriesCount" :label="$t('trials:audit:table:seriesCount')"
show-overflow-tooltip min-width="140" sortable="custom"></el-table-column>
<!--图像数量-->
<el-table-column
align="center"
prop="InstanceCount"
:label="$t('trials:audit:table:instanceCount')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="InstanceCount" :label="$t('trials:audit:table:instanceCount')"
show-overflow-tooltip min-width="140" sortable="custom"></el-table-column>
<!--检查日期-->
<el-table-column
align="center"
prop="StudyTime"
:label="$t('trials:audit:table:studyDate')"
show-overflow-tooltip
min-width="140"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="StudyTime" :label="$t('trials:audit:table:studyDate')" show-overflow-tooltip
min-width="140" sortable="custom"></el-table-column>
<!--访视-->
<el-table-column
align="center"
prop="StudyTime"
:label="$t('trials:auditRecord:table:visit')"
show-overflow-tooltip
min-width="140"
>
<el-table-column align="center" prop="StudyTime" :label="$t('trials:auditRecord:table:visit')"
show-overflow-tooltip min-width="140">
<template slot-scope="scope">
<!--切换访视-->
<visitSelect
:modelData.sync="scope.row.SubjectVisitId"
:disabled="Number(scope.row.SubmitState) > 1"
:loading="addLoading"
:studyData="scope.row"
:list="visitList"
@add="addVisit"
@selectChange="selectChange"
@putVisit="putVisit"
/>
<visitSelect :modelData.sync="scope.row.SubjectVisitId" :disabled="Number(scope.row.SubmitState) > 1"
:loading="addLoading" :studyData="scope.row" :list="visitList" @add="addVisit" @selectChange="selectChange"
@putVisit="putVisit" />
</template>
</el-table-column>
<!--操作-->
<el-table-column
:label="$t('common:action:action')"
min-width="100"
class-name="actionBox"
>
<el-table-column :label="$t('common:action:action')" min-width="100" class-name="actionBox">
<template slot-scope="scope">
<!-- 详情 -->
<el-button
circle
icon="el-icon-view"
:title="$t('trials:trials-list:action:panel')"
@click.stop="detail(scope.row)"
/>
<el-button circle icon="el-icon-view" :title="$t('trials:trials-list:action:panel')"
@click.stop="detail(scope.row)" />
<!-- 移除 -->
<el-button
circle
icon="el-icon-delete"
:title="$t('common:button:remove')"
@click.stop="remove(scope.row)"
:disabled="
!scope.row.SubjectVisitId || Number(scope.row.SubmitState) > 1
"
/>
<el-button circle icon="el-icon-delete" :title="$t('common:button:remove')" @click.stop="remove(scope.row)"
:disabled="!scope.row.SubjectVisitId || Number(scope.row.SubmitState) > 1
" />
</template>
</el-table-column>
</el-table>
@@ -240,6 +140,10 @@ export default {
require: true,
default: "trial",
},
showTitle: {
type: Boolean,
default: true
}
},
data() {
return {
@@ -408,6 +312,7 @@ export default {
if (res.IsSuccess) {
this.list = res.Result;
// this.total = res.Result.TotalCount;
this.getSubjectVisitSelectList()
if (flag) {
this.$nextTick(() => {
this.handleAllSelect();
@@ -580,6 +485,7 @@ export default {
display: flex;
align-items: center;
flex-wrap: wrap;
.form {
width: 100%;
display: flex;
@@ -587,11 +493,13 @@ export default {
justify-content: space-between;
}
}
.line {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
&::after {
display: block;
content: "";
@@ -600,6 +508,7 @@ export default {
border-top: 1px solid #ddd;
}
}
.detail {
margin-left: 10px;
}
@@ -21,62 +21,6 @@
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:patientName')">
<el-input v-model="searchData.PatientName" clearable style="width: 100px" :maxlength="400"></el-input>
</el-form-item>
<!-- patientSex -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:patientSex')"
>
<el-select
v-model="searchData.PatientSex"
clearable
style="width: 140px"
>
<el-option
v-for="item of $d.Sex"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item> -->
<!-- patientBirthDate -->
<!-- <el-form-item
:label="$t('trials:inspection:pullImage:search:patientBirthDate')"
>
<el-date-picker
v-model="PatientBirthDate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyyMMDD"
>
</el-date-picker>
</el-form-item> -->
<!-- studyID -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:studyID')"
>
<el-input
v-model="searchData.StudyID"
clearable
:maxlength="400"
></el-input>
</el-form-item> -->
<!-- AccessionNumber -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:AccessionNumber')"
>
<el-input
v-model="searchData.AccessionNumber"
clearable
style="width: 100px"
:maxlength="400"
></el-input>
</el-form-item> -->
<!-- modalitiesInStudy -->
<el-form-item :label="$t('trials:inspection:pullImage:search:modalitiesInStudy')">
<el-select v-model="searchData.ModalitiesInStudyList" placeholder="" clearable multiple collapse-tags
@@ -92,54 +36,6 @@
:picker-options="pickerOptions">
</el-date-picker>
</el-form-item>
<!-- studyTime -->
<!-- <el-form-item
:label="$t('trials:inspection:pullImage:search:studyTime')"
>
<el-time-picker
is-range
arrow-control
v-model="StudyTime"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围"
>
</el-time-picker>
</el-form-item> -->
<!-- bodyPartExamined -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:bodyPartExamined')"
>
<el-input
v-model="searchData.BodyPartExamined"
clearable
:maxlength="400"
></el-input>
</el-form-item> -->
<!-- studyDescription -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:studyDescription')"
>
<el-input
v-model="searchData.StudyDescription"
clearable
:maxlength="400"
></el-input>
</el-form-item> -->
<!-- studyInstanceUID -->
<!-- <el-form-item
class="my_multiple"
:label="$t('trials:inspection:pullImage:search:studyInstanceUID')"
>
<el-input
v-model="searchData.StudyInstanceUID"
clearable
:maxlength="400"
></el-input>
</el-form-item> -->
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
@@ -151,9 +47,14 @@
</el-button>
<!-- 拉取 -->
<el-button type="primary" :disabled="!multipleSelection || multipleSelection.length <= 0"
@click="pullImage()">
@click="openGroup(null, 2)">
{{ $t('trials:inspection:button:pull') }}
</el-button>
<!-- 转发 -->
<el-button type="primary" v-if="IsSupportThirdService"
:disabled="!multipleSelection || multipleSelection.length <= 0" @click="openTranspond(multipleSelection)">
{{ $t('trials:inspection:button:transpond') }}
</el-button>
</el-form-item>
</el-form>
</div>
@@ -225,18 +126,85 @@
<!--studyInstanceUID-->
<el-table-column prop="StudyInstanceUID" :label="$t('trials:inspection:pullImage:table:studyInstanceUID')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--课题组-->
<el-table-column prop="ViewHospitalGroupList"
:label="$t('trials:inspection:pullImage:table:ViewHospitalGroupList')" show-overflow-tooltip min-width="100">
<template slot-scope="scope">
<span>{{
scope.row.ViewHospitalGroupList && scope.row.ViewHospitalGroupList.length > 0 ?
scope.row.ViewHospitalGroupList.map(item => item.Name).join(', ') : ''}}</span>
</template>
</el-table-column>
<!--操作-->
<el-table-column :label="$t('common:action:action')" min-width="80">
<el-table-column :label="$t('common:action:action')" min-width="160">
<template slot-scope="scope">
<el-button circle icon="el-icon-refresh" class="refreshBtn" :title="$t('trials:inspection:button:pull')"
@click.stop="pullImage(scope.row)" />
@click.stop="openGroup(scope.row, 2)" />
<el-button circle icon="el-icon-edit-outline" :title="$t('trials:inspection:button:collect')"
v-if="scope.row.IsStudyExist" @click.stop="openGroup(scope.row, 1)" />
<!-- 转发 -->
<el-button circle icon="el-icon-position" :title="$t('trials:inspection:button:transpond')"
v-if="IsSupportThirdService" @click="openTranspond([scope.row])" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="PageIndex" :limit.sync="PageSize" @pagination="paging" />
<base-model v-if="group_model.visible" :config="group_model">
<template slot="dialog-body">
<el-form ref="groupFrom" :model="form" :rules="rules" label-width="100px" size="small">
<el-form-item :label="$t('trials:externalStaff:table:lastName')" prop="LastName" v-show="false">
<el-input clearable />
</el-form-item>
<!-- 用户类型 -->
<el-form-item :label="$t('trials:externalStaff:table:hospitalGroupIdList')" prop="HospitalGroupIdList">
<el-select v-model="form.HospitalGroupIdList" style="width: 100%" multiple clearable>
<el-option v-for="item of hospitalGroupList" :key="item.Id" :label="item.Name" :value="item.Id">
<!-- <span>{{ item.UserType }}</span> -->
</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<!-- 取消 -->
<el-button size="small" type="primary" :disabled="btnLoading" @click="handleCancelGroup">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button size="small" type="primary" :loading="btnLoading" @click="pullImage">
{{ $t("common:button:save") }}
</el-button>
</template>
</base-model>
<base-model v-if="transpond_model.visible" :config="transpond_model">
<template slot="dialog-body">
<el-form ref="transpondFrom" :model="transpondForm" :rules="transpondRules" label-width="100px" size="small">
<el-form-item :label="$t('trials:externalStaff:table:lastName')" prop="LastName" v-show="false">
<el-input clearable />
</el-form-item>
<!-- AE -->
<el-form-item :label="$t('trials:externalStaff:table:DestinationAE')" prop="HospitalGroupIdList">
<el-select v-model="transpondForm.DestinationAE" style="width: 100%" clearable placeholder="">
<el-option v-for="item of transpondAElist" :key="item.Id" :label="item.CalledAE" :value="item.CalledAE">
<!-- <span>{{ item.UserType }}</span> -->
</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<!-- 取消 -->
<el-button size="small" type="primary" :disabled="btnLoading" @click="handleCancelGroup">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button size="small" type="primary" :loading="btnLoading" @click="transpondImage">
{{ $t("trials:inspection:pullImage:button:transpond") }}
</el-button>
</template>
</base-model>
</div>
</template>
<script>
@@ -247,6 +215,8 @@ import {
cMoveVerify,
} from '@/api/inspection.js'
import { getDicomAEList } from '@/api/dicomAE.js'
import BaseModel from '@/components/BaseModel'
import { modifySCPStudyHospitalGroup } from '@/api/admin.js'
const defaultSearchData = () => {
return {
PacsDicomAEId: null,
@@ -267,7 +237,7 @@ const defaultSearchData = () => {
}
export default {
name: 'byPatient',
components: { Pagination },
components: { Pagination, BaseModel },
props: {
calledAeList: {
required: true,
@@ -300,6 +270,52 @@ export default {
PageSize: 50,
AElist: [],
multipleSelection: [],
group_model: {
visible: false,
title: this.$t('trials:inspection:dialogTitle:collect'),
width: '400px',
appendToBody: true
},
form: {
HospitalGroupIdList: [],
},
rules: {
HospitalGroupIdList: [
{
required: true,
type: "array",
message: this.$t('common:ruleMessage:specify'),
trigger: ['blur', 'change']
}
]
},
btnLoading: false,
hospitalGroupList: [],
groupStatus: 1,
IsSupportThirdService: false,
transpond_model: {
visible: false,
title: this.$t('trials:inspection:dialogTitle:transpond'),
width: '400px',
appendToBody: true
},
transpondForm: {
StudyInstanceUIDList: [],
DestinationAE: null
},
transpondRules: {
DestinationAE: [
{
required: true,
type: "array",
message: this.$t('common:ruleMessage:select'),
trigger: ['blur', 'change']
}
]
},
transpondAElist: []
}
},
computed: {
@@ -416,6 +432,16 @@ export default {
this.getAEList(false, true)
},
methods: {
openTranspond(arr) {
this.getTranspondAEList();
this.transpondForm.StudyInstanceUIDList = []
this.transpondForm.DestinationAE = null
this.transpondForm.StudyInstanceUIDList = arr.map(
(item) => item.StudyInstanceUID
)
this.transpond_model.visible = true
},
pacsDicomAEIdChange(val, f = false) {
let pacs = this.AElist.find((item) => item.Id === val)
this.ModalityList = pacs.ModalityList
@@ -447,16 +473,6 @@ export default {
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key]
})
// if (
// this.PatientBirthDate &&
// this.PatientBirthDate[0] &&
// this.PatientBirthDate[1]
// ) {
// data.PatientBirthDate =
// this.PatientBirthDate[0] + '-' + this.PatientBirthDate[1]
// } else {
// data.PatientBirthDate = null
// }
if (this.StudyDate && this.StudyDate[0] && this.StudyDate[1]) {
data.StudyDate =
this.$moment(this.StudyDate[0]).format('YYYYMMDD') +
@@ -465,14 +481,6 @@ export default {
} else {
data.StudyDate = null
}
// if (this.StudyTime && this.StudyTime[0] && this.StudyTime[1]) {
// data.StudyTime =
// this.$moment(this.StudyTime[0]).format('HHmmss') +
// '-' +
// this.$moment(this.StudyTime[1]).format('HHmmss')
// } else {
// data.StudyTime = null
// }
try {
this.loading = true
let res = await getCFindStudyList(data)
@@ -515,6 +523,7 @@ export default {
let res = await getDicomAEList(data)
this.loading = false
if (res.IsSuccess) {
this.IsSupportThirdService = res.OtherInfo.IsSupportThirdService
this.AElist = res.Result.CurrentPageData
if (this.AElist.length > 0) {
if (!f) {
@@ -536,6 +545,30 @@ export default {
console.log(err)
}
},
//
async getTranspondAEList() {
let data = {
CalledAE: null,
IP: null,
Port: null,
PacsTypeEnum: 3,
IsTestOK: null,
PageIndex: 1,
PageSize: 1000,
SortField: 'CreateTime',
Asc: false,
}
try {
this.loading = true
let res = await getDicomAEList(data)
this.loading = false
if (res.IsSuccess) {
this.transpondAElist = res.Result.CurrentPageData
}
} catch (err) {
console.log(err)
}
},
//
paging() {
this.PageList = []
@@ -577,14 +610,104 @@ export default {
}
this.paging()
},
// pacs
async pullImage(row) {
async handleSaveGroup() {
try {
let validate = await this.$refs.groupFrom.validate()
if (!validate) return false
let ScPstudyIdList = []
let row = this.currentData
if (!row) {
if (this.multipleSelection.length <= 0) return false
ScPstudyIdList = this.multipleSelection.map(item => item.SCPStudyId)
} else {
ScPstudyIdList = [this.currentData.SCPStudyId]
}
let data = {
ScPstudyIdList,
AddOrDelete: 1,
HospitalGroupIdList: this.form.HospitalGroupIdList
}
this.btnLoading = true
let res = await modifySCPStudyHospitalGroup(data)
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.handleCancelGroup()
this.getList()
}
} catch (err) {
console.log(err)
this.btnLoading = false
}
},
handleCancelGroup() {
this.form.HospitalGroupIdList = []
this.groupStatus = 1
this.group_model.visible = false
this.transpond_model.visible = false
},
openGroup(row, type = 1) {
this.currentData = row
this.groupStatus = type
if (row && Object.keys(row).length !== 0) {
this.hospitalGroupList = row.CurrentUserHospitalGroupList
} else {
this.hospitalGroupList = this.multipleSelection[0].CurrentUserHospitalGroupList
}
if (type === 1) {
this.group_model.title = this.$t('trials:inspection:dialogTitle:collect')
} else {
this.group_model.title = this.$t('trials:inspection:dialogTitle:pull')
if (this.hospitalGroupList.length === 1) {
this.form.HospitalGroupIdList = [this.hospitalGroupList[0].Id]
return this.pullImage()
}
}
this.group_model.visible = true
},
//
async transpondImage() {
try {
let validate = await this.$refs.transpondFrom.validate()
if (!validate) return false
let data = {
PacsDicomAEId: this.searchData.PacsDicomAEId,
DestinationAE: this.transpondForm.DestinationAE,
StudyInstanceUIDList: this.transpondForm.StudyInstanceUIDList
// studyIDList: [row.StudyID],
}
if (row) {
this.loading = true
this.btnLoading = true
let res = await cmoveStudyList(data)
this.loading = false
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('trials:inspection:pullImage:message:transpondSuccess')
)
this.handleCancelGroup()
}
} catch (err) {
this.loading = false
this.btnLoading = false
console.log(err)
}
},
// pacs
async pullImage() {
try {
if (this.$refs.groupFrom) {
let validate = await this.$refs.groupFrom.validate()
if (!validate) return false
}
if (this.groupStatus === 1) return this.handleSaveGroup()
let row = this.currentData
let data = {
PacsDicomAEId: this.searchData.PacsDicomAEId,
HospitalGroupIdList: this.form.HospitalGroupIdList
// studyIDList: [row.StudyID],
}
if (row && Object.keys(row).length !== 0) {
data.StudyInstanceUIDList = [row.StudyInstanceUID]
} else {
data.StudyInstanceUIDList = this.multipleSelection.map(
@@ -620,15 +743,19 @@ export default {
if (!confirm) return false
this.loading = true
this.btnLoading = true
let res = await cmoveStudyList(data)
this.loading = false
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('trials:inspection:pullImage:message:pullSuccess')
)
this.handleCancelGroup()
}
} catch (err) {
this.loading = false
this.btnLoading = false
console.log(err)
}
},
@@ -0,0 +1,142 @@
<template>
<div>
<el-descriptions :column="1" border style="width: 600px">
<!--项目类型-->
<el-descriptions-item :label="$t('trials:inspection:pullImage:title:toolDownload')">
<el-button type="text" @click="handleDownload">
{{ $t('trials:inspection:pullImage:button:toolDownload') }}
</el-button>
</el-descriptions-item>
<!--项目编号-->
<el-descriptions-item>
<span slot="label">
{{ $t('trials:inspection:pullImage:title:hirAE') }}
<i class="el-icon-warning" style="cursor: pointer;"
:title="$t('trials:inspection:pullImage:tip:hirAE')" />
</span>
<el-form ref="hirAEform" :model="hirAE" label-width="120px">
<el-form-item :label="$t('trials:inspection:pullImage:form:hirAEName')">
<span>{{ hirAE.CalledAE }}</span>
<i class="el-icon-document-copy copy"
@click="copy(`${$t('trials:inspection:pullImage:form:hirAEName')}:${hirAE.CalledAE}\n${$t('trials:inspection:pullImage:form:hirAIP')}:${hirAE.IP}\n${$t('trials:inspection:pullImage:form:hirAPort')}:${hirAE.Port}`)"></i>
</el-form-item>
<el-form-item :label="$t('trials:inspection:pullImage:form:hirAIP')">
<span>{{ hirAE.IP }}</span>
</el-form-item>
<el-form-item :label="$t('trials:inspection:pullImage:form:hirAPort')">
<span>{{ hirAE.Port }}</span>
</el-form-item>
</el-form>
</el-descriptions-item>
<el-descriptions-item>
<span slot="label">
{{ $t('trials:inspection:pullImage:title:groupAE') }}
<i class="el-icon-warning" style="cursor: pointer;"
:title="$t('trials:inspection:pullImage:tip:groupAE')" />
</span>
<el-form ref="groupAEAEform" label-width="120px">
<el-form-item v-for="item of groupAEList" :key="item.Id" :label="`${item.Name}: `">
<span>{{ item.CallingAE }}</span>
<i class="el-icon-document-copy copy" @click="copy(item.CallingAE)"></i>
</el-form-item>
</el-form>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script>
import { getDicomAEList } from '@/api/dicomAE.js'
import { getUser } from '@/api/admin'
import { getCommonDocument } from '@/api/dictionary'
import { downLoadFile } from '@/utils/stream.js'
export default {
name: "byTool",
data() {
return {
hirAE: {},
groupAEList: []
}
},
created() {
this.getHirAE()
this.getGroupAE()
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
},
methods: {
copy(str) {
this.$copyText(str).then(
res => {
this.$message.success(this.$t('trials:researchRecord:message:copySuccessfully'))
}
).catch(() => { this.$message.error(this.$t('trials:researchRecord:message:copyFailed')) })
},
async getHirAE() {
try {
let data = { PacsTypeEnum: 0, PageIndex: 1, PageSize: 20, }
let res = await getDicomAEList(data)
if (res.IsSuccess) {
this.hirAE = res.Result.CurrentPageData[0]
}
} catch (err) {
console.log(err)
}
},
async getGroupAE() {
try {
let res = await getUser()
if (res.IsSuccess) {
this.groupAEList = res.Result.HospitalGroupList
}
} catch (err) {
console.log(err)
}
},
//
async handleDownload() {
try {
this.downloading = true
let res = await getCommonDocument({ Code: 'DICOMScannerAndSender' })
if (res.IsSuccess) {
let row = res.Result
let fileName = this.isEN ? row.Name : row.NameCN;
let type = fileName
.substring(fileName.lastIndexOf('.'))
.toLocaleLowerCase()
if (!type) {
let extendName = row.Path
.substring(row.Path.lastIndexOf('.'))
.toLocaleLowerCase()
fileName += extendName
}
const a = document.createElement('a')
// xls: application/vnd.ms-excel
// xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
const href = this.OSSclientConfig.basePath + row.Path
a.download = fileName
a.href = href
a.click()
URL.revokeObjectURL(href)
// res = await downLoadFile(this.OSSclientConfig.basePath + row.Path, fileName)
}
this.downloading = false
} catch (err) {
this.downloading = false
}
},
}
}
</script>
<style lang="scss" scoped>
.copy {
margin-left: 5px;
cursor: pointer;
&:hover {
color: #409EFF;
}
}
</style>
@@ -162,7 +162,7 @@
</el-button>
<!-- 拉取 -->
<el-button type="primary" :disabled="!multipleSelection || multipleSelection.length <= 0"
@click="pullImage()">
@click="openGroup({}, 2)">
{{ $t('trials:inspection:button:pull') }}
</el-button>
</el-form-item>
@@ -236,18 +236,58 @@
<!--studyInstanceUID-->
<el-table-column prop="StudyInstanceUID" :label="$t('trials:inspection:pullImage:table:studyInstanceUID')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--课题组-->
<el-table-column prop="ViewHospitalGroupList"
:label="$t('trials:inspection:pullImage:table:ViewHospitalGroupList')" show-overflow-tooltip
min-width="100">
<template slot-scope="scope">
<span>{{
scope.row.ViewHospitalGroupList && scope.row.ViewHospitalGroupList.length > 0 ?
scope.row.ViewHospitalGroupList.map(item => item.Name).join(', ') : ''}}</span>
</template>
</el-table-column>
<!--操作-->
<el-table-column :label="$t('common:action:action')" min-width="80">
<el-table-column :label="$t('common:action:action')" min-width="120">
<template slot-scope="scope">
<el-button circle icon="el-icon-refresh" class="refreshBtn"
:title="$t('trials:inspection:button:pull')" @click.stop="pullImage(scope.row)" />
:title="$t('trials:inspection:button:pull')" @click.stop="openGroup(scope.row, 2)" />
<el-button circle icon="el-icon-edit-outline" :title="$t('trials:inspection:button:collect')"
v-if="scope.row.IsStudyExist" @click.stop="openGroup(scope.row, 1)" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="PageIndex" :limit.sync="PageSize" @pagination="paging" />
<base-model v-if="group_model.visible" :config="group_model">
<template slot="dialog-body">
<el-form ref="groupFrom" :model="form" :rules="rules" label-width="100px" size="small">
<el-form-item :label="$t('trials:externalStaff:table:lastName')" prop="LastName" v-show="false">
<el-input clearable />
</el-form-item>
<!-- 用户类型 -->
<el-form-item :label="$t('trials:externalStaff:table:hospitalGroupIdList')"
prop="HospitalGroupIdList">
<el-select v-model="form.HospitalGroupIdList" style="width: 100%" multiple clearable>
<el-option v-for="item of hospitalGroupList" :key="item.Id" :label="item.Name"
:value="item.Id">
<!-- <span>{{ item.UserType }}</span> -->
</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<!-- 取消 -->
<el-button size="small" type="primary" :disabled="btnLoading" @click="handleCancelGroup">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button size="small" type="primary" :loading="btnLoading" @click="pullImage">
{{ $t("common:button:save") }}
</el-button>
</template>
</base-model>
</div>
</template>
<script>
@@ -259,6 +299,7 @@ import {
getUserJoinedTrialPatientList
} from '@/api/inspection.js'
import { getDicomAEList } from '@/api/dicomAE.js'
import BaseModel from '@/components/BaseModel'
const defaultSearchData = () => {
return {
PacsDicomAEId: null,
@@ -280,7 +321,7 @@ const defaultSearchData = () => {
}
export default {
name: 'byTrials',
components: { Pagination },
components: { Pagination, BaseModel },
props: {
calledAeList: {
required: true,
@@ -314,7 +355,31 @@ export default {
AElist: [],
multipleSelection: [],
trialList: []
trialList: [],
group_model: {
visible: false,
title: this.$t('trials:inspection:dialogTitle:collect'),
width: '400px',
appendToBody: true
},
form: {
HospitalGroupIdList: [],
},
rules: {
HospitalGroupIdList: [
{
required: true,
type: "array",
message: this.$t('common:ruleMessage:specify'),
trigger: ['blur', 'change']
}
]
},
btnLoading: false,
hospitalGroupList: [],
groupStatus: 1, // 1 2
currentData: {}
}
},
computed: {
@@ -615,14 +680,69 @@ export default {
}
this.paging()
},
// pacs
async pullImage(row) {
async handleSaveGroup() {
try {
let validate = await this.$refs.groupFrom.validate()
if (!validate) return false
let ScPstudyIdList = []
let row = this.currentData
if (!row) {
if (this.multipleSelection.length <= 0) return false
ScPstudyIdList = this.multipleSelection.map(item => item.SCPStudyId)
} else {
ScPstudyIdList = [this.currentData.SCPStudyId]
}
let data = {
ScPstudyIdList,
AddOrDelete: 1,
HospitalGroupIdList: this.form.HospitalGroupIdList
}
this.btnLoading = true
let res = await modifySCPStudyHospitalGroup(data)
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.handleCancelGroup()
this.getList()
}
} catch (err) {
console.log(err)
this.btnLoading = false
}
},
handleCancelGroup() {
this.form.HospitalGroupIdList = []
this.groupStatus = 1
this.group_model.visible = false
},
openGroup(row, type = 1) {
this.currentData = row
this.groupStatus = type
if (row && Object.keys(row).length !== 0) {
this.hospitalGroupList = row.CurrentUserHospitalGroupList
} else {
this.hospitalGroupList = this.multipleSelection[0].CurrentUserHospitalGroupList
}
if (type === 1) {
this.group_model.title = this.$t('trials:inspection:dialogTitle:collect')
} else {
this.group_model.title = this.$t('trials:inspection:dialogTitle:pull')
}
this.group_model.visible = true
},
// pacs
async pullImage() {
let validate = await this.$refs.groupFrom.validate()
if (!validate) return false
if (this.groupStatus === 1) return this.handleSaveGroup()
try {
let row = this.currentData
let data = {
PacsDicomAEId: this.searchData.PacsDicomAEId,
HospitalGroupIdList: this.form.HospitalGroupIdList
// studyIDList: [row.StudyID],
}
if (row) {
if (row && Object.keys(row).length !== 0) {
data.StudyInstanceUIDList = [row.StudyInstanceUID]
} else {
data.StudyInstanceUIDList = this.multipleSelection.map(
@@ -658,15 +778,19 @@ export default {
if (!confirm) return false
this.loading = true
this.btnLoading = true
let res = await cmoveStudyList(data)
this.loading = false
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('trials:inspection:pullImage:message:pullSuccess')
)
this.handleCancelGroup()
}
} catch (err) {
this.loading = false
this.btnLoading = false
console.log(err)
}
},
@@ -10,15 +10,19 @@
<byTrials :calledAeList="calledAeList" :callingAeList="callingAeList"
v-if="activeName === 'byTrials'" />
</el-tab-pane>
<el-tab-pane :label="$t('trials:inspection:pullImage:title:byTool')" name="byTool">
<byTool :calledAeList="calledAeList" :callingAeList="callingAeList" v-if="activeName === 'byTool'" />
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script>
import byPatient from './byPatient.vue'
import byTrials from './byTrials.vue'
import byTool from './byTool.vue'
export default {
name: 'pullImage',
components: { byPatient, byTrials },
components: { byPatient, byTrials, byTool },
props: {
visible: {
required: true,
@@ -47,6 +51,7 @@ export default {
beforeCloseStudyDig() {
this.$setOpenWindow()
this.$emit('update:visible', false)
this.$emit('getList')
},
},
}
@@ -1,62 +1,28 @@
<template>
<el-dialog
:visible.sync="visible"
:close-on-click-modal="false"
:fullscreen="true"
custom-class="upload-dialog"
:before-close="beforeCloseStudyDig"
>
<el-dialog :visible.sync="visible" :close-on-click-modal="false" :fullscreen="true" custom-class="upload-dialog"
:before-close="beforeCloseStudyDig">
<span slot="title"> {{ $t('trials:inspection:title:pushRecord') }}</span>
<div class="search">
<el-form :inline="true" class="base-search-form">
<!-- Called AE -->
<el-form-item
class="my_multiple"
:label="$t('trials:inspection:search:CalledAE')"
>
<el-select
v-model="searchData.CalledAE"
clearable
style="width: 140px"
>
<el-option
v-for="(item, index) of calledAeList"
:key="index"
:label="item"
:value="item"
>
<el-form-item class="my_multiple" :label="$t('trials:inspection:search:CalledAE')">
<el-select v-model="searchData.CalledAE" clearable style="width: 140px">
<el-option v-for="(item, index) of calledAeList" :key="index" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<!-- Calling AE -->
<el-form-item
class="my_multiple"
:label="$t('trials:inspection:search:CallingAE')"
>
<el-select
v-model="searchData.callingAE"
clearable
style="width: 140px"
>
<el-option
v-for="(item, index) of callingAeList"
:key="index"
:label="item"
:value="item"
>
<el-form-item class="my_multiple" :label="$t('trials:inspection:search:CallingAE')">
<el-select v-model="searchData.callingAE" clearable style="width: 140px">
<el-option v-for="(item, index) of callingAeList" :key="index" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<!-- 推送日期 -->
<el-form-item :label="$t('trials:inspection:table:pushDate')">
<el-date-picker
v-model="dateValue"
type="datetimerange"
range-separator="-"
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
:default-time="['00:00:00', '23:59:59']"
>
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<el-form-item>
@@ -65,78 +31,37 @@
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
</div>
<!--检查列表-->
<el-table
ref="viewStudyList"
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'StartTime', order: 'descending' }"
>
<el-table ref="viewStudyList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'StartTime', order: 'descending' }">
<el-table-column type="index" width="40" />
<!--Called AE-->
<el-table-column
prop="CalledAE"
:label="$t('trials:inspection:table:CalledAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CalledAE" :label="$t('trials:inspection:table:CalledAE')" show-overflow-tooltip
min-width="120">
</el-table-column>
<!--Calling AE-->
<el-table-column
prop="CallingAE"
:label="$t('trials:inspection:table:CallingAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CallingAE" :label="$t('trials:inspection:table:CallingAE')" show-overflow-tooltip
min-width="120">
</el-table-column>
<!--Calling AE IP-->
<el-table-column
prop="CallingAEIP"
:label="$t('trials:inspection:table:CallingAEIP')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CallingAEIP" :label="$t('trials:inspection:table:CallingAEIP')" show-overflow-tooltip
min-width="120">
</el-table-column>
<!--检查数量--->
<el-table-column
:label="$t('trials:inspection:table:StudyCount')"
prop="StudyCount"
min-width="90"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column :label="$t('trials:inspection:table:StudyCount')" prop="StudyCount" min-width="90"
show-overflow-tooltip sortable="custom" />
<!--图像数量-->
<el-table-column
align="center"
prop="FileCount"
:label="$t('trials:inspection:table:FileCount')"
show-overflow-tooltip
min-width="100"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="FileCount" :label="$t('trials:inspection:table:FileCount')"
show-overflow-tooltip min-width="100" sortable="custom"></el-table-column>
<!--图像大小-->
<el-table-column
align="center"
prop="FileSize"
:label="$t('trials:inspection:table:FileSize')"
show-overflow-tooltip
min-width="100"
sortable="custom"
>
<el-table-column align="center" prop="FileSize" :label="$t('trials:inspection:table:FileSize')"
show-overflow-tooltip min-width="100" sortable="custom">
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
@@ -146,51 +71,57 @@
</template>
</el-table-column>
<!--推送开始日期-->
<el-table-column
align="center"
prop="StartTime"
:label="$t('trials:inspection:table:StartTime')"
show-overflow-tooltip
min-width="180"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="StartTime" :label="$t('trials:inspection:table:StartTime')"
show-overflow-tooltip min-width="180" sortable="custom"></el-table-column>
<!--推送结束日期-->
<el-table-column
align="center"
prop="EndTime"
:label="$t('trials:inspection:table:EndTime')"
show-overflow-tooltip
min-width="180"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="EndTime" :label="$t('trials:inspection:table:EndTime')"
show-overflow-tooltip min-width="180" sortable="custom"></el-table-column>
<!--操作-->
<!-- <el-table-column :label="$t('common:action:action')" min-width="80">
<el-table-column :label="$t('common:action:action')" min-width="80">
<template slot-scope="scope">
<el-button
circle
disabled
icon="el-icon-view"
:title="$t('trials:inspection:button:image')"
@click.stop="image(scope.row)"
/>
<!-- <el-button circle disabled icon="el-icon-view" :title="$t('trials:inspection:button:image')"
@click.stop="image(scope.row)" /> -->
<el-button circle icon="el-icon-info" :title="$t('trials:inspection:button:detail')"
:disabled="!scope.row.UploadJsonStr" @click.stop="view(scope.row)" />
</template>
</el-table-column> -->
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<base-model v-if="detail_model.visible" :config="detail_model">
<template slot="dialog-body">
<el-table :data="detailData" style="width: 100%">
<el-table-column prop="PatientNameList" :label="$t('trials:inspection:table:PatientNameList')"
show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ Array.isArray(scope.row.PatientNameList) ? scope.row.PatientNameList.join(", ") : '' }}</span>
</template>
</el-table-column>
<el-table-column prop="StudyInstanceUid" :label="$t('trials:inspection:table:StudyInstanceUid')"
show-overflow-tooltip>
</el-table-column>
<el-table-column prop="SuccessImageCount" :label="$t('trials:inspection:table:SuccessImageCount')">
</el-table-column>
<el-table-column prop="FailedImageCount" :label="$t('trials:inspection:table:FailedImageCount')">
</el-table-column>
</el-table>
</template>
<template slot="dialog-footer">
<!-- 保存 -->
<el-button size="small" type="primary" @click="detail_model.visible = false">
{{ $t("common:button:confirm") }}
</el-button>
</template>
</base-model>
</el-dialog>
</template>
<script>
import Pagination from '@/components/Pagination'
import { getSCPImageUploadList } from '@/api/inspection.js'
import { getToken } from '@/utils/auth'
import BaseModel from '@/components/BaseModel'
const defaultSearchData = () => {
return {
CallingAE: null,
@@ -206,7 +137,7 @@ const defaultSearchData = () => {
}
export default {
name: 'pushRecordList',
components: { Pagination },
components: { Pagination, BaseModel },
props: {
visible: {
required: true,
@@ -234,12 +165,23 @@ export default {
loading: false,
list: [],
total: 0,
detail_model: {
visible: false,
title: this.$t('trials:inspection:dialogTitle:detail'),
width: '800px',
appendToBody: true
},
detailData: []
}
},
created() {
this.getList()
},
methods: {
view(row) {
this.detailData = JSON.parse(row.UploadJsonStr).UploadList
this.detail_model.visible = true
},
async getList() {
let data = {}
Object.keys(this.searchData).forEach((key) => {
@@ -1,44 +1,53 @@
<template>
<el-dialog
:visible.sync="visible"
:close-on-click-modal="false"
:fullscreen="true"
custom-class="upload-dialog"
:before-close="beforeCloseStudyDig"
>
<span slot="title"
>{{ $t('trials:inspection:message:viewStudy') }}{{
$t('trials:uploadDicomList:table:patientInfo')
}}{{ Patient.PatientIdStr }}{{ Patient.PatientName }}</span
>
<el-dialog :visible.sync="visible" :close-on-click-modal="false" :fullscreen="true" custom-class="upload-dialog"
:before-close="beforeCloseStudyDig">
<span slot="title" v-if="!isAll">{{ $t('trials:inspection:message:viewStudy') }}{{
$t('trials:uploadDicomList:table:patientInfo')
}}{{ Patient.PatientIdStr }}{{ Patient.PatientName }}</span>
<div class="search">
<el-form :inline="true" class="base-search-form">
<template v-if="isAll">
<!-- 患者ID/患者姓名 -->
<el-form-item :label="$t('trials:uploadDicomList:table:pId')">
<el-input v-model="searchData.PatientIdStr" style="width: 100px" clearable />
</el-form-item>
<el-form-item :label="$t('trials:uploadDicomList:table:patientName')">
<el-input v-model="searchData.PatientName" style="width: 100px" clearable />
</el-form-item>
<!-- Called AE -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:search:CalledAE')">
<el-select v-model="searchData.CalledAEList" clearable multiple style="width: 140px">
<el-option v-for="(item, index) of calledAeList" :key="index" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<!-- Calling AE -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:search:CallingAE')">
<el-select v-model="searchData.callingAE" clearable style="width: 140px">
<el-option v-for="(item, index) of callingAeList" :key="index" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<!-- 课题组 -->
<el-form-item :label="$t('trials:trials-myinfo:form:StudyHospitalGroupList')">
<el-select v-model="searchData.HospitalGroupIdList" clearable multiple style="width: 140px">
<el-option v-for="(item) of hospitalGroupList" :key="item.Id" :label="item.Name" :value="item.Id">
</el-option>
</el-select>
</el-form-item>
</template>
<!-- 检查类型 -->
<el-form-item :label="$t('trials:audit:table:modality')">
<el-select
v-model="searchData.Modalities"
clearable
style="width: 140px"
>
<el-option
v-for="item of $d.modalType"
:key="item.id"
:label="item.label"
:value="item.label"
>
<el-select v-model="searchData.Modalities" clearable style="width: 140px">
<el-option v-for="item of $d.modalType" :key="item.id" :label="item.label" :value="item.label">
</el-option>
</el-select>
</el-form-item>
<!-- 检查日期 -->
<el-form-item :label="$t('trials:uploadedDicoms:table:studyDate')">
<el-date-picker
v-model="dateValue"
type="datetimerange"
range-separator="-"
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
:default-time="['00:00:00', '23:59:59']"
>
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<el-form-item>
@@ -47,145 +56,152 @@
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<!-- 选择课题组 -->
<el-button type="primary" v-hasPermi="['trials:trialsInspection:addGroup']" v-if="!isAll"
:disabled="multipleSelection.length <= 0" @click="openGroup({})">
{{ $t('trials:inspection:button:checkGroupId') }}
</el-button>
<!-- 下载影像 -->
<el-button type="primary" v-hasPermi="['trials:trialsInspection:downloadImage']" v-if="!isAll"
:disabled="multipleSelection.length <= 0" @click="getDownloadPatientStudyInfo(multipleSelection)">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item>
</el-form>
</div>
<!--检查列表-->
<el-table
ref="viewStudyList"
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'StudyTime', order: 'descending' }"
>
<el-table-column type="index" width="40" />
<el-table ref="viewStudyList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'StudyTime', order: 'descending' }"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" v-if="hasPermi(['trials:trialsInspection:editGroup']) && !isAll" />
<el-table-column type="index" width="40" v-else />
<template v-if="isAll">
<!--患者ID-->
<el-table-column prop="PatientIdStr" :label="$t('trials:uploadDicomList:table:pId')" show-overflow-tooltip
min-width="120" sortable="custom"></el-table-column>
<!--患者姓名-->
<el-table-column prop="PatientName" :label="$t('trials:uploadDicomList:table:patientName')"
show-overflow-tooltip min-width="120" sortable="custom"></el-table-column>
<!--出生日期-->
<el-table-column prop="PatientBirthDate" :label="$t('trials:inspection:table:birthdate')" show-overflow-tooltip
min-width="120" sortable="custom"></el-table-column>
<!--性别-->
<el-table-column prop="PatientSex" :label="$t('trials:trials-myinfo:form:gender')" show-overflow-tooltip
min-width="100" sortable="custom">
<template slot-scope="scope">
<span>{{ $fd('Sex', scope.row.PatientSex) }}</span>
</template>
</el-table-column>
</template>
<!--检查申请号-->
<el-table-column
align="center"
prop="AccessionNumber"
:label="$t('trials:inspection:table:AccessionNumber')"
show-overflow-tooltip
min-width="120"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="AccessionNumber" :label="$t('trials:inspection:table:AccessionNumber')"
show-overflow-tooltip min-width="120" sortable="custom"></el-table-column>
<!--检查描述-->
<el-table-column
align="center"
prop="Description"
:label="$t('trials:inspection:table:studyDescription')"
show-overflow-tooltip
min-width="120"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="Description" :label="$t('trials:inspection:table:studyDescription')"
show-overflow-tooltip min-width="120" sortable="custom"></el-table-column>
<!--检查类型-->
<el-table-column
align="center"
prop="Modalities"
:label="$t('trials:audit:table:modality')"
show-overflow-tooltip
min-width="120"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="Modalities" :label="$t('trials:audit:table:modality')" show-overflow-tooltip
min-width="120" sortable="custom"></el-table-column>
<!--Called AE-->
<el-table-column
prop="CalledAE"
:label="$t('trials:inspection:table:CalledAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CalledAE" :label="$t('trials:inspection:table:CalledAE')" show-overflow-tooltip
min-width="120">
</el-table-column>
<!--Calling AE-->
<el-table-column
prop="CallingAE"
:label="$t('trials:inspection:table:CallingAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CallingAE" :label="$t('trials:inspection:table:CallingAE')" show-overflow-tooltip
min-width="120">
</el-table-column>
<!--课题组-->
<el-table-column prop="HospitalGroupList" :label="$t('trials:inspection:table:ViewHospitalGroupList')"
show-overflow-tooltip min-width="100">
<template slot-scope="scope">
<span>{{
scope.row.ViewHospitalGroupList && scope.row.ViewHospitalGroupList.length > 0 ?
scope.row.ViewHospitalGroupList.map(item => item.Name).join(', ') : ''}}</span>
</template>
</el-table-column>
<!--序列数量-->
<el-table-column
align="center"
prop="SeriesCount"
:label="$t('trials:audit:table:seriesCount')"
show-overflow-tooltip
min-width="100"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="SeriesCount" :label="$t('trials:audit:table:seriesCount')"
show-overflow-tooltip min-width="100" sortable="custom"></el-table-column>
<!--图像数量-->
<el-table-column
align="center"
prop="InstanceCount"
:label="$t('trials:audit:table:instanceCount')"
show-overflow-tooltip
min-width="100"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="InstanceCount" :label="$t('trials:audit:table:instanceCount')"
show-overflow-tooltip min-width="100" sortable="custom"></el-table-column>
<!--检查日期-->
<el-table-column
align="center"
prop="StudyTime"
:label="$t('trials:audit:table:studyDate')"
show-overflow-tooltip
min-width="180"
sortable="custom"
></el-table-column>
<el-table-column align="center" prop="StudyTime" :label="$t('trials:audit:table:studyDate')" show-overflow-tooltip
min-width="180" sortable="custom"></el-table-column>
<!--uid-->
<el-table-column align="center" prop="StudyInstanceUid" :label="$t('trials:audit:table:StudyInstanceUid')"
show-overflow-tooltip min-width="180" sortable="custom"></el-table-column>
<!--操作-->
<el-table-column :label="$t('common:action:action')" min-width="150">
<el-table-column :label="$t('common:action:action')" min-width="240" fixed="right">
<template slot-scope="scope">
<!-- 影像 -->
<el-button
circle
icon="el-icon-view"
:title="$t('trials:inspection:button:image')"
@click.stop="image(scope.row)"
/>
<el-button circle icon="el-icon-view" :title="$t('trials:inspection:button:image')"
@click.stop="image(scope.row)" />
<!-- 修改课题组 -->
<el-button circle icon="el-icon-edit-outline" :title="$t('trials:inspection:button:editGroup')" v-if="!isAll"
v-hasPermi="['trials:trialsInspection:editGroup']" @click.stop="openGroup(scope.row, 3)" />
<!--删除-->
<el-button
circle
v-hasPermi="['trials:trialsInspection:delStudy']"
icon="el-icon-delete"
:title="$t('trials:inspection:button:delete')"
@click.stop="deletePatientStudy(scope.row)"
/>
<el-button circle v-hasPermi="['trials:trialsInspection:delStudy']" icon="el-icon-delete" v-if="!isAll"
:title="$t('trials:inspection:button:delete')" @click.stop="deletePatientStudy(scope.row)" />
<!-- 诊断报告 -->
<el-button
circle
icon="el-icon-document"
@click.stop="report(scope.row)"
:title="$t('trials:inspection:button:diagnosticReport')"
disabled
/>
<el-button circle icon="el-icon-document" @click.stop="report(scope.row)"
:title="$t('trials:inspection:button:diagnosticReport')" disabled />
<!-- 下载影像 -->
<el-button v-hasPermi="['trials:trialsInspection:downloadImage']" circle icon="el-icon-download"
@click="getDownloadPatientStudyInfo([scope.row])" :title="$t('trials:inspection:button:downloadImage')" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<base-model v-if="group_model.visible" :config="group_model">
<template slot="dialog-body">
<el-form ref="groupFrom" :model="form" :rules="rules" label-width="100px" size="small">
<el-form-item :label="$t('trials:externalStaff:table:lastName')" prop="LastName" v-show="false">
<el-input clearable />
</el-form-item>
<!-- 用户类型 -->
<el-form-item :label="$t('trials:externalStaff:table:hospitalGroupIdList')" prop="HospitalGroupIdList">
<el-select v-model="form.HospitalGroupIdList" style="width: 100%" multiple clearable>
<el-option v-for="item of hospitalGroupList" :key="item.Id" :label="item.Name" :value="item.Id">
<!-- <span>{{ item.UserType }}</span> -->
</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
<template slot="dialog-footer">
<!-- 取消 -->
<el-button size="small" type="primary" :disabled="btnLoading" @click="handleCancelGroup">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSaveGroup">
{{ $t("common:button:save") }}
</el-button>
</template>
</base-model>
</el-dialog>
</template>
<script>
import Pagination from '@/components/Pagination'
import { getPatientStudyList, deletePatientStudy } from '@/api/inspection.js'
import { modifySCPStudyHospitalGroup, getHospitalGroupList } from '@/api/admin.js'
import { getToken } from '@/utils/auth'
import BaseModel from '@/components/BaseModel'
const defaultSearchData = () => {
return {
PatientIdStr: null,
PatientName: null,
CalledAEList: [],
callingAE: null,
ExperimentName: null,
HospitalGroupIdList: [],
Modalities: null,
EarliestStudyTime: null,
LatestStudyTime: null,
@@ -198,7 +214,7 @@ const defaultSearchData = () => {
}
export default {
name: 'viewStudyList',
components: { Pagination },
components: { Pagination, BaseModel },
props: {
visible: {
required: true,
@@ -210,6 +226,28 @@ export default {
return {}
},
},
isAll: {
required: true,
default: false,
},
calledAeList: {
type: Array,
default: () => {
return []
},
},
callingAeList: {
type: Array,
default: () => {
return []
},
},
hospitalGroupList: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {
@@ -220,12 +258,98 @@ export default {
loading: false,
list: [],
total: 0,
multipleSelection: [],
group_model: {
visible: false,
title: this.$t('trials:inspection:dialogTitle:add'),
width: '400px',
appendToBody: true
},
form: {
HospitalGroupIdList: [],
},
rules: {
HospitalGroupIdList: [
{
required: true,
type: "array",
message: this.$t('common:ruleMessage:specify'),
trigger: ['blur', 'change']
}
]
},
btnLoading: false,
// hospitalGroupList: [],
groupStatus: 1,
currentData: {}
}
},
created() {
this.getList()
},
methods: {
getDownloadPatientStudyInfo(arr) {
this.$emit('getDownloadPatientStudyInfo', arr)
},
async getHospitalGroupList() {
try {
let res = await getHospitalGroupList({})
if (res.IsSuccess) {
this.hospitalGroupList = res.Result
}
} catch (err) {
console.log(err)
}
},
openGroup(row, status = 1) {
this.form.HospitalGroupIdList = []
this.group_model.title = this.$t('trials:inspection:dialogTitle:add')
if (row.ViewHospitalGroupList && row.ViewHospitalGroupList.length > 0) {
this.form.HospitalGroupIdList = row.ViewHospitalGroupList.map(item => item.Id)
this.group_model.title = this.$t('trials:inspection:dialogTitle:edit')
}
this.currentData = row
this.groupStatus = status
this.getHospitalGroupList()
this.group_model.visible = true
},
handleCancelGroup() {
this.form.HospitalGroupIdList = []
this.groupStatus = 1
this.group_model.visible = false
},
async handleSaveGroup() {
try {
let validate = await this.$refs.groupFrom.validate()
if (!validate) return false
let ScPstudyIdList = []
if (this.groupStatus === 1) {
if (this.multipleSelection.length <= 0) return false
ScPstudyIdList = this.multipleSelection.map(item => item.SCPStudyId)
} else {
ScPstudyIdList = [this.currentData.SCPStudyId]
}
let data = {
ScPstudyIdList,
AddOrDelete: this.groupStatus,
HospitalGroupIdList: this.form.HospitalGroupIdList
}
this.btnLoading = true
let res = await modifySCPStudyHospitalGroup(data)
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.handleCancelGroup()
this.getList()
}
} catch (err) {
console.log(err)
this.btnLoading = false
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
//
async deletePatientStudy(item) {
try {
@@ -264,7 +388,9 @@ export default {
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key]
})
data.PatientId = this.Patient.PatientId
if (!this.isAll) {
data.PatientId = this.Patient.PatientId
}
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.EarliestStudyTime = this.$moment(this.dateValue[0]).format(
'YYYY-MM-DD HH:mm:ss'
@@ -315,7 +441,7 @@ export default {
this.$setOpenWindow(newWindow)
},
//
report() {},
report() { },
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop
@@ -327,5 +453,4 @@ export default {
},
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>
+330 -27
View File
@@ -28,10 +28,19 @@
<el-form-item :label="$t('trials:trials-list:table:researchName')">
<el-input v-model="searchData.ExperimentName" style="width: 100px" clearable />
</el-form-item>
<!-- 课题组 -->
<el-form-item :label="$t('trials:trials-myinfo:form:StudyHospitalGroupList')">
<el-select v-model="searchData.HospitalGroupIdList" clearable multiple style="width: 140px">
<el-option v-for="(item) of hospitalGroupList" :key="item.Id" :label="item.Name" :value="item.Id">
</el-option>
</el-select>
</el-form-item>
<!-- 最新接收时间 -->
<el-form-item :label="$t('trials:inspection:table:latestReceiveTime')">
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-" :start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']" clearable>
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']"
clearable>
</el-date-picker>
</el-form-item>
<el-form-item>
@@ -57,14 +66,35 @@
{{ $t('common:button:pull') }}
</el-button>
</el-form-item>
<el-form-item>
<!-- 查看所有检查 -->
<el-button type="primary" @click="handleOpenDialog({}, 'study', true)">
{{ $t('common:button:viewAllStudy') }}
</el-button>
</el-form-item>
<el-form-item v-if="hasPermi(['trials:trialsInspection:downloadImage'])">
<!-- 下载影像 -->
<el-button type="primary" @click="getDownloadPatientStudyInfo(multipleSelection)"
:disabled="multipleSelection.length <= 0">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item>
<el-form-item v-if="hasPermi(['trials:trialsInspection:downloadImage'])">
<!-- 下载记录 -->
<el-button type="primary" @click="() => RecordVisible = true">
{{ $t('trials:inspection:button:downloadRecord') }}
</el-button>
</el-form-item>
</el-form>
</template>
<!-- 检查列表 -->
<template slot="main-container">
<el-table ref="inspectionList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
height="100" @sort-change="handleSortByColumn" :default-sort="{ prop: 'LatestPushTime', order: 'descending' }">
<el-table-column type="index" width="40" />
height="100" @sort-change="handleSortByColumn" @selection-change="handleSelectionChange"
:default-sort="{ prop: 'LatestPushTime', order: 'descending' }">
<el-table-column type="selection" width="55" v-if="hasPermi(['trials:trialsInspection:downloadImage'])" />
<el-table-column type="index" width="40" v-else />
<!--患者ID-->
<el-table-column prop="PatientIdStr" :label="$t('trials:uploadDicomList:table:pId')" show-overflow-tooltip
min-width="120" sortable="custom"></el-table-column>
@@ -116,6 +146,15 @@
<!-- <span v-else>{{ scope.row.VisitName }}</span> -->
</template>
</el-table-column>
<!--课题组-->
<el-table-column prop="ViewHospitalGroupList" :label="$t('trials:trials-myinfo:form:StudyHospitalGroupList')"
show-overflow-tooltip min-width="100">
<template slot-scope="scope">
<span>{{
scope.row.ViewHospitalGroupList && scope.row.ViewHospitalGroupList.length > 0 ?
scope.row.ViewHospitalGroupList.join(', ') : '' }}</span>
</template>
</el-table-column>
<!-- 检查数 -->
<el-table-column prop="StudyCount" :label="$t('trials:studyList:table:count')" show-overflow-tooltip
min-width="100" sortable="custom">
@@ -130,15 +169,15 @@
<el-table-column prop="LatestPushTime" :label="$t('trials:inspection:table:latestReceiveTime')"
show-overflow-tooltip min-width="180" sortable="custom"></el-table-column>
<!--操作-->
<el-table-column :label="$t('common:action:action')" min-width="100" fixed="right" v-if="
hasPermi([
'trials:trialsInspection:addTrials',
'trials:trialsInspection:delPatient',
])
">
<el-table-column :label="$t('common:action:action')" min-width="140" fixed="right">
<template slot-scope="scope">
<el-button circle icon="el-icon-view" :title="$t('trials:trialsInspection:button:view')"
@click.stop="handleOpenDialog(scope.row, 'study')" />
<el-button circle v-hasPermi="['trials:trialsInspection:addTrials']" icon="el-icon-plus"
:title="$t('trials:inspection:button:addTrials')" @click.stop="handleOpenDialog(scope.row, 'add')" />
<!-- 下载影像 -->
<el-button v-hasPermi="['trials:trialsInspection:downloadImage']" circle icon="el-icon-download"
@click="getDownloadPatientStudyInfo([scope.row])" :title="$t('trials:inspection:button:downloadImage')" />
<!-- <el-button
circle
icon="el-icon-delete"
@@ -163,13 +202,29 @@
@handleOpenDialog="handleOpenDialog" />
<!--查看检查列表-->
<viewStudyList v-if="studyTrialsVisible" :visible.sync="studyTrialsVisible" :Patient="selectPatient"
@getList="getList" />
:isAll="studyAll" :calledAeList="calledAeList" :callingAeList="callingAeList"
:hospitalGroupList="hospitalGroupList" @getList="getList"
@getDownloadPatientStudyInfo="getDownloadPatientStudyInfo" />
<!--推送记录列表-->
<pushRecordList v-if="pushTrialsVisible" :visible.sync="pushTrialsVisible" :calledAeList="calledAeList"
:callingAeList="callingAeList" />
<!--pacs拉取列表-->
<pullImage v-if="pullTrialsVisible" :visible.sync="pullTrialsVisible" :calledAeList="calledAeList"
:callingAeList="callingAeList" />
:callingAeList="callingAeList" @getList="getList" />
<el-dialog title="" :visible.sync="RecordVisible" :fullscreen="true">
<downloadRecord :isSystem="true" v-if="RecordVisible" />
</el-dialog>
<!-- <el-dialog :title="$t('dialog:title:downLoadProgress')" :visible.sync="downloadVisible" width="35%"
:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
<div v-if="downloadType == 'downLoad' || downloadType == 'start'">
<span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<span>{{ speed }}</span>
<el-progress :percentage="percentage * 1" v-if="downloadVisible"></el-progress>
</div>
<div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span>
</div>
</el-dialog> -->
</BaseContainer>
</template>
<script>
@@ -180,9 +235,16 @@ import addTrialsList from './components/add-trials-list'
import viewStudyList from './components/view-study-list'
import pushRecordList from './components/push-record-list'
import pullImage from './components/pullImage/index.vue'
import { getPatientList, deletePatientStudyAllData } from '@/api/inspection.js'
import { getPatientList, deletePatientStudyAllData, getDownloadPatientStudyInfo, PatientStudyBatchDownload } from '@/api/inspection.js'
import { getDicomCalledAEList, getDicomCallingAEList } from '@/api/dicomAE.js'
import downloadRecord from "@/views/trials/trials-panel/trial-summary/download-record"
import { getToken } from '@/utils/auth'
// import * as signalR from '@microsoft/signalr'
import {
downloadImageSuccess,
} from '@/api/trials.js'
import { getHospitalGroupList } from '@/api/admin.js'
import { downLoadFile } from '@/utils/stream.js'
const defaultSearchData = () => {
return {
PatientIdStr: null,
@@ -190,6 +252,7 @@ const defaultSearchData = () => {
CalledAEList: [],
callingAE: null,
ExperimentName: null,
HospitalGroupIdList: [],
Asc: false,
BeginPushTime: null,
EndPushTime: null,
@@ -208,6 +271,7 @@ export default {
viewStudyList,
pushRecordList,
pullImage,
downloadRecord
},
data() {
return {
@@ -220,6 +284,9 @@ export default {
total: 0,
loading: false,
list: [],
multipleSelection: [],
downloadId: null,
RecordVisible: false,
//
selectPatient: {},
//
@@ -232,14 +299,220 @@ export default {
pushTrialsVisible: false,
// pacs
pullTrialsVisible: false,
hospitalGroupList: [],
studyAll: false,
downloadVisible: false,
downloadType: '',
percentage: 0,
downLoadImageCount: 0,
speed: '0KB/s'
}
},
created() {
this.getDicomCalledAEList()
this.getDicomCallingAEList()
this.getList()
this.getHospitalGroupList()
},
methods: {
handleClose(done) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
this.downloadId = null
done()
},
generate() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async getDownloadPatientStudyInfo(arr) {
try {
let data = {
PatientIdList: [],
ScpStudyIdList: []
}
this.downloadId = this.generate()
data.CurrentNoticeId = this.downloadId
arr.forEach(item => {
data.PatientIdList.push(item.PatientId)
if (item.SCPStudyId) {
data.ScpStudyIdList.push(item.SCPStudyId)
}
})
let params = null
data.PatientIdList.forEach(item => {
if (!params) {
params = `PatientIdList=${item}`
} else {
params += `&PatientIdList=${item}`
}
})
data.ScpStudyIdList.forEach(item => {
if (!params) {
params = `ScpStudyIdList=${item}`
} else {
params += `&ScpStudyIdList=${item}`
}
})
if (!params) {
params = `CurrentNoticeId=${this.downloadId}`
} else {
params += `&CurrentNoticeId=${this.downloadId}`
}
if (params) {
params += `&access_token=${getToken()}`
let url = `/api/download/GetPatientStudyBatchDownload?${params}`
// let url = `http://106.14.89.110:30021/download/DownloadBigFileBatch?fileName=Test_HIR_New_log.ldf`
let a = document.createElement('a')
a.href = url
a.click()
a = null
}
} catch (err) {
console.log(err)
}
},
formatSize(size, fixed = 2) {
if (isNaN(parseFloat(size))) return ''
let kbSize = size / 1024
if (kbSize <= 1024) {
return `${kbSize.toFixed(fixed)}KB`
}
let mbSize = kbSize / 1024
return `${mbSize.toFixed(fixed)}MB`
},
//
async downloadImage(data, OtherInfo) {
try {
let { files, name } = this.formatDownloadFile(data)
let res = await downLoadFile(files, name, 'zip', async (data) => {
let { type } = data
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.downLoadImageCount++
if (this.downLoadImageCount >= OtherInfo.ImageCount) {
this.downLoadImageCount = OtherInfo.ImageCount
this.percentage = 100
} else {
this.percentage = (((this.downLoadImageCount / OtherInfo.ImageCount).toFixed(2)) * 100).toFixed(0)
}
}
if (type === 'downLoaded') {
}
if (type === 'error') {
let confirm = await this.$confirm(this.$t('trials:imageSummary:confirm:downloadError'))
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
}
if (type === 'zipEnd') {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
if (this.downloadId) {
this.downloadImageSuccess()
}
}
})
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile(data) {
let files = [],
name = `Image_${Date.now()}.zip`
data.forEach(patient => {
if (Array.isArray(patient.StudyList) && patient.StudyList.length > 0) {
patient.StudyList.forEach((study) => {
let arr = []
study.ModalityList.forEach(item => {
if (!arr.includes(item)) {
arr.push(item)
}
})
let str = arr.join('_')
if (study.StudyDIRPath && !study.dirHas) {
study.dirHas = true
let obj = {
name: `${study.PatientId}/${study.StudyTime}_${str}/DICOMDIR`,
url: this.OSSclientConfig.basePath + study.StudyDIRPath,
}
files.push(obj)
}
if (Array.isArray(study.SeriesList) && study.SeriesList.length > 0) {
study.SeriesList.forEach((series) => {
if (
Array.isArray(series.InstanceList) &&
series.InstanceList.length > 0
) {
series.InstanceList.forEach((instance) => {
let fileName = instance.FileName || instance.Path.split('/').pop()
let obj = {
name: `${study.PatientId}/${study.StudyTime}_${str}/IMAGE/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
})
}
})
}
})
}
})
return { files, name }
},
//
async downloadImageSuccess() {
try {
let params = {
TrialImageDownloadId: this.downloadId,
}
await downloadImageSuccess(params)
} catch (err) {
console.log(err)
}
},
// calledAE
async getDicomCalledAEList() {
try {
let res = await getDicomCalledAEList()
if (res.IsSuccess) {
this.calledAeList = res.Result
}
} catch (err) {
console.log(err)
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
async getHospitalGroupList() {
try {
let res = await getHospitalGroupList({})
if (res.IsSuccess) {
this.hospitalGroupList = res.Result
}
} catch (err) {
console.log(err)
}
},
//
async deletePatientStudyAllData(item) {
try {
@@ -265,17 +538,6 @@ export default {
console.log(err)
}
},
// calledAE
async getDicomCalledAEList() {
try {
let res = await getDicomCalledAEList()
if (res.IsSuccess) {
this.calledAeList = res.Result
}
} catch (err) {
console.log(err)
}
},
// callingAE
async getDicomCallingAEList() {
try {
@@ -337,10 +599,46 @@ export default {
this.getList()
},
//
handleOpenDialog(item, key) {
handleOpenDialog(item, key, isAll = false) {
if (key === 'study') {
this[`${key}All`] = isAll
}
this[`${key}TrialsVisible`] = true
this.selectPatient = item
},
async onUploadProgress(id, num, type = 'start') {
if (id !== this.downloadId) return false
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.percentage = num
// if (this.downLoadImageCount >= OtherInfo.ImageCount) {
// this.downLoadImageCount = OtherInfo.ImageCount
// this.percentage = 100
// } else {
// this.percentage = (((this.downLoadImageCount / OtherInfo.ImageCount).toFixed(2)) * 100).toFixed(0)
// }
}
if (num >= 100) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
}
// if (type === 'downLoaded') {
// }
// if (type === 'error') {
// let confirm = await this.$confirm(this.$t('trials:imageSummary:confirm:downloadError'))
// this.downLoadType = 'start'
// this.percentage = 0
// this.downLoadImageCount = 0
// this.downloadVisible = false
// }
}
},
mounted() {
this.$EventBus.$on("reload", (data) => {
@@ -349,4 +647,9 @@ export default {
}
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
::v-deep .el-progress {
display: flex;
align-items: center;
}
</style>
@@ -1,125 +1,82 @@
<template>
<div class="notice-marquee_wrapper">
<marquee ref="mar" hspace="0" direction="left" :width="isEN ? '400' : '500'" @mouseout="start()" @mouseover="stop()">
<marquee ref="mar" hspace="0" direction="left" width="100%" @mouseout="start()" @mouseover="stop()">
<!-- <i class="el-icon-message-solid" /> -->
<svg-icon v-if="noticeList.length > 0" icon-class="speaker" />
<span v-for="item in noticeList" :key="item.Id" style="cursor: pointer" @click="showDetail(item)">
<span v-for="item in noticeList" :key="item.Id" style="cursor:pointer;" @click="showDetail(item)">
{{ item.Content }}
</span>
</marquee>
</div>
</template>
<script>
import { setSystemNoticeHaveRead } from "@/api/global";
import { getBasicDataSelects } from "@/api/dictionary/dictionary";
import { setSystemNoticeHaveRead } from '@/api/global'
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
export default {
name: "NoticeMarquee",
name: 'NoticeMarquee',
data() {
return {
noteType: [],
};
noteType: []
}
},
computed: {
noticeList() {
return this.$store.state.global.noticeList || [];
},
isEN() {
return this.$i18n.locale !== 'zh'
return this.$store.state.global.noticeList || []
}
},
mounted() {
this.getDicData();
this.getDicData()
},
methods: {
start() {
this.$refs["mar"].start();
this.$refs['mar'].start()
},
stop() {
this.$refs["mar"].stop();
this.$refs['mar'].stop()
},
showDetail(item) {
var currentNoticeType = "";
const i = this.noteType.findIndex(
(note) => note.Code * 1 === item.NoticeTypeEnum
);
var currentNoticeType = ''
const i = this.noteType.findIndex(note => note.Code * 1 === item.NoticeTypeEnum)
if (i > -1) {
currentNoticeType = this.noteType[i].Value;
currentNoticeType = this.noteType[i].Value
}
const h = this.$createElement;
let _this = this;
const h = this.$createElement
this.$msgbox({
title: currentNoticeType,
message: h("div", null, [
h("span", null, item.Content),
item.Path
? h(
"div",
{
style: {
marginTop: "10px",
},
},
_this.$t("trials:notice:message:tipTitle")
)
: "",
item.Path
? h(
"a",
{
attrs: {
href: _this.OSSclientConfig.basePath + item.Path,
target: "_blank",
},
style: {
color: "#428bca",
},
},
item.FileName
)
: "",
]),
message: h('span', null, item.Content),
beforeClose: (action, instance, done) => {
if (action === "confirm") {
instance.confirmButtonLoading = true;
setSystemNoticeHaveRead(item.Id)
.then(async (res) => {
if (res.IsSuccess) {
await this.$store.dispatch("global/getNoticeList");
}
instance.confirmButtonLoading = false;
done();
})
.catch(() => {
instance.confirmButtonLoading = false;
});
if (action === 'confirm') {
instance.confirmButtonLoading = true
setSystemNoticeHaveRead(item.Id).then(async res => {
if (res.IsSuccess) {
await this.$store.dispatch('global/getNoticeList')
}
instance.confirmButtonLoading = false
done()
}).catch(() => { instance.confirmButtonLoading = false })
} else {
done();
done()
}
},
});
}
})
},
getDicData() {
getBasicDataSelects(["NoteType"]).then((res) => {
this.noteType = res.Result.NoteType;
});
},
},
};
getBasicDataSelects(['NoteType']).then(res => {
this.noteType = res.Result.NoteType
})
}
}
}
</script>
<style lang="scss" scoped>
.notice-marquee_wrapper {
.notice-marquee_wrapper{
width: 100%;
display: flex;
align-items: center;
span {
font-size: 20px;
}
>>>.el-dialog__header {
::v-deep .el-dialog__header{
padding: 10px;
}
>>>.el-dialog__body {
::v-deep .el-dialog__body{
padding: 10px 20px;
line-height: 25px;
}
@@ -22,7 +22,7 @@
<!-- 工作台 -->
<!-- <span slot="title">{{ $t('trials:menuTitle:workbench') }}</span>
</el-menu-item> -->
<el-menu-item v-if="hasPermi(['role:pm', 'role:oa', 'role:admin', 'role:dev'])" index="1">
<el-menu-item v-if="hasPermi(['role:pm', 'role:sa', 'role:admin', 'role:dev', 'role:ga'])" index="1">
<i class="el-icon-odometer" />
<!-- 检查 -->
<span slot="title">{{ $t('trials:menuTitle:inspection') }}</span>
@@ -61,7 +61,7 @@
$t('trials:trials-myinfo:title:accountInfo')
}}</el-menu-item>
<!-- 管理后台 -->
<el-menu-item v-if="hasPermi(['role:dev', 'role:oa', 'role:admin'])" index="4-4">{{
<el-menu-item v-if="hasPermi(['role:dev', 'role:sa', 'role:admin', 'role:ga'])" index="4-4">{{
$t('trials:trials-myinfo:title:system') }}</el-menu-item>
<!-- 切换角色 -->
<el-menu-item index="4-5" v-if="hasRole">{{
@@ -98,7 +98,7 @@ export default {
NODE_ENV: process.env.NODE_ENV, // process.env.NODE_ENV
activeIndex: '2',
isReviewer: false,
userTypeShortName: zzSessionStorage.getItem('userTypeShortName'),
// userTypeShortName: zzSessionStorage.getItem('userTypeShortName'),
notice: '',
hospital: {
HospitalLogoPath: null,
@@ -116,6 +116,7 @@ export default {
'device',
'TotalNeedSignSystemDocCount',
'language',
'userTypeShortName'
]),
roles() {
return this.$store.state.user.roles
@@ -140,23 +141,22 @@ export default {
},
},
created() {
this.isReviewer = JSON.parse(zzSessionStorage.getItem('IsReviewer'))
// this.isReviewer = JSON.parse(zzSessionStorage.getItem('IsReviewer'))
this.changeRoute(this.$route)
this.getInfo()
this.$store.dispatch('user/getUserInfo')
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
loginByRole(row) {
let { UserId, UserTypeId } = row
if (this.$store.state.user.userId === UserId) {
loginByRole(userRoleId) {
if (this.$store.state.user.userId === userRoleId) {
this.toggleRoleVisible = false
this.toggleRoleLoading = false
return false
}
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { UserId, UserTypeId })
.dispatch('user/loginByRole', { userRoleId })
.then((res) => {
if (res) {
this.$store
@@ -176,17 +176,22 @@ export default {
return
}
if (
this.hasPermi(['role:pm', 'role:oa', 'role:admin', 'role:dev'])
this.hasPermi(['role:pm', 'role:sa', 'role:admin', 'role:dev', 'role:ga'])
) {
history.replaceState(null, null, '/trials/trials-inspection')
history.go(0)
// this.$router.replace({ path: '/trials/trials-list' })
} else {
history.replaceState(null, null, '/trials/trials-list')
history.go(0)
// this.$router.replace({ path: '/trials/trials-workbench' })
}
this.toggleRoleVisible = false
this.toggleRoleLoading = false
this.$EventBus.$emit('reload')
// this.$nextTick(() => {
// window.location.reload()
// })
} else {
//
this.toggleRoleLoading = false
@@ -274,7 +279,7 @@ export default {
this.$store.dispatch('app/toggleSideBar')
},
async logout() {
await loginOut()
// await loginOut()
await this.$store.dispatch('user/logout')
this.$router.push(`/login`)
this.$i18n.locale = 'zh'
@@ -1,66 +1,28 @@
<!-- eslint-disable -->
<template>
<el-form
ref="trialForm"
v-loading="loading"
label-width="250px"
:rules="trialFormRules"
class="demo-ruleForm trial-Form"
:model="trialForm"
label-position="right"
:inline="true"
>
<el-form ref="trialForm" v-loading="loading" label-width="250px" :rules="trialFormRules"
class="demo-ruleForm trial-Form" :model="trialForm" label-position="right" :inline="true">
<el-row>
<!-- 项目码 -->
<el-form-item
:label="$t('trials:trials-list:table:trialId')"
prop="TrialCode"
v-if="trialForm.Id !== ''"
>
<el-form-item :label="$t('trials:trials-list:table:trialId')" prop="TrialCode" v-if="trialForm.Id !== ''">
<el-input v-model="trialForm.TrialCode" disabled />
<!-- <el-input v-model="trialForm.TrialCode" /> -->
</el-form-item>
<!-- 项目类型 -->
<el-form-item
:label="$t('trials:trials-list:form:trialType')"
prop="TrialType"
>
<el-radio-group
v-model="trialForm.TrialType"
:disabled="trialForm.Id !== ''"
>
<el-radio
v-for="item of $d.TrialType"
:key="item.id"
:label="item.value"
>{{ item.label }}</el-radio
>
<el-form-item :label="$t('trials:trials-list:form:trialType')" prop="TrialType">
<el-radio-group v-model="trialForm.TrialType" :disabled="trialForm.Id !== ''">
<el-radio v-for="item of $d.TrialType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-row>
<el-row>
<!-- 研究方案号 -->
<el-form-item
:label="$t('trials:trials-list:form:researchNumber')"
prop="ResearchProgramNo"
>
<el-input
v-model="trialForm.ResearchProgramNo"
clearable
:disabled="TrialStatusStr === 'Ongoing'"
/>
<el-form-item :label="$t('trials:trials-list:form:researchNumber')" prop="ResearchProgramNo">
<el-input v-model="trialForm.ResearchProgramNo" clearable :disabled="TrialStatusStr === 'Ongoing'" />
</el-form-item>
<!-- 研究名称 -->
<el-form-item
:label="$t('trials:trials-list:table:researchName')"
prop="ExperimentName"
>
<el-input
v-model="trialForm.ExperimentName"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4 }"
clearable
/>
<el-form-item :label="$t('trials:trials-list:table:researchName')" prop="ExperimentName">
<el-input v-model="trialForm.ExperimentName" type="textarea" :autosize="{ minRows: 1, maxRows: 4 }" clearable />
</el-form-item>
</el-row>
<el-row>
@@ -69,34 +31,19 @@
<el-input v-model="trialForm.MedicineName" clearable />
</el-form-item>
<!-- 申办方 -->
<el-form-item
:label="$t('trials:trials-list:form:sponsor')"
prop="Sponsor"
>
<el-form-item :label="$t('trials:trials-list:form:sponsor')" prop="Sponsor">
<el-input v-model="trialForm.Sponsor" maxlength="200" clearable />
</el-form-item>
</el-row>
<el-row>
<!-- 研究者 -->
<el-form-item
:label="$t('trials:trials-list:form:investigator')"
prop="HeadPI"
>
<el-form-item :label="$t('trials:trials-list:form:investigator')" prop="HeadPI">
<el-input v-model="trialForm.HeadPI" clearable />
</el-form-item>
<!-- 临床分期 -->
<el-form-item :label="$t('trials:trials-list:form:phase')" prop="PhaseId">
<el-select
v-model="trialForm.PhaseId"
@change="handlePhaseChange"
clearable
>
<el-option
v-for="item of $d.Trial_Phase"
:key="item.id"
:label="item.label"
:value="item.id"
/>
<el-select v-model="trialForm.PhaseId" @change="handlePhaseChange" clearable>
<el-option v-for="item of $d.Trial_Phase" :key="item.id" :label="item.label" :value="item.id" />
</el-select>
</el-form-item>
</el-row>
@@ -106,37 +53,30 @@
<el-input v-model="trialForm.Indication" clearable />
</el-form-item>
<!-- 阅片标准 -->
<el-form-item
:label="$t('trials:trials-list:form:criterion')"
prop="CriterionTypeList"
>
<el-select
v-model="trialForm.CriterionTypeList"
multiple
clearable
:disabled="TrialStatusStr === 'Ongoing'"
>
<el-option
v-for="item of CriterionTypeList"
:key="item.Id"
:label="item.CriterionName"
:value="item.CriterionType"
:title="item.Description"
/>
<el-form-item :label="$t('trials:trials-list:form:criterion')" prop="CriterionTypeList">
<el-select v-model="trialForm.CriterionTypeList" multiple clearable :disabled="TrialStatusStr === 'Ongoing'">
<el-option v-for="item of CriterionTypeList" :key="item.Id" :label="item.CriterionName"
:value="item.CriterionType" :title="item.Description" />
</el-select>
</el-form-item>
</el-row>
<el-row>
<!-- 课题组 -->
<el-form-item :label="$t('trials:trials-list:form:HospitalGroupId')" prop="HospitalGroupId">
<el-select v-model="trialForm.HospitalGroupId" clearable :disabled="TrialStatusStr === 'Ongoing'">
<el-option v-for="item of hospitalGroupList" :key="item.Id" :label="item.Name" :value="item.Id" />
</el-select>
</el-form-item>
<!-- CRO -->
<el-form-item :label="$t('trials:trials-list:form:cro')" prop="Cro">
<el-input v-model="trialForm.CRO" maxlength="200" clearable />
</el-form-item>
</el-row>
<el-row>
<!-- 联系人 -->
<el-form-item :label="$t('trials:researchForm:form:contactor')">
<el-input v-model="trialForm.ContactUser" clearable />
</el-form-item>
</el-row>
<el-row>
<!-- 电话 -->
<el-form-item :label="$t('trials:trials-myinfo:form:phone')">
<el-input v-model="trialForm.ContactPhone" type="number" clearable />
@@ -144,32 +84,15 @@
</el-row>
<el-row>
<!-- 项目周期 -->
<el-form-item
:label="$t('trials:trials-list:form:projectCycle')"
prop="AuthorizationDuration"
>
<el-form-item :label="$t('trials:trials-list:form:projectCycle')" prop="AuthorizationDuration">
<div style="position: relative">
<el-input
v-model.number="trialForm.AuthorizationDuration"
type="number"
clearable
:max="200"
:min="1"
/>
<el-input v-model.number="trialForm.AuthorizationDuration" type="number" clearable :max="200" :min="1" />
</div>
</el-form-item>
<!-- 到期日 -->
<el-form-item
:label="$t('trials:trials-list:table:dateAuthorized')"
prop="visitNumberAuthorized"
>
<el-date-picker
v-model="trialForm.AuthorizationDate"
value-format="yyyy-MM-dd"
type="date"
placeholder=""
disabled
>
<el-form-item :label="$t('trials:trials-list:table:dateAuthorized')" prop="visitNumberAuthorized">
<el-date-picker v-model="trialForm.AuthorizationDate" value-format="yyyy-MM-dd" type="date" placeholder=""
disabled>
</el-date-picker>
</el-form-item>
</el-row>
@@ -193,6 +116,9 @@ import {
addOrUpdateTrialHir,
getSystemConfirmedCreiterionList,
} from "@/api/trials";
import {
getHospitalGroupList
} from '@/api/admin.js'
import { getBasicDataSelects } from "@/api/dictionary/dictionary";
export default {
name: "TrialForm",
@@ -222,9 +148,18 @@ export default {
ContactPhone: "",
AuthorizationDuration: null,
AuthorizationDate: null,
HospitalGroupId: null
},
indicationGrouping: null,
trialFormRules: {
//
HospitalGroupId: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
},
],
//
TrialCode: [
{
@@ -350,6 +285,7 @@ export default {
dictionaryList: {},
CriterionTypeList: [], //
TrialStatusStr: null, //
hospitalGroupList: []
};
},
computed: {
@@ -360,6 +296,16 @@ export default {
this.initPage();
},
methods: {
async getHospitalGroupList() {
try {
let res = await getHospitalGroupList({})
if (res.IsSuccess) {
this.hospitalGroupList = res.Result
}
} catch (err) {
console.log(err)
}
},
//
async getSystemConfirmedCreiterionList() {
try {
@@ -494,6 +440,7 @@ export default {
this.initForm();
}
this.getSystemConfirmedCreiterionList();
this.getHospitalGroupList()
this.loading = false;
},
getDicData() {
@@ -519,6 +466,7 @@ export default {
.trial-Form .el-textarea {
width: 340px;
}
.trial-Form .el-col .el-input {
width: 165px;
margin-right: 10px;
@@ -1,7 +1,9 @@
<template>
<el-dialog v-dialogDrag :visible.sync="visible" :close-on-click-modal="false"
:title="$t('trials:trials-list:action:activateProject')" width="500px" append-to-body :before-close="handleCancel">
<el-form ref="activateProjectForm" :model="form" :rules="rules" size="small" label-width="120px">
:title="$t('trials:trials-list:action:activateProject')" :width="isEN ? '600px' : '500px'" append-to-body
:before-close="handleCancel">
<el-form ref="activateProjectForm" :model="form" :rules="rules" size="small"
:label-width="isEN ? '200px' : '120px'">
<div class="base-dialog-body">
<p class="title">{{ $t("trials:activate:ApplyMessage") }}</p>
<!-- 单位名称 -->
@@ -25,7 +27,7 @@
}}</span>
</el-form-item>
<!-- 项目码 -->
<el-form-item :label="$t('trials:trials-list:table:trialID')">
<el-form-item :label="$t('trials:trials-list:table:trialGuid')">
<span>{{ form.TrialId }}</span>
</el-form-item>
<!-- 机器码 -->
@@ -158,6 +160,11 @@ export default {
timer: null,
};
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
}
},
created() {
this.getTrialAuthorizationInfo();
},
+5 -5
View File
@@ -87,14 +87,14 @@
</el-table-column>
<el-table-column prop="TrialCode" :label="$t('trials:trials-list:table:trialId')" show-overflow-tooltip
min-width="100" sortable="custom" />
<el-table-column prop="ResearchProgramNo" :label="$t('trials:trials-list:table:researchNumber')"
show-overflow-tooltip min-width="120" sortable="custom" />
<el-table-column prop="ExperimentName" :label="$t('trials:trials-list:table:experimentName')"
show-overflow-tooltip min-width="120" sortable="custom" />
<el-table-column prop="ResearchProgramNo" :label="$t('trials:trials-list:table:researchNumber')"
show-overflow-tooltip min-width="120" sortable="custom" />
<el-table-column prop="Sponsor" :label="$t('trials:trials-list:table:sponsor')" min-width="90"
show-overflow-tooltip sortable="custom" />
<el-table-column prop="HospitalGroupName" :label="$t('trials:trials-list:table:HospitalGroupName')"
show-overflow-tooltip min-width="120" sortable="custom" />
<el-table-column prop="TrialStatusStr" :label="$t('trials:trials-list:table:status')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
@@ -137,7 +137,7 @@
show-overflow-tooltip
sortable="custom"
/> -->
<el-table-column label="" min-width="200" align="left" fixed="right">
<el-table-column :label="$t('common:action:action')" min-width="200" align="left" fixed="right">
<template slot-scope="scope">
<!-- 详情 -->
<el-button v-hasPermi="['trials:trials-list:panel']" circle icon="el-icon-info"
+130 -97
View File
@@ -5,132 +5,73 @@
<!-- 账号信息 -->
{{ $t("trials:trials-myinfo:title:accountInfo") }}
</div>
<el-form label-position="right" label-width="100px">
<el-form label-position="right" label-width="100px" ref="userForm" :model="userForm" :rules="rules">
<!-- 用户名 -->
<el-form-item
:label="$t('trials:trials-myinfo:form:userName')"
style="margin-bottom: 5px"
prop="UserName"
>
<el-form-item :label="$t('trials:trials-myinfo:form:userName')" style="margin-bottom: 5px" prop="UserName">
<span>{{ user.UserName }}</span>
</el-form-item>
<el-form-item label="" style="position: relative" prop="UserName">
<el-input
v-model="userForm.UserName"
:placeholder="$t('trials:trials-myinfo:form:userName')"
/>
<el-input v-model="userForm.UserName" :placeholder="$t('trials:trials-myinfo:form:userName')" />
<!-- 修改 -->
<el-button
:disabled="!userForm.UserName"
class="saveBtn"
type="primary"
size="small"
@click="setNewUserName"
>
<el-button :disabled="!userForm.UserName" class="saveBtn" type="primary" size="small" @click="setNewUserName">
{{ $t("trials:trials-myinfo:button:update") }}
</el-button>
</el-form-item>
<!-- 校验码 -->
<el-form-item
:label="$t('trials:researchForm:form:checkCode')"
style="margin-bottom: 5px"
prop="CheckCode"
>
<el-form-item :label="$t('trials:researchForm:form:checkCode')" style="margin-bottom: 5px" prop="CheckCode">
<span>{{ user.CheckCode }}</span>
</el-form-item>
<el-form-item label="" style="position: relative" prop="CheckCode">
<el-input
v-model="userForm.CheckCode"
:placeholder="$t('trials:researchForm:form:checkCode')"
:maxlength="6"
type="number"
/>
<el-input v-model="userForm.CheckCode" :placeholder="$t('trials:researchForm:form:checkCode')" :maxlength="6"
:title="this.$t('recompose:tip:inputCheckCode')" type="number" />
<!-- 修改 -->
<el-button
:disabled="!userForm.CheckCode"
class="saveBtn"
type="primary"
size="small"
@click.stop="setNewUserCheckCode"
>
<el-button :disabled="!userForm.CheckCode || userForm.CheckCode.length != 6" class="saveBtn" type="primary"
size="small" @click.stop="setNewUserCheckCode">
{{ $t("trials:trials-myinfo:button:update") }}
</el-button>
</el-form-item>
<!-- 电话 -->
<el-form-item
:label="$t('trials:trials-myinfo:form:phone')"
style="margin-bottom: 5px"
prop="UserName"
>
<el-form-item :label="$t('trials:trials-myinfo:form:phone')" style="margin-bottom: 5px" prop="Phone">
<span>{{ user.Phone }}</span>
</el-form-item>
<el-form-item label="" style="position: relative" prop="UserName">
<el-input
v-model="userForm.Phone"
:placeholder="$t('trials:trials-myinfo:form:phone')"
/>
<el-form-item label="" style="position: relative">
<el-input v-model="userForm.Phone" :placeholder="$t('trials:trials-myinfo:form:phone')" />
<!-- 修改 -->
<el-button
:disabled="!userForm.Phone"
class="saveBtn"
type="primary"
size="small"
@click="setNewPhone"
>
<el-button :disabled="!userForm.Phone" class="saveBtn" type="primary" size="small" @click="setNewPhone">
{{ $t("trials:trials-myinfo:button:update") }}
</el-button>
</el-form-item>
<!-- 邮箱 -->
<el-form-item
:label="$t('trials:trials-myinfo:form:email')"
style="margin-bottom: 5px"
prop="UserName"
>
<el-form-item :label="$t('trials:trials-myinfo:form:email')" style="margin-bottom: 5px">
<span>{{ user.EMail }}</span>
</el-form-item>
<el-form-item
label=""
style="margin-bottom: 10px; position: relative"
prop="EMail"
v-if="IsCanConnectInternet"
>
<el-input
v-model="userForm.EMail"
@input="handleEmailChange"
:placeholder="$t('trials:trials-myinfo:form:email')"
/>
<el-button
class="sendCode"
:disabled="sendDisabled"
type="primary"
size="mini"
@click="sendVerificationCode"
>{{ sendTitle }}</el-button
>
<el-form-item label="" style="margin-bottom: 10px; position: relative" prop="EMail" v-if="IsCanConnectInternet">
<el-input v-model="userForm.EMail" @input="handleEmailChange"
:placeholder="$t('trials:trials-myinfo:form:email')" />
<el-button class="sendCode" :disabled="sendDisabled" type="primary" size="mini"
@click="sendVerificationCode">{{ sendTitle }}</el-button>
</el-form-item>
<el-form-item
label=""
style="position: relative"
prop="VerificationCode"
v-if="IsCanConnectInternet"
>
<el-input
v-model="userForm.VerificationCode"
:placeholder="$t('trials:researchForm:form:verifyCode')"
/>
<el-form-item label="" style="position: relative" v-if="IsCanConnectInternet">
<el-input v-model="userForm.VerificationCode" :placeholder="$t('trials:researchForm:form:verifyCode')" />
<!-- 修改 -->
<el-button
:disabled="
!userForm.EMail || !userForm.VerificationCode
"
class="saveBtn"
type="primary"
size="small"
@click="setNewEmail"
>
<el-button :disabled="!userForm.EMail || !userForm.VerificationCode
" class="saveBtn" type="primary" size="small" @click="setNewEmail">
{{ $t("trials:trials-myinfo:button:update") }}
</el-button>
</el-form-item>
<el-form-item :label="$t('trials:trials-myinfo:form:toggleRole')" style="position: relative" v-if="hasRole">
<el-radio-group v-model="userRoleId" class="roles" v-if="hasRole">
<el-radio v-for="item in roles" :key="item.Id" :label="item.Id" :disabled="item.IsUserRoleDisabled"
style="margin-bottom: 10px">
{{ item.UserTypeShortName }}
</el-radio>
</el-radio-group>
<!-- 修改 -->
<el-button :disabled="!userRoleId || saveDisabled" class="saveBtn" :loading="toggleRoleLoading" type="primary"
size="small" @click="toggleRole">
{{ $t('trials:trials-myinfo:button:toggleRole') }}
</el-button>
</el-form-item>
</el-form>
</div>
<password />
@@ -168,12 +109,98 @@ export default {
userForm: {},
sendDisabled: true,
sendTitle: this.$t("trials:trials-myinfo:button:getVCode"),
userRoleId: null,
toggleRoleLoading: false,
rules: {
CheckCode: [
{
validator: (rule, value, callback) => {
const regex = /^[1-9]\d{5}$/;
if (
value &&
(String(value).includes('.') ||
!regex.test(String(value)))
) {
callback(new Error(this.$t('recompose:tip:inputCheckCode')))
} else {
callback()
}
},
trigger: 'blur',
},
],
EMail: [
{
pattern: new RegExp(this.$reg().EmailRegexStr),
message: this.$t("passwordReset:formRule:passwordinvalid"),
trigger: ['blur'],
},
],
UserName: [
{
validator: (rule, value, callback) => {
var lang = zzSessionStorage.getItem('lang')
? zzSessionStorage.getItem('lang')
: 'zh'
/* eslint-disable */
var reg1 = /^[a-zA-Z0-9_]{4,16}$/ //8
if (value && !reg1.test(value)) {
callback(
lang === 'zh'
? new Error(
'1)新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
)
: new Error(
'For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
)
)
} else {
callback()
}
}, trigger: 'blur'
},
],
}
};
},
created() {
this.userRoleId = zzSessionStorage.getItem('userId')
},
computed: {
roles() {
return this.$store.state.user.roles
},
hasRole() {
return this.roles && this.roles.length > 1
},
saveDisabled() {
return this.userRoleId === zzSessionStorage.getItem('userId')
},
},
methods: {
//
toggleRole() {
if (
this.userRoleId === zzSessionStorage.getItem('userId') ||
this.toggleRoleLoading
)
return false
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { userRoleId: this.userRoleId })
.then((res) => {
zzSessionStorage.removeItem('lastWorkbench')
window.location.reload()
})
.catch(() => {
this.toggleRoleLoading = false
})
},
//
async setNewUserCheckCode() {
try {
let validate = await this.$refs.userForm.validate()
if (!validate) return false
let res = await SetNewCheckCode(this.userForm.CheckCode);
if (res.IsSuccess) {
this.userForm.CheckCode = "";
@@ -186,7 +213,9 @@ export default {
console.log(err);
}
},
setNewEmail() {
async setNewEmail() {
let validate = await this.$refs.userForm.validate()
if (!validate) return false
setNewEmail(this.userForm.EMail, this.userForm.VerificationCode).then(
() => {
this.userForm.EMail = "";
@@ -200,6 +229,8 @@ export default {
},
async setNewUserName() {
try {
let validate = await this.$refs.userForm.validate()
if (!validate) return false
let confirm = await this.$confirm(
this.$t("trials:trials-myInfo:confirmMessage:updateUserName"),
{
@@ -224,7 +255,9 @@ export default {
console.log(err);
}
},
setNewPhone() {
async setNewPhone() {
let validate = await this.$refs.userForm.validate()
if (!validate) return false
setNewPhone(this.userForm.Phone).then(() => {
this.userForm.Phone = "";
this.$message.success(
+20 -22
View File
@@ -1,11 +1,6 @@
<template>
<div class="trial-myinfo">
<el-menu
:default-active="activeIndex"
@select="handleSelect"
class="el-menu-demo"
style="width: 200px"
>
<el-menu :default-active="activeIndex" @select="handleSelect" class="el-menu-demo" style="width: 200px">
<el-menu-item index="1">{{
$t("trials:trials-myinfo:menuTitle:mine")
}}</el-menu-item>
@@ -17,19 +12,10 @@
}}</el-menu-item>
</el-menu>
<div class="contentBox">
<mine
:user="user"
:userTypeOptions="userTypeOptions"
v-if="activeIndex === '1'"
@getUserInfo="getUserInfo"
/>
<account
:user="user"
@getUserInfo="getUserInfo"
:IsCanConnectInternet="IsCanConnectInternet"
v-if="activeIndex === '2'"
/>
<login-log v-if="activeIndex === '3'" :id="userId" :isMine="true" />
<mine :user="user" :userTypeOptions="userTypeOptions" v-if="activeIndex === '1'" @getUserInfo="getUserInfo" />
<account :user="user" @getUserInfo="getUserInfo" :IsCanConnectInternet="IsCanConnectInternet"
v-if="activeIndex === '2'" />
<login-log v-if="activeIndex === '3'" :id="identityUserId" :isMine="true" />
</div>
</div>
</template>
@@ -56,7 +42,7 @@ export default {
};
},
computed: {
...mapGetters(["userId", "userName"]),
...mapGetters(["identityUserId", "userName"]),
},
mounted() {
this.getUserInfo();
@@ -86,11 +72,11 @@ export default {
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.07)",
});
getUser(this.userId)
getUser()
.then(async (res) => {
this.user = res.Result;
/* eslint-disable */
zzSessionStorage.setItem("realName", this.user.RealName);
zzSessionStorage.setItem("Name", this.user.FullName);
await store.dispatch("user/updateInfo");
loading.close();
})
@@ -116,6 +102,7 @@ export default {
display: flex;
flex-direction: row;
justify-content: space-around;
.contentBox {
width: calc(100% - 220px);
background-color: #fff;
@@ -124,18 +111,21 @@ export default {
overflow: auto;
// padding-bottom: 50px;
}
.trial-myinfo-head {
position: absolute;
top: 40px;
left: 20px;
font-size: 14px;
}
.trial-myinfo-left {
overflow: auto;
background: #fff;
// width: calc(50% - 9px);
// margin: 6px 0;
height: 100%;
// padding-bottom: 50px;
.trial-myinfo-left-top {
width: 70%;
@@ -143,6 +133,7 @@ export default {
position: relative;
// margin: 0 auto;
margin-bottom: 10px;
.trial-myinfo-body {
width: 160px;
height: 160px;
@@ -152,6 +143,7 @@ export default {
justify-content: center;
align-items: center;
margin-left: 30px;
div {
color: #fff;
font-size: 30px;
@@ -159,36 +151,42 @@ export default {
}
}
}
.saveBtn {
position: absolute;
right: -10px;
top: 2px;
transform: translateX(100%);
}
.trial-info-btn {
position: absolute;
bottom: -60px;
left: 10px;
min-width: 97px;
}
.trial-myinfo-left-bottom {
width: 40%;
padding-top: 100px;
position: relative;
// margin: 0 auto;
}
.trial-myinfo-right {
overflow: auto;
background: #fff;
// width: calc(50% - 9px);
// margin: 6px 0;
height: 100%;
.sendCode {
position: absolute;
right: -10px;
top: 50%;
transform: translate(100%, -50%);
}
.trial-myinfo-right-box {
width: 40%;
padding-top: 100px;
+15 -57
View File
@@ -5,77 +5,35 @@
<!-- 用户基本信息 -->
{{ $t("trials:trials-myinfo:title:basicInfo") }}
</div>
<el-form
ref="userForm"
label-position="right"
:model="user"
:rules="userFormRules"
label-width="120px"
>
<el-form ref="userForm" label-position="right" :model="user" :rules="userFormRules" label-width="120px">
<el-form-item v-if="user.Code" label="ID: " prop="Code">
<el-input v-model="user.Code" disabled />
</el-form-item>
<!-- -->
<el-form-item
:disabled="user.UserTypeEnum === 8"
:label="$t('trials:trials-myinfo:form:surname')"
prop="LastName"
>
<el-input
v-model="user.LastName"
:placeholder="$t('trials:trials-myinfo:form:surname')"
/>
<el-form-item :disabled="user.UserTypeEnum === 8" :label="$t('trials:trials-myinfo:form:surname')"
prop="LastName">
<el-input v-model="user.LastName" :placeholder="$t('trials:trials-myinfo:form:surname')" />
</el-form-item>
<!-- -->
<el-form-item
:disabled="user.UserTypeEnum === 8"
:label="$t('trials:trials-myinfo:form:givenname')"
prop="FirstName"
>
<el-input
v-model="user.FirstName"
:placeholder="$t('trials:trials-myinfo:form:givenname')"
/>
<el-form-item :disabled="user.UserTypeEnum === 8" :label="$t('trials:trials-myinfo:form:givenname')"
prop="FirstName">
<el-input v-model="user.FirstName" :placeholder="$t('trials:trials-myinfo:form:givenname')" />
</el-form-item>
<!-- 单位$t('trials:trials-myinfo:form:organization') -->
<el-form-item
:label="$t('trials:trials-myinfo:form:organization')"
prop="OrganizationName"
>
<el-input
:disabled="user.IsZhiZhun"
v-model="user.OrganizationName"
placeholder=""
/>
<!-- 单位$t('trials:trials-myinfo:form:organization'):disabled="user.IsZhiZhun" -->
<el-form-item :label="$t('trials:trials-myinfo:form:organization')" prop="OrganizationName">
<el-input v-model="user.OrganizationName" placeholder="" />
</el-form-item>
<!-- 部门 -->
<el-form-item
:label="$t('trials:trials-myinfo:form:department')"
prop="DepartmentName"
>
<el-input
v-model="user.DepartmentName"
:placeholder="$t('trials:trials-myinfo:form:organization')"
/>
<el-form-item :label="$t('trials:trials-myinfo:form:department')" prop="DepartmentName">
<el-input v-model="user.DepartmentName" :placeholder="$t('trials:trials-myinfo:form:organization')" />
</el-form-item>
<!-- 职位 -->
<el-form-item
:label="$t('trials:trials-myinfo:form:position')"
prop="PositionName"
>
<el-input
v-model="user.PositionName"
:placeholder="$t('trials:trials-myinfo:form:position')"
/>
<el-form-item :label="$t('trials:trials-myinfo:form:position')" prop="PositionName">
<el-input v-model="user.PositionName" :placeholder="$t('trials:trials-myinfo:form:position')" />
</el-form-item>
</el-form>
<!-- 保存 -->
<el-button
class="trial-info-btn"
type="primary"
size="small"
@click="handleSave"
>
<el-button class="trial-info-btn" type="primary" size="small" @click="handleSave">
{{ $t("trials:trials-myinfo:button:save") }}
</el-button>
</div>
@@ -24,7 +24,9 @@
<!-- 是否签署 -->
<el-form-item :label="$t('trials:self-attachment:table:isSign')">
<el-select v-model="searchData.IsSign" clearable style="width:120px;">
<el-option v-for="item of $d.YesOrNo" v-if="item.raw.ValueCN !== '无'" :label="item.label" :value="item.value" />
<template v-for="item of $d.YesOrNo">
<el-option v-if="item.raw.ValueCN !== '无'" :key="item.id" :label="item.label" :value="item.value" />
</template>
</el-select>
</el-form-item>
<el-form-item>
@@ -229,7 +231,7 @@ export default {
if (this.$route.query.isSign) {
this.searchData.IsSign = JSON.parse(this.$route.query.isSign)
}
this.getList()
// this.getList()
},
destroyed() {
if (this.timer) {
+196 -228
View File
@@ -5,79 +5,38 @@
<el-form :inline="true">
<!-- 受试者编号 -->
<el-form-item :label="$t('trials:uploadMonitor:table:subjectId')">
<el-input
v-model="searchData.SubjectCode"
clearable
style="width: 140px"
/>
<el-input v-model="searchData.SubjectCode" clearable style="width: 140px" />
</el-form-item>
<!-- 患者编号 -->
<el-form-item :label="$t('trials:uploadDicomList:table:pId')">
<el-input
v-model="searchData.PatientIdStr"
clearable
style="width: 140px"
/>
<el-input v-model="searchData.PatientIdStr" clearable style="width: 140px" />
</el-form-item>
<!-- 患者姓名 -->
<el-form-item :label="$t('trials:uploadDicomList:table:patientName')">
<el-input
v-model="searchData.PatientName"
clearable
style="width: 140px"
/>
<el-input v-model="searchData.PatientName" clearable style="width: 140px" />
</el-form-item>
<!-- 患者性别 -->
<el-form-item :label="$t('trials:subject:table:gender')">
<el-select
v-model="searchData.SubjectSex"
clearable
filterable
style="width: 150px"
>
<el-option
v-for="item of $d.Sex"
:key="item.id"
:label="item.label"
:value="item.value"
/>
<el-select v-model="searchData.SubjectSex" clearable filterable style="width: 150px">
<el-option v-for="item of $d.Sex" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 访视名称 -->
<el-form-item :label="$t('trials:uploadMonitor:table:visitName')">
<el-input
v-model="searchData.VisitName"
clearable
style="width: 140px"
/>
<el-input v-model="searchData.VisitName" clearable style="width: 140px" />
</el-form-item>
<!--拍片日期-->
<el-form-item :label="$t('trials:trials-panel:table:ScanDate')">
<el-date-picker
v-model="dateValue"
type="datetimerange"
range-separator="-"
<el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')"
clearable
:default-time="['00:00:00', '23:59:59']"
>
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" clearable
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<!--状态-->
<el-form-item :label="$t('trials:trials-list:table:status')">
<el-select
v-model="searchData.SubmitState"
clearable
filterable
style="width: 150px"
>
<el-option
v-for="item of $d.SubmitState"
:key="item.id"
:label="item.label"
:value="item.value"
/>
<el-select v-model="searchData.SubmitState" clearable filterable style="width: 150px">
<el-option v-for="item of $d.SubmitState" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
@@ -86,60 +45,39 @@
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<!-- 下载影像 -->
<el-button type="primary" @click="getDownloadSubjectVisitStudyInfo(multipleSelection)"
:disabled="multipleSelection.length <= 0" v-hasPermi="['trials:trials-panel:hirVisit:download']">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item>
</el-form>
</template>
<!-- 访视列表:default-sort="{ prop: 'SubmitTime', order: 'descending' }" -->
<template slot="main-container">
<el-table
ref="visitList"
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
>
<el-table ref="visitList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
@sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
<el-table-column type="selection" :selectable="isRowSelectable" width="55" v-if="hasPermi(['trials:trials-panel:hirVisit:download'])" />
<el-table-column min-width="20">
<template slot-scope="scope">
<i
v-if="
Number(scope.row.SubmitState) === 1 &&
scope.row.VisitLatestStudyTime
"
class="el-icon-warning-outline"
:title="$t('trials:hirVisit:tipMessage:tipOne')"
style="color: red"
></i>
<i v-if="
Number(scope.row.SubmitState) === 1 &&
scope.row.VisitLatestStudyTime
" class="el-icon-warning-outline" :title="$t('trials:hirVisit:tipMessage:tipOne')" style="color: red"></i>
</template>
</el-table-column>
<!-- 受试者编号 -->
<el-table-column
prop="SubjectCode"
:label="$t('trials:uploadMonitor:table:subjectId')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<el-table-column prop="SubjectCode" :label="$t('trials:uploadMonitor:table:subjectId')" show-overflow-tooltip
sortable="custom" min-width="120" />
<!-- 患者编号 -->
<el-table-column
prop="PatientList.PatientIdStr"
:label="$t('trials:uploadDicomList:table:pId')"
show-overflow-tooltip
>
<el-table-column prop="PatientList.PatientIdStr" :label="$t('trials:uploadDicomList:table:pId')"
show-overflow-tooltip>
<template slot-scope="scope">
<span
v-for="(item, index) in scope.row.PatientList"
:key="`${index}${item.PatientId}`"
>
<span v-for="(item, index) in scope.row.PatientList" :key="`${index}${item.PatientId}`">
{{
index === scope.row.PatientList.length - 1
? item.PatientIdStr
@@ -149,32 +87,18 @@
</template>
</el-table-column>
<!-- 患者姓名 -->
<el-table-column
prop="SubjectShortName"
:label="$t('trials:researchStaff:table:Name')"
show-overflow-tooltip
sortable="custom"
min-width="100"
/>
<el-table-column prop="SubjectShortName" :label="$t('trials:researchStaff:table:Name')" show-overflow-tooltip
sortable="custom" min-width="100" />
<!-- 性别 -->
<el-table-column
prop="SubjectSex"
:label="$t('trials:subject:table:gender')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="SubjectSex" :label="$t('trials:subject:table:gender')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<span>{{ $fd('Sex', scope.row.SubjectSex) }}</span>
</template>
</el-table-column>
<!-- 访视名称 -->
<el-table-column
prop="VisitName"
:label="$t('trials:uploadMonitor:table:visitName')"
show-overflow-tooltip
sortable="custom"
min-width="100"
>
<el-table-column prop="VisitName" :label="$t('trials:uploadMonitor:table:visitName')" show-overflow-tooltip
sortable="custom" min-width="100">
<template slot-scope="scope">
<el-button type="text" @click="handleOpenStudyDialog(scope.row)">
<span>{{ scope.row.VisitName }}</span>
@@ -182,39 +106,21 @@
</template>
</el-table-column>
<!-- 最早拍片日期 -->
<el-table-column
prop="VisitEarliestStudyTime"
:label="$t('trials:trials-panel:table:EarliestScanDate')"
show-overflow-tooltip
sortable="custom"
min-width="140"
/>
<el-table-column prop="VisitEarliestStudyTime" :label="$t('trials:trials-panel:table:EarliestScanDate')"
show-overflow-tooltip sortable="custom" min-width="140" />
<!-- 最晚拍片日期 -->
<el-table-column
prop="VisitLatestStudyTime"
:label="$t('trials:linkedRP:table:latestScanDate')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<el-table-column prop="VisitLatestStudyTime" :label="$t('trials:linkedRP:table:latestScanDate')"
show-overflow-tooltip sortable="custom" min-width="120" />
<!-- 状态 -->
<el-table-column
prop="SubmitState"
:label="$t('trials:trials-list:table:status')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="SubmitState" :label="$t('trials:trials-list:table:status')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<el-tag
:type="
Number(scope.row.SubmitState) === 0
? 'warning'
: Number(scope.row.SubmitState) === 1
? 'danger'
: ''
"
>{{ $fd('SubmitState', Number(scope.row.SubmitState)) }}</el-tag
>
<el-tag :type="Number(scope.row.SubmitState) === 0
? 'warning'
: Number(scope.row.SubmitState) === 1
? 'danger'
: ''
">{{ $fd('SubmitState', Number(scope.row.SubmitState)) }}</el-tag>
</template>
</el-table-column>
<!-- 打包状态 -->
@@ -240,94 +146,57 @@
</template>
</el-table-column> -->
<!-- 提交时间 -->
<el-table-column
prop="SubmitTime"
:label="$t('trials:crcUpload:table:submitTime')"
show-overflow-tooltip
min-width="100"
sortable="custom"
/>
<el-table-column prop="SubmitTime" :label="$t('trials:crcUpload:table:submitTime')" show-overflow-tooltip
min-width="100" sortable="custom" />
<!--操作-->
<el-table-column
:label="$t('common:action:action')"
min-width="200"
fixed="right"
v-if="
hasPermi([
'trials:trials-panel:hirVisit:edit',
'trials:trials-panel:hirVisit:submit',
'trials:trials-panel:hirVisit:remove',
'trials:trials-panel:hirVisit:download',
])
"
>
<el-table-column :label="$t('common:action:action')" min-width="200" fixed="right" v-if="
hasPermi([
'trials:trials-panel:hirVisit:edit',
'trials:trials-panel:hirVisit:submit',
'trials:trials-panel:hirVisit:remove',
'trials:trials-panel:hirVisit:download',
])
">
<template slot-scope="scope">
<!--修改检查-->
<el-button
circle
icon="el-icon-edit-outline"
v-hasPermi="['trials:trials-panel:hirVisit:edit']"
:title="$t('trials:hirVisit:button:editStudy')"
:disabled="Number(scope.row.SubmitState) > 1"
@click.stop="editStudy(scope.row)"
/>
<el-button circle icon="el-icon-edit-outline" v-hasPermi="['trials:trials-panel:hirVisit:edit']"
:title="$t('trials:hirVisit:button:editStudy')" :disabled="Number(scope.row.SubmitState) > 1"
@click.stop="editStudy(scope.row)" />
<!--提交-->
<el-button
circle
icon="el-icon-position"
v-hasPermi="['trials:trials-panel:hirVisit:submit']"
:disabled="
Number(scope.row.SubmitState) != 1 ||
!scope.row.VisitLatestStudyTime
"
:title="$t('common:button:submit')"
@click.stop="submit(scope.row)"
/>
<el-button circle icon="el-icon-position" v-hasPermi="['trials:trials-panel:hirVisit:submit']" :disabled="Number(scope.row.SubmitState) != 1 ||
!scope.row.VisitLatestStudyTime
" :title="$t('common:button:submit')" @click.stop="submit(scope.row)" />
<!--删除-->
<el-button
circle
icon="el-icon-delete"
v-hasPermi="['trials:trials-panel:hirVisit:remove']"
@click.stop="remove(scope.row)"
:disabled="Number(scope.row.SubmitState) > 1"
:title="$t('common:button:delete')"
/>
<el-button circle icon="el-icon-delete" v-hasPermi="['trials:trials-panel:hirVisit:remove']"
@click.stop="remove(scope.row)" :disabled="Number(scope.row.SubmitState) > 1"
:title="$t('common:button:delete')" />
<!--下载报告-->
<el-button
v-hasPermi="['trials:trials-panel:hirVisit:download']"
circle
:loading="downloading"
icon="el-icon-download"
:disabled="Number(scope.row.SubmitState) !== 2"
:title="$t('trials:reading:button:download')"
@click="getDownloadSubjectVisitStudyInfo(scope.row)"
/>
<el-button v-hasPermi="['trials:trials-panel:hirVisit:download']" circle :loading="downloading"
icon="el-icon-download" :disabled="Number(scope.row.SubmitState) !== 2"
:title="$t('trials:reading:button:download')" @click="getDownloadSubjectVisitStudyInfo([scope.row])" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</template>
<!--修改检查-->
<editStudyList
:visible.sync="editStudyVisible"
:data="editStudyData"
v-if="editStudyVisible"
@getList="getList"
/>
<editStudyList :visible.sync="editStudyVisible" :data="editStudyData" v-if="editStudyVisible" @getList="getList" />
<!--访视详情-->
<visitInfo
v-if="visitVisible"
:visible.sync="visitVisible"
:rowData="rowData"
/>
<visitInfo v-if="visitVisible" :visible.sync="visitVisible" :rowData="rowData" />
<!-- <el-dialog :title="$t('dialog:title:downLoadProgress')" :visible.sync="downloadVisible" width="35%"
:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
<div v-if="downloadType == 'downLoad' || downloadType == 'start'">
<span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<span>{{ speed }}</span>
<el-progress :percentage="percentage * 1"></el-progress>
</div>
<div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span>
</div>
</el-dialog> -->
</BaseContainer>
</template>
<script>
@@ -339,8 +208,11 @@ import { deleteSubjectVisit } from '@/api/trials'
import { getPatientSubejctVisitList } from '@/api/trials/visit.js'
import { submitVisitStudyBinding } from '@/api/inspection.js'
import { downLoadFile } from '@/utils/stream.js'
import { getToken } from '@/utils/auth'
// import * as signalR from '@microsoft/signalr'
import {
getDownloadSubjectVisitStudyInfo,
VisitImageDownload,
downloadImageSuccess,
} from '@/api/trials.js'
const defaultSearchData = () => {
@@ -389,6 +261,12 @@ export default {
//
downloading: false,
downloadId: null,
downloadVisible: false,
downloadType: '',
percentage: 0,
downLoadImageCount: 0,
speed: '0KB/s',
multipleSelection: []
}
},
created() {
@@ -398,7 +276,59 @@ export default {
}
this.getList()
},
mounted() {
// let connection = new signalR.HubConnectionBuilder()
// .withUrl("/DownloadHub", { accessTokenFactory: () => getToken() })
// .configureLogging(signalR.LogLevel.Information)
// .withAutomaticReconnect()
// .build()
// connection.start()
// connection.on("ReceivProgressAsync", (id, obj) => {
// console.log(obj)
// this.speed = obj.speed
// this.onUploadProgress(id, obj.sizePercent, 'downLoad')
// });
},
methods: {
handleSelectionChange(val) {
this.multipleSelection = val;
},
isRowSelectable(row, index) {
return row.SubmitState === 2
},
handleClose(done) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
this.downloadId = null
done()
},
generate() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async onUploadProgress(id, num, type = 'start') {
if (id !== this.downloadId) return false
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.percentage = num
}
if (num >= 100) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
}
},
//
handleSearch() {
this.getList()
@@ -517,20 +447,54 @@ export default {
}
},
//
async getDownloadSubjectVisitStudyInfo(row) {
async getDownloadSubjectVisitStudyInfo(arr) {
if (this.downloading) return
try {
let data = {
SubjectVisitId: row.SubjectVisitId,
// SubjectVisitId: row.SourceSubjectVisitId,
SubjectVisitIdList: arr.map(item => item.SubjectVisitId),
TrialId: this.$route.query.trialId,
}
this.downloading = true
let res = await getDownloadSubjectVisitStudyInfo(data)
this.downloading = false
if (res.IsSuccess) {
this.downloadId = res.OtherInfo
this.downloadImage(res.Result)
this.downloadId = this.generate()
data.CurrentNoticeId = this.downloadId
// this.onUploadProgress(this.downloadId)
// this.downloading = true
let params = null
data.SubjectVisitIdList.forEach(item => {
if (!params) {
params = `SubjectVisitIdList=${item}`
} else {
params += `&SubjectVisitIdList=${item}`
}
})
// data.ScpStudyIdList.forEach(item => {
// if (!params) {
// params = `ScpStudyIdList=${item}`
// } else {
// params += `&ScpStudyIdList=${item}`
// }
// })
if (!params) {
params = `CurrentNoticeId=${this.downloadId}`
} else {
params += `&CurrentNoticeId=${this.downloadId}`
}
params += `&TrialId=${this.$route.query.trialId}`
if (params) {
params += `&access_token=${getToken()}`
let url = `/api/download/VisitImageDownload?${params}`
// let url = `http://106.14.89.110:30021/download/DownloadBigFileBatch?fileName=Test_HIR_New_log.ldf`
let a = document.createElement('a')
a.href = url
a.click()
a = null
}
// await VisitImageDownload(data)
// this.downloading = false
// if (res.IsSuccess) {
// this.downloadId = res.OtherInfo
// this.downloadImage(res.Result)
// }
} catch (err) {
this.downloading = false
console.log(err)
@@ -564,11 +528,9 @@ export default {
series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${
study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${
series.Modality
}/${fileName}`,
name: `${data.SubjectCode}_${data.VisitName}/${study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
@@ -595,3 +557,9 @@ export default {
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-progress {
display: flex;
align-items: center;
}
</style>
@@ -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="position:relative;"
class="cornerstone-element"
@mouseup="sliderMouseup"
@contextmenu.prevent="onContextmenu"
>
<div id="canvas" ref="canvas" v-loading="loading" element-loading-text="Loading..."
element-loading-background="rgba(0, 0, 0, 0.8)" style="position:relative;" class="cornerstone-element"
@mouseup="sliderMouseup" @contextmenu.prevent="onContextmenu">
<!-- 临床数据 -->
<div v-if="stack.isExistsClinicalData" class="info-cd" @click.stop="handleViewCD($event)">
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:clinicalData')" placement="bottom">
@@ -18,46 +10,40 @@
</div>
<!-- 切换访视 -->
<div
v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
class="info-visit"
@dblclick.stop="preventDefault($event)"
>
<div
class="arrw_div_wrapper"
:style="{cursor:stack.visitTaskNum <= minVistNum?'not-allowed':'pointer',color:stack.visitTaskNum <= minVistNum?'#888':'#fff'}"
@click.stop.prevent="toggleSeries($event,-1)"
@dblclick.stop="preventDefault($event)"
>
<div v-if="stack.imageRendered && isReadingTaskViewInOrder === 1" class="info-visit"
@dblclick.stop="preventDefault($event)">
<div class="arrw_div_wrapper"
:style="{ cursor: stack.visitTaskNum <= minVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum <= minVistNum ? '#888' : '#fff' }"
@click.stop.prevent="toggleSeries($event, -1)" @dblclick.stop="preventDefault($event)">
<i class="el-icon-caret-left" />
</div>
<div class="blind_name_wrapper">
{{ stack.taskBlindName }}
</div>
<div
class="arrw_div_wrapper"
:style="{cursor:stack.visitTaskNum >= maxVistNum?'not-allowed':'pointer',color:stack.visitTaskNum >= maxVistNum?'#888':'#fff'}"
@click.stop.prevent="toggleSeries($event,1)"
@dblclick.stop="preventDefault($event)"
>
<div class="arrw_div_wrapper"
:style="{ cursor: stack.visitTaskNum >= maxVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum >= maxVistNum ? '#888' : '#fff' }"
@click.stop.prevent="toggleSeries($event, 1)" @dblclick.stop="preventDefault($event)">
<i class="el-icon-caret-right" />
</div>
</div>
<div class="info-series">
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2>
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{
stack.taskBlindName }}</h2>
<div v-show="dicomInfo.series">Series: #{{ dicomInfo.series }}</div>
<div>Image: #{{ dicomInfo.frame }}</div>
<div>{{ dicomInfo.modality }}</div>
</div>
<div class="info-image">
<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)">
SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.suv.toFixed(3) :mousePosition.suv.toFixed(digitPlaces) }}
SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.suv.toFixed(3) : mousePosition.suv.toFixed(digitPlaces) }}
</div>
<div v-else-if="mousePosition.mo">
Density: {{ mousePosition.mo }}
@@ -75,14 +61,20 @@
<div class="info-subject">
<div>{{ stack.description }}</div>
<!-- <div>{{ dicomInfo.hospital }}</div> -->
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
<div v-if="dicomInfo.pid">{{ dicomInfo.pid }}</div>
<div v-if="dicomInfo.patientName">{{ dicomInfo.patientName }}</div>
<!-- <div>{{ subjectCode }}</div> -->
<!-- <div>{{ dicomInfo.sex }} {{ dicomInfo.age }}</div> -->
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> -->
<div v-if="dicomInfo.modality">{{ dicomInfo.modality }}</div>
<div v-if="dicomInfo.time">{{ dicomInfo.time }}</div>
</div>
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 140px);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" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event)" />
<div ref="sliderBox" class="my_slider_box"
style="position: absolute;right: 1px;height: calc(100% - 140px);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"
@click.stop.prevent="() => { return }" @mousedown.stop="sliderMousedown($event)" />
</div>
<div style="position: absolute;left: 50%;top: 30px;color: #f44336;transform: translateX(-50%);">
{{ markers.top }}
@@ -117,7 +109,7 @@
</div>
</template>
<style>
.my_slider_box:after{
.my_slider_box:after {
content: '';
position: absolute;
bottom: -20px;
@@ -152,6 +144,7 @@ import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/too
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'
// import calculateLongestAndShortestDiameters from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/calculateLongestAndShortestDiameters'
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
import { convertBytes } from '@/utils/dicom-character-set'
cornerstoneTools.external.cornerstone = cornerstone
cornerstoneTools.external.Hammer = Hammer
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
@@ -299,7 +292,9 @@ export default {
],
scrollSyncInfo: { offset: 0 },
hideMeasureArr: []
hideMeasureArr: [],
IsCriticalSequence: false,
isInitWwwc: true
}
},
@@ -510,6 +505,11 @@ export default {
cornerstone.resize(this.canvas)
},
mouseMove(e) {
if (this.IsCriticalSequence) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
}
const { element, image, currentPoints } = e.detail
const x = Math.round(currentPoints.image.x)
const y = Math.round(currentPoints.image.y)
@@ -549,7 +549,7 @@ export default {
mouseUp(e) {
// console.log('mouseUp')
if (this.readingTaskState >= 2) return
if (this.readingTaskState >= 2 || this.IsCriticalSequence) return
this.image = e.detail.image
this.getToolStateInfo(e)
},
@@ -560,7 +560,7 @@ export default {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
} else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional' && this.readingTaskState < 2) {
} else if ((this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional') && this.readingTaskState < 2) {
if (!e.detail.image.columnPixelSpacing || !e.detail.image.rowPixelSpacing) {
// ''
this.$confirm(this.$t('trials:reading:warnning:msg56'), '', {
@@ -568,11 +568,36 @@ export default {
type: 'warning'
}).then(() => {
}).catch(() => {})
}).catch(() => { })
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
}
if (this.IsCriticalSequence) {
// ''
this.$confirm(this.$t('trials:reading:warnning:msg99'), '', {
showCancelButton: false,
type: 'warning'
}).then(() => {
}).catch(() => { })
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
}
} else if (this.IsCriticalSequence) {
if (this.activeToolName) {
// ''
this.$confirm(this.$t('trials:reading:warnning:msg99'), '', {
showCancelButton: false,
type: 'warning'
}).then(() => {
}).catch(() => { })
}
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
}
},
pointNearTool(e) {
@@ -916,7 +941,7 @@ export default {
})
},
setMeasureDataVisible() {
if (this.readingTaskState >= 2) return
if (this.readingTaskState >= 2 || this.IsCriticalSequence) return
var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image
const imageInfo = this.getInstanceInfo(imageId)
@@ -981,6 +1006,7 @@ export default {
}
},
mouseClick(e) {
if (this.IsCriticalSequence) return false
const { element, currentPoints, image, viewport } = e.detail
var imageId = image.imageId
const imageInfo = this.getInstanceInfo(imageId)
@@ -1038,6 +1064,13 @@ export default {
},
loadImageStack(dicomSeries) {
return new Promise(resolve => {
var idx = this.visitTaskList.findIndex(item => item.VisitTaskId === dicomSeries.visitTaskId)
if (!!~idx) {
this.IsCriticalSequence = this.visitTaskList[idx].StudyList[dicomSeries.studyIndex].IsCriticalSequence
} else {
this.IsCriticalSequence = false
}
this.isInitWwwc = true
this.isCurrentTask = dicomSeries.isCurrentTask
this.isBaseline = dicomSeries.isBaseLineTask
this.readingTaskState = dicomSeries.readingTaskState
@@ -1088,7 +1121,7 @@ export default {
var frame = imageInfo.frame
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
this.stack.instanceId = instanceId
const element = this.$refs.canvas
cornerstone.enable(element)
element.tabIndex = 0
@@ -1141,7 +1174,7 @@ export default {
// const scope = this
Array.from(toolButtons).forEach((toolBtn) => {
// Add the tool
// Add the tool
const toolName = toolBtn.getAttribute('data-tool')
const apiTool = cornerstoneTools[`${toolName}Tool`]
if (apiTool) {
@@ -1149,15 +1182,15 @@ export default {
if (!toolAlreadyAddedToElement) {
if (toolName === 'Length') {
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true }})
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true } })
} else if (toolName === 'Bidirectional') {
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true }})
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true } })
} else if (toolName === 'ArrowAnnotate') {
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
} else if (toolName === 'RectangleRoi') {
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
@@ -1183,10 +1216,10 @@ export default {
mouseButtonMask: 4
})
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
// }
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
// }
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
}
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
@@ -1218,9 +1251,24 @@ export default {
ToolStateManager.clearImageIdToolState(imageId)
e.detail.enabledElement.options = {}
var data = e.detail.image.data
const patientNameElement = data.elements.x00100010
const patientNameBytes = new Uint8Array(
data.byteArray.buffer,
patientNameElement ? patientNameElement.dataOffset : 0,
patientNameElement ? patientNameElement.length : 0
)
// dicom 2025.03.04
let SpecificCharacterSet = data.string('x00080005')
? data.string('x00080005').replace('ISO IR', 'ISO_IR')
: ''
const patientNameStr = convertBytes(
SpecificCharacterSet,
patientNameBytes
)
this.dicomInfo.hospital = data.string('x00080080')
// this.dicomInfo.pid = data.string('x00100020')
this.dicomInfo.pid = data.string('x00120040')
this.dicomInfo.pid = data.string('x00100020')
this.dicomInfo.patientName = patientNameStr
// this.dicomInfo.pid = data.string('x00120040')
this.dicomInfo.name = data.string('x00100010')
this.dicomInfo.age = data.string('x00101010')
this.dicomInfo.sex = data.string('x00100040')
@@ -1231,9 +1279,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')}*${data.uint16(
'x00280010'
)}`
@@ -1283,7 +1330,6 @@ export default {
// this.initWwc()
this.imageId = instanceId
}
this.stack.instanceId = instanceId
var viewport = e.detail.viewport
this.dicomInfo.wwwc = `${Math.round(
@@ -1301,6 +1347,9 @@ export default {
this.scrollSyncInfo.offset = 0
}
this.renderMeasuredData(e)
if (this.isInitWwwc) {
this.resetWwwc()
}
},
getOrientationMarker(element) {
const enabledElement = cornerstone.getEnabledElement(element)
@@ -1322,7 +1371,8 @@ export default {
this.setMarkers()
},
onMeasurementcompleted(e) {
if (this.readingTaskState >= 2) return
console.log(this.IsCriticalSequence, 'this.IsCriticalSequence')
if (this.readingTaskState >= 2 || this.IsCriticalSequence) return
var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport
@@ -1413,9 +1463,9 @@ export default {
var element = cornerstone.getEnabledElement(this.canvas)
const { rowPixelSpacing, colPixelSpacing } = this.getPixelSpacing(element.image)
const dx =
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
const dy =
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
const length = Math.sqrt(dx * dx + dy * dy)
return length.toFixed(this.digitPlaces)
@@ -1429,9 +1479,9 @@ export default {
if (imagePlane) {
return {
rowPixelSpacing:
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
colPixelSpacing:
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
}
}
@@ -1446,7 +1496,7 @@ export default {
onMeasurementmodified(e) {
//
// console.log('modified')
if (this.readingTaskState >= 2) return
if (this.readingTaskState >= 2 || this.IsCriticalSequence) return
const { measurementData, toolType } = e.detail
var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport
@@ -1482,7 +1532,7 @@ export default {
},
debounce(callback, delay) {
let timerId
return function() {
return function () {
clearTimeout(timerId)
timerId = setTimeout(() => {
callback.apply(this, arguments)
@@ -1640,7 +1690,7 @@ export default {
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
).data[0].loop = true
} else {
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
@@ -1652,6 +1702,7 @@ export default {
},
resetWwwc() {
this.isInitWwwc = true
this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas)
// viewport.invert = false
@@ -1663,6 +1714,7 @@ export default {
setWwwc(ww, wc) {
// console.log('setWwwc', ww, wc)
this.isInitWwwc = false
var viewport = cornerstone.getViewport(this.canvas)
viewport.voi.windowWidth = ww
viewport.voi.windowCenter = wc
@@ -1783,6 +1835,9 @@ export default {
// console.log(toolName)
// cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
// })
if (toolName === 'Wwwc') {
this.isInitWwwc = false
}
this.activeToolName = toolName
this.$nextTick(() => {
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))
@@ -1963,88 +2018,102 @@ export default {
</script>
<style lang="scss" scoped>
.context-menu-wrapper{
position: absolute;
ul{
list-style: none;
margin: 0px;
padding: 0px;
.context-menu-wrapper {
position: absolute;
ul {
list-style: none;
margin: 0px;
padding: 0px;
background: #343333;
color: #fff;
margin: 0;
border: 1px solid #2a2a2a;
border-radius: 3px;
height: auto;
min-height: 50px;
line-height: 1.5em;
width: 80px;
box-sizing: border-box;
}
.menu {
li {
padding: 2px 5px;
position: relative;
border-bottom: 1px solid #666;
div {
padding: 5px;
}
}
.submenu {
position: absolute;
left: 77px;
top: -1px;
background: #343333;
color: #fff;
margin: 0;
border: 1px solid #2a2a2a;
border-radius: 3px;
height: auto;
min-height: 50px;
line-height: 1.5em;
width:80px;
box-sizing: border-box;
}
.menu{
display: none;
li {
padding: 2px 5px;
position: relative;
border-bottom: 1px solid #666;
div{
div {
padding: 5px;
}
}
.submenu{
position: absolute;
left: 77px;
top: -1px;
background: #343333;
color: #fff;
display: none;
li {
padding: 2px 5px;
border-bottom: 1px solid #666;
div{
padding: 5px;
}
}
}
}
.menu li:hover{
background-color: #ff5722;
.submenu{
display:block;
}
}
.menu_active{
cursor: pointer;
}
.menu_disabled{
cursor: not-allowed;
}
}
.info-visit{
position: absolute;
left:50%;
top: 5px;
transform: translateX(-50%);
display: flex;
flex-direction: row;
.arrw_div_wrapper{
width: 20px;
height: 20px;
background-color: #3f3f3f;
text-align: center;
line-height: 20px;
border-radius: 10%;
}
.blind_name_wrapper{
height: 20px;
line-height: 20px;
background-color: #00000057;
color: #fff;
padding:0 10px;
font-size: 14px;
.menu li:hover {
background-color: #ff5722;
.submenu {
display: block;
}
}
.info-cd{
.menu_active {
cursor: pointer;
}
.menu_disabled {
cursor: not-allowed;
}
}
.info-visit {
position: absolute;
left: 50%;
top: 5px;
transform: translateX(-50%);
display: flex;
flex-direction: row;
.arrw_div_wrapper {
width: 20px;
height: 20px;
background-color: #3f3f3f;
text-align: center;
line-height: 20px;
border-radius: 10%;
}
.blind_name_wrapper {
height: 20px;
line-height: 20px;
background-color: #00000057;
color: #fff;
padding: 0 10px;
font-size: 14px;
}
}
.info-cd {
position: absolute;
left: 10px;
top: 5px;
@@ -2053,6 +2122,7 @@ export default {
font-size: 18px;
cursor: pointer;
}
.info-series {
position: absolute;
left: 10px;
@@ -2062,6 +2132,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-image {
position: absolute;
left: 10px;
@@ -2081,6 +2152,7 @@ export default {
font-size: 12px;
/* z-index: 1; */
}
.info-instance {
position: absolute;
right: 15px;
@@ -2113,6 +2185,7 @@ export default {
margin: 10px;
cursor: default;
}
.menu__item:hover {
color: #ff0000;
}
@@ -2132,11 +2205,12 @@ li:hover {
background-color: #e0e0e2;
color: white;
}
.msg-div {
position: absolute;
z-index: 10;
background-color: rgba(255, 255, 255, 0.5);
color: #000;
padding: 5px 20px;
}
position: absolute;
z-index: 10;
background-color: rgba(255, 255, 255, 0.5);
color: #000;
padding: 5px 20px;
}
</style>
File diff suppressed because it is too large Load Diff
@@ -50,6 +50,7 @@
:key="qs.Id"
:label="`${qs.QuestionName}`"
:prop="qs.Id"
:title="qs.Remark"
:rules="[
{ required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10)) && qs.Type!=='group' && qs.Type!=='summary',
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
@@ -497,6 +498,7 @@ export default {
let msg = this.$t('trials:reading:warnning:msg14')
// msg = msg.replace('xxx', this.tableQuestions[idx].QuestionName)
msg = msg.replace('xxx', this.tableQuestions[idx].MaxQuestionCount)
msg = msg.replace('yyy', this.$fd('CriterionType', this.CriterionType))
this.$confirm(msg, {
type: 'warning',
showCancelButton: false,
@@ -553,6 +555,7 @@ export default {
.then(async res => {
if (res.IsSuccess) {
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('getKeySeries')
}
loading.close()
resolve()
@@ -862,6 +865,7 @@ export default {
}
deleteReadingRowAnswer(param)
.then(async res => {
DicomEvent.$emit('getKeySeries')
resolve()
}).catch(() => {
})
@@ -2003,6 +2007,7 @@ export default {
this.$emit('close')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('setMeasuredToolsPassive')
DicomEvent.$emit('getKeySeries')
}
loading.close()
} catch (e) {
@@ -2106,6 +2111,7 @@ export default {
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
}
DicomEvent.$emit('refreshStudyListMeasureData')
DicomEvent.$emit('getKeySeries')
loading.close()
} catch (e) {
loading.close()
@@ -744,6 +744,7 @@ export default {
let msg = this.$t('trials:reading:warnning:msg14')
// msg = msg.replace('xxx', qs.QuestionName)
msg = msg.replace('xxx', qs.MaxQuestionCount)
msg = msg.replace('yyy', this.$fd('CriterionType', this.criterionType))
this.$confirm(msg, {
type: 'warning',
showCancelButton: false,
@@ -1103,6 +1104,7 @@ export default {
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
DicomEvent.$emit('showIRecistTip')
}
loading.close()
} catch (e) {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

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