Compare commits

...

307 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
wangxiaoshuang 0153644432 系统管理员创建账号,增加提示
continuous-integration/drone/push Build is passing
2025-07-17 10:09:10 +08:00
wangxiaoshuang 379bcc883c 阅片页面跳过阅片任务,阅片任务的跳过状态,只在当前阅片回合生效 2025-07-17 10:08:26 +08:00
wangxiaoshuang 15113fb976 1
continuous-integration/drone/push Build is passing
2025-06-06 11:26:29 +08:00
wangxiaoshuang 8795826d6b logo宽高改为配置
continuous-integration/drone/push Build is passing
2025-06-06 11:12:57 +08:00
wangxiaoshuang 898fcbc688 导出报告名称修改
continuous-integration/drone/push Build is passing
2025-06-06 09:22:21 +08:00
wangxiaoshuang e6b0d97e27 登录页样式调整
continuous-integration/drone/push Build is passing
2025-06-05 16:49:42 +08:00
wangxiaoshuang d59de26c66 logo图大小修改
continuous-integration/drone/push Build is passing
2025-06-05 16:27:56 +08:00
wangxiaoshuang d97ed7a999 1
continuous-integration/drone/push Build is passing
2025-05-30 16:59:26 +08:00
wangxiaoshuang d73a525b2a pacs修改默认查询
continuous-integration/drone/push Build is passing
2025-05-29 15:04:48 +08:00
wangxiaoshuang 2613d25788 项目授权
continuous-integration/drone/push Build is passing
2025-05-29 09:45:21 +08:00
wangxiaoshuang 8ed6fa466e 激活码新增查看功能
continuous-integration/drone/push Build is passing
2025-05-27 15:37:37 +08:00
wangxiaoshuang 223c567b17 阅片跟踪导出暂时屏蔽
continuous-integration/drone/push Build is passing
2025-05-14 16:16:29 +08:00
wangxiaoshuang bfa23dc007 稽查国际化修改
continuous-integration/drone/push Build is passing
2025-05-13 17:41:09 +08:00
wangxiaoshuang 042db393ca 账号锁定后,输入账号密码解锁,然后再操作其他页面,会重复弹出对话框。
continuous-integration/drone/push Build is passing
2025-04-25 10:36:50 +08:00
wangxiaoshuang c93dfc5d88 忘记密码修改
continuous-integration/drone/push Build is passing
2025-04-24 10:45:49 +08:00
wangxiaoshuang 69cde152bb 切换角色时my_usename更换
continuous-integration/drone/push Build is passing
2025-04-21 10:24:37 +08:00
wangxiaoshuang d103b056c9 项目详情授权按钮添加权限标识
continuous-integration/drone/push Build is passing
2025-04-18 13:42:48 +08:00
wangxiaoshuang ada99d0d57 1
continuous-integration/drone/push Build is failing
2025-04-17 16:39:03 +08:00
wangxiaoshuang ec9be3ceae usa样式修改
continuous-integration/drone/push Build is failing
2025-04-17 16:04:31 +08:00
wangxiaoshuang 1e45537adc 登录页新增配置文件下载
continuous-integration/drone/push Build is passing
2025-04-15 14:58:10 +08:00
wangxiaoshuang 3621d4448a token问题修复
continuous-integration/drone/push Build is passing
2025-04-01 17:43:28 +08:00
wangxiaoshuang 67e1ea542e 登录页从路由中获取token登录添加loading
continuous-integration/drone/push Build is passing
2025-04-01 16:00:48 +08:00
wangxiaoshuang 50b05afda0 1
continuous-integration/drone/push Build is passing
2025-04-01 15:38:09 +08:00
wangxiaoshuang 76252e50d1 登录页从路由中获取token登录
continuous-integration/drone/push Build is running
2025-04-01 15:35:16 +08:00
wangxiaoshuang 42eeda29d2 日期搜索框国际化
continuous-integration/drone/push Build is passing
2025-03-31 15:16:31 +08:00
wangxiaoshuang 42728a67d2 登录页测试环境开放国际化切换
continuous-integration/drone/push Build is passing
2025-03-31 14:52:47 +08:00
wangxiaoshuang 448d626fc0 样式调整
continuous-integration/drone/push Build is passing
2025-03-31 14:42:04 +08:00
wangxiaoshuang ed9a200ae0 部分页面国际化配置
continuous-integration/drone/push Build is passing
2025-03-31 11:51:19 +08:00
wangxiaoshuang 5d5370de88 部分页面国际化配置
continuous-integration/drone/push Build is passing
2025-03-31 11:15:31 +08:00
wangxiaoshuang 667631be5d 字体文件改为本地
continuous-integration/drone/push Build is passing
2025-03-28 13:38:26 +08:00
wangxiaoshuang b7c3ac6607 置换token
continuous-integration/drone/push Build is passing
2025-03-28 10:12:57 +08:00
wangxiaoshuang 7b1fd033b9 添加切换角色功能
continuous-integration/drone/push Build is passing
2025-03-28 09:29:32 +08:00
wangxiaoshuang a0d32a77ec 编辑医院增加是否默认字段
continuous-integration/drone/push Build is passing
2025-03-27 09:38:42 +08:00
wangxiaoshuang c6302e88c3 dicom ae添加是否支持多模态字段
continuous-integration/drone/push Build is passing
2025-03-25 15:42:54 +08:00
wangxiaoshuang 886d148b31 新增疗效评估报告
continuous-integration/drone/push Build is passing
2025-03-25 14:40:48 +08:00
wangxiaoshuang 3bfab54ef1 新增受试者正则修改
continuous-integration/drone/push Build is passing
2025-03-24 16:41:04 +08:00
wangxiaoshuang 4f38b77a53 pass按项目查询条件变更
continuous-integration/drone/push Build is passing
2025-03-24 16:06:01 +08:00
wangxiaoshuang 1ffb033013 pass按项目查询条件变更
continuous-integration/drone/push Build is passing
2025-03-24 15:59:12 +08:00
wangxiaoshuang 403e78f1da 登录页切换医院添加限制条件
continuous-integration/drone/push Build is passing
2025-03-24 10:50:45 +08:00
wangxiaoshuang 6d4705c0d4 Admin可以管理多个医院
continuous-integration/drone/push Build is passing
2025-03-21 15:12:53 +08:00
wangxiaoshuang 836d2ffc22 临床试验影像库中的患者影像可以查询新增检查,并可以从PACS拉取到影像库
continuous-integration/drone/push Build is passing
2025-03-21 11:08:52 +08:00
wangxiaoshuang 7254622c6d 列表默认的行数,都是20
continuous-integration/drone/push Build is passing
2025-03-21 09:46:23 +08:00
wangxiaoshuang 9942cde78a 推送记录默认展示20条
continuous-integration/drone/push Build is passing
2025-02-08 09:17:46 +08:00
wangxiaoshuang f71cd0e361 pacs拉取去除检查申请号查询
continuous-integration/drone/push Build is passing
2024-12-20 14:07:15 +08:00
wangxiaoshuang 5eddaf4300 pacs拉取新增检查申请号查询
continuous-integration/drone/push Build is passing
2024-12-20 13:10:20 +08:00
wangxiaoshuang 249e4cd5cc pacs拉取首次查询添加默认查询条件
continuous-integration/drone/push Build is passing
2024-12-20 10:52:40 +08:00
wangxiaoshuang 62023fea04 1
continuous-integration/drone/push Build is passing
2024-12-19 14:46:08 +08:00
wangxiaoshuang 576b99d185 pacs拉取选择AE信息头部展示
continuous-integration/drone/push Build is failing
2024-12-19 14:25:05 +08:00
wangxiaoshuang 8c45d239f8 pacs拉取时间选择器显示问题
continuous-integration/drone/push Build is passing
2024-12-19 13:23:21 +08:00
wangxiaoshuang b5402fff35 pacs拉取查询检查模态字段变更
continuous-integration/drone/push Build is passing
2024-12-19 13:08:22 +08:00
wangxiaoshuang f3b0c5def9 pacs存在图标遮挡问题
continuous-integration/drone/push Build is passing
2024-12-19 11:30:54 +08:00
wangxiaoshuang c949a0b6fb PACS拉取配置信息每次查询获取一次
continuous-integration/drone/push Build is passing
2024-12-19 10:35:32 +08:00
wangxiaoshuang e9cefc1157 pacs拉取问题修复
continuous-integration/drone/push Build is passing
2024-12-19 09:54:04 +08:00
wangxiaoshuang 098e3c888a pacs拉取问题修复
continuous-integration/drone/push Build is passing
2024-12-18 13:50:16 +08:00
wangxiaoshuang 3c15561485 pacs接收修改
continuous-integration/drone/push Build is passing
2024-12-17 17:16:56 +08:00
wangxiaoshuang 1dd21911e5 pacs拉取添加是否已拉取判断
continuous-integration/drone/push Build is passing
2024-12-13 17:35:30 +08:00
wangxiaoshuang beb96f272f pacs拉取批量
continuous-integration/drone/push Build is passing
2024-12-13 16:38:07 +08:00
wangxiaoshuang 46c64369d8 pacs拉取检查时间查询修改
continuous-integration/drone/push Build is passing
2024-12-13 16:14:07 +08:00
wangxiaoshuang 0942c32cba PACS影像拉取
continuous-integration/drone/push Build is passing
2024-12-13 13:29:31 +08:00
wangxiaoshuang 107d520266 项目详情接口报错处理
continuous-integration/drone/push Build is passing
2024-12-02 15:48:56 +08:00
wangxiaoshuang 6069e2657e qa通知菜单打开
continuous-integration/drone/push Build is passing
2024-11-29 18:07:38 +08:00
wangxiaoshuang afafce3dc9 授权更新修改
continuous-integration/drone/push Build is passing
2024-11-29 14:39:54 +08:00
wangxiaoshuang 0f57c44f45 激活页面路由屏蔽
continuous-integration/drone/push Build is passing
2024-11-28 13:58:26 +08:00
wangxiaoshuang 15309e77ba 1
continuous-integration/drone/push Build is passing
2024-11-28 13:52:12 +08:00
wangxiaoshuang 6c8014ac75 个人中心单位输入框取消提示语
continuous-integration/drone/push Build is passing
2024-11-28 13:43:19 +08:00
wangxiaoshuang 7239974a25 已阅、退回列表查询条件变更
continuous-integration/drone/push Build is passing
2024-11-28 10:54:36 +08:00
wangxiaoshuang e523e1d0a5 性别字典变更
continuous-integration/drone/push Build is passing
2024-11-28 09:38:08 +08:00
wangxiaoshuang 4aa1221006 用户单位信息逻辑更改
continuous-integration/drone/push Build is passing
2024-11-27 17:42:54 +08:00
wangxiaoshuang 8a55cfcad7 登录页oss配置请求问题
continuous-integration/drone/push Build is passing
2024-11-27 10:50:53 +08:00
wangxiaoshuang b8279e1f4c logo更改
continuous-integration/drone/push Build is passing
2024-11-26 16:04:30 +08:00
wangxiaoshuang d6f9b5cc7d 国际化修改弹窗查询
continuous-integration/drone/push Build is passing
2024-11-26 14:10:56 +08:00
wangxiaoshuang b8beac28c4 配置修改
continuous-integration/drone/push Build is passing
2024-11-25 17:31:12 +08:00
wangxiaoshuang 74a1f342bd 1
continuous-integration/drone/push Build is passing
2024-11-25 17:22:23 +08:00
wangxiaoshuang a3818c696f 版权信息修改
continuous-integration/drone/push Build is passing
2024-11-25 16:48:44 +08:00
wangxiaoshuang b5b4db84fc 版权信息修改
continuous-integration/drone/push Build is passing
2024-11-25 16:29:34 +08:00
caiyiling 277881a8d1 1
continuous-integration/drone/push Build is passing
2024-11-25 14:49:00 +08:00
caiyiling 72a7a09f44 下载模板bug修复
continuous-integration/drone/push Build is passing
2024-11-25 14:43:06 +08:00
caiyiling 98604a7684 导出接口同步
continuous-integration/drone/push Build is passing
2024-11-25 14:24:51 +08:00
caiyiling 21871f7948 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/hir_web into main
continuous-integration/drone/push Build is passing
2024-11-25 13:27:51 +08:00
caiyiling 5c1248ff93 阅片跟踪添加导出功能 2024-11-25 13:27:21 +08:00
wangxiaoshuang f0cb493a17 1
continuous-integration/drone/push Build is passing
2024-11-22 17:02:52 +08:00
wangxiaoshuang f5cdce04e4 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/hir_web
continuous-integration/drone/push Build is running
2024-11-22 17:00:22 +08:00
wangxiaoshuang bb4b0011ef 下载记录列表 2024-11-22 17:00:12 +08:00
159 changed files with 23541 additions and 11493 deletions
+1 -1
View File
@@ -46,4 +46,4 @@ VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs'
VUE_APP_OSS_PATH = '/test/dist'
VUE_APP_OSS_PATH = /hir_test/dist
+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:
+4 -2
View File
@@ -2,7 +2,7 @@
"name": "HICS",
"version": "1.0.0",
"scripts": {
"dev": "vue-cli-service serve --open",
"dev": "vue-cli-service serve --open --mode development",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build --mode prod",
"build:uat": "vue-cli-service build --mode uat",
@@ -38,10 +38,11 @@
"moment": "^2.27.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"node-sass": "^4.14.1",
"normalize.css": "7.0.0",
"normalize.css": "^8.0.1",
"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",
+12
View File
@@ -0,0 +1,12 @@
const WINDOW_CONFIG = {
hospital: '复旦大学附属肿瘤医院',
hospitalEN: '',
company: '武汉行藏科技有限公司',
companyEN: '',
logoScale: { // logo宽高比
login: 4, // height:60px
page: 3.4 // height:50px
}
}
// export default config
+1 -1
View File
@@ -28,7 +28,6 @@
</script>
<% } else { %>
<script>
console.log(2)
window.zzSessionStorage = {
setItem: (item, value) => {
return sessionStorage.setItem(item, value)
@@ -58,6 +57,7 @@
num = e.data
}
</script>
<script src="/config.js"></script>
</head>
<body>
<noscript>
+30
View File
@@ -0,0 +1,30 @@
影像双屏浏览设置
开启双屏显示具有浏览器相应权限,Chrome 和 Edge 浏览器的设置如下:
1、 Chrome 浏览器设置
点击地址栏左侧按钮,如图所示
点击网站设置,如图所示。
进入网站设置页面,向下滚动页面找到窗口管理,点击右侧下拉框并选择:
允许,如图所示。
1
返回网站,点击重新加载,页面刷新后再次点击阅片按钮即可进行双屏阅片。
2、 Microsoft Edge 浏览器
点击地址栏左侧按钮,如图所示。
2
点击此网站的权限,如图所示。
进入网站权限设置页面,向下滚动页面找到窗口管理,点击右侧下拉框并选
择:允许,如图所示。
3
返回网站,点击刷新,页面刷新后再次点击阅片按钮即可进行双屏阅片,如
图所示。
4
+183 -110
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,67 +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-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>
@@ -88,11 +82,12 @@
import {
batchAddOrUpdateFrontInternationalization,
getFrontInternationalizationList,
} from "@/api/dictionary/dictionary";
import Vue from "vue";
import i18n from "./lang";
} from '@/api/dictionary/dictionary'
import Vue from 'vue'
import i18n from './lang'
import { getHospital } from '@/api/hospital.js'
export default {
name: "App",
name: 'App',
data() {
return {
drawer: false,
@@ -100,15 +95,36 @@ 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);
this.$set(target, attr, e)
},
keyChange(v) {
if (this.key) {
@@ -116,69 +132,111 @@ 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 {
this.tableData = Object.assign([], this.arr);
this.tableData = Object.assign([], this.arr)
}
},
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() {
this.tableData = [];
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;
});
openI18n(ARRAY) {
this.tableData = []
this.il8nExternal = false
this.State = null
this.key = null
this.drawer = true
let arr = []
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);
});
return ~this.$path.indexOf(v.Code)
})
this.$path.forEach((v) => {
let o = tableData.find((a) => {
return a.Code === v;
});
return a.Code === v
})
if (o) {
arr.push(o);
arr.push(o)
} else {
arr.push({
Code: v,
Description: null,
Value: null,
ValueCN: null,
});
State: 0,
Version: this.$version.Version,
InternationalizationType: 0,
})
}
});
this.arr = arr;
})
this.arr = arr
if (this.key) {
this.tableData = Object.assign(
[],
@@ -188,25 +246,36 @@ export default {
~v.Value.indexOf(this.key) ||
~v.ValueCN.indexOf(this.key)
)
);
)
} else {
this.tableData = Object.assign([], this.arr);
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>
<style lang="scss">
.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;
@@ -215,18 +284,20 @@ export default {
display: block;
}
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
}
input[type="number"] {
input[type='number'] {
-moz-appearance: textfield !important;
}
.viewer-fixed.viewer-container {
z-index: 10000;
}
textarea {
white-space: break-spaces;
word-break: normal;
@@ -235,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;
}
+121 -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,3 +285,113 @@ 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({
url: `/Patient/getHIRHospitalList`,
method: 'post',
data: param
})
}
// 删除医院
export function deleteHIRHospital(id) {
return request({
url: `/Patient/deleteHIRHospital/${id}`,
method: 'delete',
})
}
// 新增或修改医院
export function addOrUpdateHIRHospital(data) {
return request({
url: `/Patient/addOrUpdateHIRHospital`,
method: 'post',
data
})
}
// 设置默认医院
export function updateDefaultHospital(params) {
return request({
url: `/Patient/updateDefaultHospital`,
method: 'put',
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'
})
}
+35
View File
@@ -178,3 +178,38 @@ export function showReadReport(data) {
data
})
}
// 预览肿瘤报告
export function showTumorReport(data) {
return request({
url: `/ReadingImageTask/getTumorEvaluationUrl`,
method: 'post',
data
})
}
export function getCommonEvaluationList_Export(data) {
return requestDownload({
url: `/ExcelExport/getCommonEvaluationList_Export`,
responseType: 'blob',
method: 'post',
data
})
}
export function getCommonJudgeRatioList_Export(data) {
return requestDownload({
url: `/ExcelExport/getCommonJudgeRatioList_Export`,
responseType: 'blob',
method: 'post',
data
})
}
// 导出国际化列表
export function GetInternationalizationList_Export(data) {
return requestDownload({
url: `/ExcelExport/GetInternationalizationList_Export`,
responseType: 'blob',
method: 'post',
data
})
}
+52
View File
@@ -1,5 +1,6 @@
// 检查管理
import request from '@/utils/request'
import requestDownload from '@/utils/request-download'
// 检查->患者列表
export function getPatientList(data) {
@@ -161,4 +162,55 @@ export function verifyTrialSubject(data) {
method: 'post',
data
})
}
// pacs可拉取列表
export function getCFindStudyList(data) {
return request({
url: '/Patient/getCFindStudyList',
method: 'post',
data
})
}
// pacs拉取
export function cmoveStudyList(data) {
return request({
url: '/Patient/cmoveStudyList',
method: 'post',
data
})
}
// pacs验证
export function cMoveVerify(data) {
return request({
url: '/Patient/cMoveVerify',
method: 'post',
data
})
}
// 获取参加项目
export function getUserJoinedTrialPatientList() {
return request({
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
})
}
+32
View File
@@ -240,3 +240,35 @@ export function resetReadingTask(param) {
data: param
})
}
export function clearSkipReadingCache(param) {
return request({
url: `/ReadingImageTask/clearSkipReadingCache`,
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
})
}
+43 -3
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,5 +160,44 @@ export function GetObjectStoreToken(params) {
method: 'get'
})
}
// 置换token
export function TJUserLoginInfo(params) {
return request({
url: `/user/TJUserLoginInfo`,
method: 'get',
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
})
}
Binary file not shown.
+3 -3
View File
@@ -8,9 +8,9 @@
@font-face {
font-family: "iconfont"; /* Project id 3270795 */
src: url('//at.alicdn.com/t/c/font_3270795_fcd739rubku.woff2?t=1673580130618') format('woff2'),
url('//at.alicdn.com/t/c/font_3270795_fcd739rubku.woff?t=1673580130618') format('woff'),
url('//at.alicdn.com/t/c/font_3270795_fcd739rubku.ttf?t=1673580130618') format('truetype');
src: url('./font_3270795_fcd739rubku.woff2') format('woff2'),
url('./font_3270795_fcd739rubku.woff') format('woff'),
url('./font_3270795_fcd739rubku.ttf') format('truetype');
}
.iconfont {
+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="开始日期"
end-placeholder="结束日期"
: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;
}
+1 -1
View File
@@ -29,7 +29,7 @@ export default {
}
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.box-body{
.search{
display: flex;
+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;
+37 -62
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,37 +104,27 @@ 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;
}
);
},
},
mounted() {
console.log(this.trialsRouter);
// console.log(this.trialsRouter);
var query = ``;
var url = window.location.href;
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 {
+104
View File
@@ -0,0 +1,104 @@
<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('toggleRole:tip:title')" center top="30vh"
:show-close="false" :before-close="cancel">
<template v-if="hasRole">
<el-radio-group v-model="form.userRoleId" class="roles">
<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>
</template>
<div v-else style="text-align: center">
{{ $t('toggleRole:tip:noRole') }}
</div>
<div slot="footer">
<!-- 取消 -->
<el-button size="small" @click="cancel()">
{{ $t('common:button:cancel') }}
</el-button>
<!-- 保存 -->
<el-button type="primary" size="small" @click="save" :disabled="saveDisabled" :loading="loading" v-if="hasRole">
{{ $t('common:button:confirm') }}
</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'toggleRole',
props: {
visible: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
},
data() {
return {
form: {
userRoleId: null,
},
}
},
created() {
this.form.userRoleId = zzSessionStorage.getItem('userId')
},
computed: {
roles() {
return this.$store.state.user.roles
},
hasRole() {
return this.roles && this.roles.length > 0
},
saveDisabled() {
return this.form.userRoleId === zzSessionStorage.getItem('userId')
},
},
methods: {
cancel() {
this.$emit('update:visible', false)
this.$emit('cancel')
},
async save() {
try {
if (!this.form.userRoleId)
return this.$message.warning(this.$t('toggleRole:ruleMessage:select'))
zzSessionStorage.removeItem('lastWorkbench')
this.$emit('save', this.form.userRoleId)
} catch (err) {
console.log(err)
}
},
},
}
</script>
<style lang="scss" scoped>
.roles {
max-width: 365px;
width: fit-content;
display: flex;
align-content: center;
// justify-content: center;
flex-wrap: wrap;
margin: auto;
}
::v-deep .el-radio__original {
display: none !important;
/* 隐藏原生 radio 输入,但仍然允许交互 */
}
::v-deep.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner {
box-shadow: none !important;
}
.el-radio {
width: 60px;
}
</style>
+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
}
}
+90 -6
View File
@@ -2,11 +2,7 @@
<div class="navbar navbar-flex-wrapper">
<div class="leftMenu">
<div class="navbar-flex-wrapper">
<hamburger
:is-active="sidebar.opened"
class="hamburger-container"
@toggleClick="toggleSideBar"
/>
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb class="breadcrumb-container" />
</div>
@@ -36,6 +32,12 @@
<!-- <el-dropdown-item>
<span style="display:block;" @click="account">Account</span>
</el-dropdown-item> -->
<!-- 切换角色 -->
<el-dropdown-item divided v-if="hasRole">
<span style="display: block" @click="openToggleRole">{{
$t('system:navbar:button:toggleRole')
}}</span>
</el-dropdown-item>
<el-dropdown-item divided>
<span style="display: block" @click="logout">{{
$t("trials:trials-myinfo:button:loginout")
@@ -46,6 +48,8 @@
</div>
</div>
</div>
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
@save="loginByRole" />
</div>
</template>
@@ -54,27 +58,100 @@ import { mapGetters, mapMutations } from "vuex";
import Breadcrumb from "@/components/Breadcrumb";
import Hamburger from "@/components/Hamburger";
import Screenfull from "@/components/Screenfull";
import { resetRouter } from '@/router'
import toggleRole from '@/components/toggleRole'
export default {
components: {
Breadcrumb,
Hamburger,
Screenfull,
toggleRole
},
data() {
return {
isReviewer: false,
userTypeShortName: zzSessionStorage.getItem("userTypeShortName"),
toggleRoleVisible: false,
toggleRoleLoading: false
};
},
computed: {
...mapGetters(["sidebar", "name", "device"]),
roles() {
return this.$store.state.user.roles
},
hasRole() {
return this.roles && this.roles.length > 1
},
},
created() {
this.isReviewer = JSON.parse(zzSessionStorage.getItem("IsReviewer"));
this.$store.dispatch('user/getUserInfo')
},
methods: {
...mapMutations({ setLanguage: "lang/setLanguage" }),
openToggleRole() {
this.$store.dispatch('user/getUserInfo').then((res) => {
this.toggleRoleVisible = true
})
},
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', { userRoleId })
.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: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)
}
this.toggleRoleVisible = false
this.toggleRoleLoading = false
this.$EventBus.$emit('reload')
} else {
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
this.toggleRoleLoading = false
this.$message.warning(this.$t('login:message:login2'))
}
})
.catch((err) => {
console.log(err)
this.toggleRoleLoading = false
})
} else {
this.toggleRoleLoading = false
}
})
.catch(() => {
this.toggleRoleLoading = false
})
},
toggleSideBar() {
this.$store.dispatch("app/toggleSideBar");
},
@@ -106,12 +183,14 @@ export default {
flex-direction: row;
justify-content: space-between;
}
.navbar {
height: 50px;
overflow: hidden;
// position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.hamburger-container {
line-height: 46px;
height: 100%;
@@ -133,6 +212,7 @@ export default {
// float: right;
height: 100%;
line-height: 50px;
// position: relative;
&:focus {
outline: none;
@@ -159,6 +239,7 @@ export default {
.avatar-container {
display: inline-block;
margin-right: 200px;
.user-avatar {
margin-top: 5px;
width: 40px;
@@ -166,16 +247,19 @@ export default {
border-radius: 10px;
}
}
.dropdown-container {
// margin-left: 30px;
// position: absolute;
// right: 20px;
// top: 0px;
cursor: pointer;
.el-icon-caret-bottom {
font-size: 12px;
}
}
.el-dropdown-link {
color: #999c9e;
cursor: pointer;
+43 -13
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'
@@ -101,7 +101,7 @@ Vue.prototype.resetForm = resetForm
Vue.prototype.selectDictLabel = selectDictLabel
// Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.$EventBus = new Vue()
Vue.prototype.$getObjectName = (url) => {
// console.log(url,'url')
// console.log(Vue.prototype.OSSclientConfig.viewEndpoint,'url')
@@ -129,7 +129,7 @@ Vue.prototype.getGuid = (text) => {
return `${t4 + t3 + t2 + t1}-${t6 + t5}-${t8 + t7}-${t9}-${t10}`
}
///50350000-3e2c-0016-eb4c-08db926b69d6/Image/84410000-3e10-0016-d156-08da242403fe/50350000-3e2c-0016-414e-08db926d9135/50350000-3e2c-0016-fd9d-08db926d9137/1.2.156.110002.21.2019.1.9.84822154.1/1.3.12.2.1107.5.1.4.73793.30000019010509500386600308609/1.3.12.2.1107.5.1.4.73793.30000019010509500386600308616/7fba7d7e-b3b3-d989-fa54-82e41f87a6ed
Vue.prototype.getGuid('1.2.156.110002.21.2019.1.9.84822154.11.3.12.2.1107.5.1.4.73793.300000190105095003866003086091.3.12.2.1107.5.1.4.73793.3000001901050950038660030861650350000-3e2c-0016-eb4c-08db926b69d6')
// Vue.prototype.getGuid('1.2.156.110002.21.2019.1.9.84822154.11.3.12.2.1107.5.1.4.73793.300000190105095003866003086091.3.12.2.1107.5.1.4.73793.3000001901050950038660030861650350000-3e2c-0016-eb4c-08db926b69d6')
//7fba7d7e-b3b3-d989-fa54-82e41f87a6ed
Vue.prototype.$validatePassword = (rule, value, callback) => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
@@ -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' || 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,22 +355,35 @@ 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' || 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
}
_vm.$store.dispatch('user/logout').then(res => {
window.location.href = `/login`
// window.location.href = `/login`
try {
if (_vm.$msgbox && _vm.$msgbox.close) {
_vm.$msgbox.close();
}
} catch (err) {
console.log(err)
}
isOpen = false
isLock = null
zzSessionStorage.removeItem('isLock')
router.push("/login")
}).then(() => {
_vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
type: 'warning',
})
})
_vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
type: 'warning',
})
} : () => { }, 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') {
@@ -375,11 +405,11 @@ async function VueInit() {
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
if (!_vm.unlock.my_username) {
_vm.$alert(lang === 'zh' ? '请输入您的用户名解锁' : 'Please enter your user name to unlock.')
_vm.$message.warning(lang === 'zh' ? '请输入您的用户名解锁' : 'Please enter your user name to unlock.')
return
}
if (!_vm.unlock.my_password) {
_vm.$alert(lang === 'zh' ? '请输入您的密码解锁' : 'Please enter the correct password to unlock.')
_vm.$message.warning(lang === 'zh' ? '请输入您的密码解锁' : 'Please enter the correct password to unlock.')
return
}
var my_username = zzSessionStorage.getItem('my_username')
+42 -16
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,16 +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') {
await this.$store.dispatch('user/logout')
OSSclient()
await OSSclient()
await store.dispatch('user/logout')
}
if (to.path === '/ReviewersResearchForm') {
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()
@@ -52,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}`)
@@ -66,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?`)
+11 -5
View File
@@ -221,17 +221,23 @@ export const constantRoutes = [
hidden: true,
component: () => import('@/views/trials/trials-panel/setting/reading-unit/preview')
},
{
path: '/activate',
component: () => import('@/views/trials/trials-list/components/activate-page.vue'),
hidden: true
},
// {
// path: '/activate',
// component: () => import('@/views/trials/trials-list/components/activate-page.vue'),
// hidden: true
// },
// {
// path: '/audit',
// name: 'audit',
// 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)
+160 -36
View File
@@ -1,28 +1,35 @@
import { getToken, setToken, removeToken, setName, removeName } from '@/utils/auth'
import { login, getUserMenuTree, getUserPermissions } 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'
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
isTestUser: false,
roles: []
}
}
const state = getDefaultState()
const mutations = {
SET_ROLES: (state, roles) => {
state.roles = roles
},
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
@@ -34,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
},
@@ -49,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) {
@@ -78,22 +95,34 @@ const mutations = {
}
const actions = {
setRoles({ commit }, roles) {
commit('SET_ROLES', roles)
},
// 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)
}
@@ -103,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)
}
@@ -135,12 +163,78 @@ const actions = {
})
})
},
loginByToken({ commit }, Token) {
return new Promise((resolve, reject) => {
TJUserLoginInfo(Token).then(async response => {
if (response.IsSuccess) {
zzSessionStorage.removeItem('lastWorkbench')
const data = response.Result
commit('SET_TOKEN', response.OtherInfo)
setToken(response.OtherInfo)
commit('SET_ROLES', data)
resolve(data)
} else {
reject(response.ErrorMessage)
}
}).catch(() => {
reject()
})
})
},
loginByRole({ commit }, userInfo) {
const { userRoleId } = userInfo
let params = {
userRoleId
}
return new Promise((resolve, reject) => {
loginSelectUserRole(params).then(async response => {
if (response.IsSuccess) {
const data = response.Result
try {
commit('SET_TOKEN', data)
setToken(data)
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)
zzSessionStorage.setItem('userTypeShortName', user.userTypeShortName)
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()
commit('SET_TREE', menuTree.Result)
commit('SET_PERMISSIONS', permissions.Result)
zzSessionStorage.setItem('newTree', JSON.stringify(menuTree.Result))
zzSessionStorage.setItem('permissions', JSON.stringify(permissions.Result))
zzSessionStorage.removeItem('lastWorkbench')
} catch (e) {
console.log(e)
}
resolve(response.Result)
} else {
reject(response.ErrorMessage)
}
}).catch(() => {
reject()
})
})
},
setTree({ commit }, tree) {
commit('SET_TREE', tree)
},
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)
},
@@ -159,34 +253,64 @@ 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('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)
},
// 获取用户信息
getUserInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getUser().then(res => {
if (res.Result) {
commit('SET_ROLES', res.Result.AccountList)
}
resolve(res.Result)
}).catch(err => {
reject(err)
})
})
},
// remove token
resetToken({ commit }) {
return new Promise(resolve => {
+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()
+19 -9
View File
@@ -2,7 +2,9 @@ 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
const service = axios.create({
baseURL: '/api',
@@ -24,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')) {
@@ -60,7 +62,7 @@ service.interceptors.response.use(
type: 'warning',
showCancelButton: false,
callback: action => {
if(res.Code === 6) {
if (res.Code === 6) {
window.close()
}
}
@@ -75,12 +77,20 @@ service.interceptors.response.use(
var message = ''
if (error && error.response) {
const status = error.response.status
if (error.response.data && error.response.data.Code === -1) {
if (error.response.data && (error.response.data.Code === -1 || error.response.data.Code === -2)) {
store.dispatch('user/logout').then(() => {
let _vm = ROUTER.default.app
try {
if (_vm.$msgbox && _vm.$msgbox.close) {
_vm.$msgbox.close();
}
} catch (err) {
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) {
@@ -110,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)
+75 -112
View File
@@ -3,98 +3,57 @@
<!-- Reset Password -->
<el-page-header :content="$t('passwordReset:title:reset')" @back="goBack" />
<div class="box-wrapper">
<el-form
ref="resetForm"
v-loading="formLoading"
:model="form"
label-width="150px"
:rules="rules"
class="demo-ruleForm"
size="small"
>
<el-form ref="resetForm" v-loading="formLoading" :model="form" label-width="150px" :rules="rules"
class="demo-ruleForm" size="small">
<!-- 邮箱 -->
<el-form-item
:label="$t('passwordReset:form:email')"
prop="EmailOrPhone"
>
<el-input
v-model="form.EmailOrPhone"
autocomplete="off"
@change="handleEmailChange"
v-if="!IsCanConnectInternet"
/>
<el-form-item :label="$t('passwordReset:form:email')" prop="EmailOrPhone">
<el-input v-model="form.EmailOrPhone" autocomplete="off" @change="handleEmailChange"
v-if="!IsCanConnectInternet" />
<template v-else>
<el-col :span="18">
<el-input
v-model="form.EmailOrPhone"
autocomplete="off"
@change="handleEmailChange"
/>
<el-input v-model="form.EmailOrPhone" autocomplete="off" @change="handleEmailChange" />
</el-col>
<el-col :span="6" style="text-align: right">
<el-button
size="small"
type="primary"
style="width: 80%"
:disabled="sendDisabled"
@click="handleSendCode"
>{{ sendTitle }}</el-button
>
<el-button size="small" type="primary" style="width: 80%" :disabled="sendDisabled"
@click="handleSendCode">{{ sendTitle }}</el-button>
</el-col>
</template>
</el-form-item>
<!-- 验证码 -->
<el-form-item
:label="
!IsCanConnectInternet
? $t('trials:researchForm:form:checkCode')
: $t('trials:researchForm:form:verifyCode')
"
required
>
<el-form-item :label="!IsCanConnectInternet
? $t('trials:researchForm:form:checkCode')
: $t('trials:researchForm:form:verifyCode')
" required>
<el-col :span="18">
<el-form-item prop="VerificationCode">
<el-input v-model="form.VerificationCode" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="6" style="text-align: right">
<i
:title="
isVerify === null
? $t('passwordReset:button:verify')
: isVerify
? $t('passwordReset:button:verifySuccess')
: $t('passwordReset:button:Failed')
"
:class="
isVerify === null
? 'el-icon-question'
: isVerify
<i :title="isVerify === null
? $t('passwordReset:button:verify')
: isVerify
? $t('passwordReset:button:verifySuccess')
: $t('passwordReset:button:Failed')
" :class="isVerify === null
? 'el-icon-question'
: isVerify
? 'el-icon-success'
: 'el-icon-error'
"
:style="{
marginRight: '5px',
color:
isVerify === null
? '#909399'
: isVerify
? '#67c23a'
: '#f56c6c',
}"
></i>
" :style="{
marginRight: '5px',
color:
isVerify === null
? '#909399'
: isVerify
? '#67c23a'
: '#f56c6c',
}"></i>
<!-- 校验 -->
<el-button
size="small"
type="primary"
:style="{
width: '80%',
}"
:disabled="
form.VerificationCode === '' || form.EmailOrPhone === ''
"
@click="verifyCode"
>
<el-button size="small" type="primary" :style="{
width: '80%',
}" :disabled="form.VerificationCode === '' || form.EmailOrPhone === ''
" @click="verifyCode">
{{ $t("passwordReset:button:verify") }}
</el-button>
</el-col>
@@ -104,55 +63,35 @@
</el-form-item>
<!-- 用户名 -->
<el-form-item :label="$t('passwordReset:form:userName')" prop="UserId">
<el-select
v-model="form.UserId"
clearable
filterable
style="width: 100%"
@change="handleUserChange"
>
<el-option
v-for="item of users"
:key="item.UserId"
:label="item.UserName"
:value="item.UserId"
>
<span :title="userMsg">{{ userMsg }}</span>
<!-- <el-select v-model="form.UserId" clearable filterable style="width: 100%" @change="handleUserChange">
<el-option v-for="item of users" :key="item.UserId" :label="item.UserName" :value="item.UserId">
<span style="float: left">{{ item.UserName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{
item.UserType
}}</span>
</el-option>
</el-select>
</el-select> -->
</el-form-item>
<!-- 用户类型 -->
<el-form-item
<!-- <el-form-item
v-if="form.UserId"
:label="$t('passwordReset:form:userType')"
>
<el-input v-model="form.UserType" disabled />
</el-form-item>
</el-form-item> -->
<!-- 新密码 -->
<el-form-item
class="my_new_pwd"
:label="$t('passwordReset:form:password')"
prop="NewPwd"
style="position: relative"
>
<el-form-item class="my_new_pwd" :label="$t('passwordReset:form:password')" prop="NewPwd"
style="position: relative">
<el-input v-model="form.NewPwd" show-password autocomplete="off" />
<span style="position: absolute; right: -30px">
<el-tooltip
:content="$t('passwordReset:form:passwordtip')"
placement="top"
>
<el-tooltip :content="$t('passwordReset:form:passwordtip')" placement="top">
<i class="el-icon-question" />
</el-tooltip>
</span>
</el-form-item>
<!-- 确认密码 -->
<el-form-item
:label="$t('passwordReset:form:confirmPassword')"
prop="CheckPass"
>
<el-form-item :label="$t('passwordReset:form:confirmPassword')" prop="CheckPass">
<el-input v-model="form.CheckPass" show-password autocomplete="off" />
</el-form-item>
<el-form-item style="text-align: right">
@@ -262,13 +201,13 @@ export default {
trigger: ["blur", "change"],
},
],
UserId: [
{
required: true,
message: this.$t("common:ruleMessage:select"),
trigger: ["blur", "change"],
},
],
// UserId: [
// {
// required: true,
// message: this.$t("common:ruleMessage:select"),
// trigger: ["blur", "change"],
// },
// ],
},
sendDisabled: true,
sendTitle: this.$t("passwordReset:button:send"),
@@ -276,6 +215,24 @@ export default {
IsCanConnectInternet: true,
};
},
computed: {
userMsg() {
if (!this.users || this.users.length <= 0) return ''
let str = ''
this.users.forEach((item, index) => {
if (index === 0) {
str += `${item.UserName}(`
}
if (index === this.users.length - 1) {
str += `${item.UserTypeShortName})`
} else {
str += `${item.UserTypeShortName}`
}
})
return str
}
},
created() {
this.getInfo();
},
@@ -338,6 +295,9 @@ export default {
.then((res) => {
this.formLoading = false;
this.users = res.Result;
if (this.users && this.users.length > 0) {
this.form.UserId = this.users[0].IdentityUserId
}
this.isVerify = true;
this.$message.success(this.$t("passwordReset:button:verifySuccess"));
})
@@ -372,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;
@@ -394,12 +355,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: 700px;
margin: 20px auto;
+360 -183
View File
@@ -1,21 +1,18 @@
<template>
<div class="login-container">
<div class="login-container" v-loading="loginLoading" :element-loading-text="$t('login:tip:waitLogin')"
element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)">
<div class="login-header">
<!-- <img src="@/assets/login-logo.png" class="login-logo"> -->
</div>
<div class="login-body">
<div class="login-l">
<div class="login-logo">
<img
v-if="language === 'zh'"
:src="
hospital.HospitalLogoPath
? OSSclientConfig.basePath + hospital.HospitalLogoPath
: logoImg
"
alt=""
/>
<img v-else src="@/assets/zzlogo3.png" alt="" />
<!-- <img v-if="language === 'zh' && hospital.HospitalLogoPath" -->
<img v-if="language === 'zh'" :src="OSSclientConfig.basePath + hospital.HospitalLogoPath"
crossOrigin="anonymous" alt="" :style="`max-height:60px;max-width:${config.logoScale.login * 60}px`" />
<img v-else-if="NODE_ENV === 'usa'" :src="OSSclientConfig.basePath + hospital.HospitalLogoPath" alt=""
class="usa-logo" :style="`max-height:60px;max-width:${config.logoScale.login * 60}px`" />
<!-- <img v-else src="@/assets/zzlogo3.png" alt="" /> -->
</div>
<div class="login-image">
<img src="@/assets/login-bg.png" />
@@ -25,98 +22,60 @@
<div class="title-container">
<!-- IRC Management System -->
<div class="title">
{{ $t("login:title:system") }}
{{ $t('login:title:system') }}
</div>
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<el-form-item
prop="username"
:rules="[
{
required: true,
message: this.$t('login:formRule:userName'),
trigger: 'blur',
},
]"
>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
label-position="left">
<el-form-item prop="username" :rules="[
{
required: true,
message: this.$t('login:formRule:userName'),
trigger: 'blur',
},
]">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<!-- User Name -->
<el-input
ref="username"
v-model="loginForm.username"
size="small"
:placeholder="$t('login:form:userName')"
name="username"
type="text"
tabindex="1"
/>
<el-input ref="username" v-model="loginForm.username" size="small" :placeholder="$t('login:form:userName')"
name="username" type="text" tabindex="1" />
</el-form-item>
<el-form-item
prop="password"
:rules="[
{
required: true,
message: this.$t('login:formRule:password'),
trigger: 'blur',
},
]"
>
<el-form-item prop="password" :rules="[
{
required: true,
message: this.$t('login:formRule:password'),
trigger: 'blur',
},
]">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<!-- password -->
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
size="small"
:type="passwordType"
:placeholder="$t('login:form:password')"
name="password"
tabindex="2"
@keyup.enter.native="handleLogin"
/>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" size="small" :type="passwordType"
:placeholder="$t('login:form:password')" name="password" tabindex="2" @keyup.enter.native="handleLogin" />
<span class="show-pwd" @click="showPwd">
<svg-icon
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
/>
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
<!-- Login -->
<el-button
:loading="loading"
type="primary"
style="width: 100%; margin-bottom: 10px"
size="medium"
@click.native.prevent="handleLogin"
>
{{ $t("login:button:login") }}
<el-button :loading="loading" type="primary" style="width: 100%; margin-bottom: 10px" size="medium"
@click.native.prevent="handleLogin">
{{ $t('login:button:login') }}
</el-button>
<div style="text-align: right">
<!-- Forget password? -->
<el-button
type="text"
size="medium"
@click.native.prevent="handleResetPwd"
>
{{ $t("login:button:forgetPassword") }}
<el-button type="text" size="medium" @click.native.prevent="handleResetPwd">
{{ $t('login:button:forgetPassword') }}
</el-button>
<TopLang v-if="isDev" />
</div>
</el-form>
</div>
</div>
<div v-if="language === 'zh'" class="login-footer">
<span>Copyright © 2024 上海展影医疗科技有限公司 版权所有</span>
<div class="login-footer">
<!-- <span>Copyright © 2024 上海展影医疗科技有限公司 版权所有</span>
<span> | </span>
<a target="_blank" href="https://beian.miit.gov.cn/">
<span> 沪ICP备2021037850-2 </span>
@@ -128,44 +87,82 @@
>
<img src="@/assets/filing.png" />
<span>沪公网安备 31011002005859</span>
</a>
</a> -->
<span><span @click.stop="openHospital">{{ $t('login:copyright:title:construct') }}</span>{{ hospital.HospitalName
}}</span>
<span> | </span>
<span>{{ $t('login:copyright:title:support') }}{{ language === 'zh' ? config.company : config.companyEN }}</span>
<el-popover placement="top" trigger="click">
<div class="file_a_box">
<a :href="`${OSSclientConfig.basePath}/SupportDownload/ConfigurationDocumentation.pdf`"
download="ConfigurationDocumentation" target="_blank">{{
$t("login:file:ConfigurationDocumentation")
}}</a>
<a :href="`${OSSclientConfig.basePath}/SupportDownload/Certificate.zip`" download="Certificate">{{
$t("login:file:Certificate")
}}</a>
<a :href="`${OSSclientConfig.basePath}/SupportDownload/GoogleChromePortable.zip`"
download="GoogleChromePortable">{{ $t("login:file:GoogleChrome")
}}</a>
</div>
<span slot="reference" style="color:#409EFF;cursor: pointer;">{{ $t("login:file:click") }}</span>
</el-popover>
</div>
<Vcode
:show="isShow"
slider-text="拖到滑块完成验证"
:imgs="[Img1]"
@success="onSuccess"
/>
<Vcode :show="isShow" slider-text="拖到滑块完成验证" :imgs="[Img1]" @success="onSuccess" />
<el-dialog :title="$t('login:hospital:title:changeHospital')" :visible.sync="visible" width="30%"
:append-to-body="true">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item :label="$t('login:hospital:form:changeHospital')">
<el-select v-model="form.Id" placeholder="" style="width:100%">
<el-option v-for="item in hospitalList" :key="item.Id" :label="item.HospitalName" :value="item.Id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">{{ $t("common:button:cancel") }}</el-button>
<el-button type="primary" @click="saveHospital">{{ $t("system:hospital:save") }}</el-button>
</span>
</el-dialog>
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
@save="loginByRole" @cancel="cancel" />
</div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
import TopLang from "./topLang";
import { mapGetters, mapMutations } from 'vuex'
import TopLang from './topLang'
// import NoticeMarquee from '../trials/trials-layout/components/noticeMarquee'
import Vcode from "vue-puzzle-vcode";
import Img1 from "@/assets/pic-1.png";
import logoImg from "@/assets/zzlogo2.png";
import { getHospital } from "@/api/hospital.js";
import Vcode from 'vue-puzzle-vcode'
import Img1 from '@/assets/pic-1.png'
import logoImg from '@/assets/zzlogo2.png'
import { getHospital } from '@/api/hospital.js'
import { getHIRHospitalList, updateDefaultHospital } from '@/api/admin'
import toggleRole from '@/components/toggleRole'
import { resetRouter } from '@/router'
export default {
name: "Login",
components: { TopLang, Vcode },
name: 'Login',
components: { TopLang, Vcode, toggleRole },
data() {
return {
NODE_ENV: process.env.NODE_ENV, // process.env.NODE_ENV
config: WINDOW_CONFIG,
visible: false,
logoImg,
VUE_APP_OSS_CONFIG_REGION: process.env.VUE_APP_OSS_CONFIG_REGION,
loginForm: {
username: "",
password: "",
username: '',
password: '',
},
loginRules: {
username: [
{
required: true,
message: this.$t("login:formRule:userName"),
trigger: "blur",
message: this.$t('login:formRule:userName'),
trigger: 'blur',
},
{ max: 20, message: `${this.$t("common:ruleMessage:maxLength")} 20` },
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
],
password: [
// {
@@ -175,14 +172,14 @@ export default {
// },
{
required: true,
message: this.$t("login:formRule:password"),
trigger: "blur",
message: this.$t('login:formRule:password'),
trigger: 'blur',
},
{ max: 20, message: `${this.$t("common:ruleMessage:maxLength")} 20` },
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
],
},
loading: false,
passwordType: "password",
passwordType: 'password',
loginType: null,
location: null,
isShow: false,
@@ -190,128 +187,273 @@ export default {
hospital: {
HospitalLogoPath: null,
HospitalName: null,
Id: null
},
};
hospitalList: [],
form: {
Id: null
},
toggleRoleVisible: false,
toggleRoleLoading: false,
loginLoading: false
}
},
computed: {
...mapGetters(["asyncRoutes", "routes", "language"]),
...mapGetters(['asyncRoutes', 'routes', 'language']),
isDev() {
return process.env.VUE_APP_OSS_PATH === "/hir_test/dist"
}
},
created() {
this.getInfo();
this.getInfo()
this.getList()
},
mounted() {
this.loginType = this.$route.query.loginType;
this.location = this.$route.query.location;
zzSessionStorage.setItem("loginType", this.loginType);
localStorage.setItem("location", this.location);
// if (process.env.VUE_APP_OSS_CONFIG_REGION === "oss-us-west-1") {
// this.$i18n.locale = "en";
// this.setLanguage("en");
// this.$updateDictionary();
// } else {
// if (this.location === "USA") {
// this.$i18n.locale = "en";
// this.setLanguage("en");
// this.$updateDictionary();
// } else {
this.$i18n.locale = "zh";
this.setLanguage("zh");
this.$updateDictionary();
// }
this.loginType = this.$route.query.loginType
this.location = this.$route.query.location
zzSessionStorage.setItem('loginType', this.loginType)
localStorage.setItem('location', this.location)
if (process.env.NODE_ENV === "usa") {
this.$i18n.locale = "en";
this.setLanguage("en");
this.$updateDictionary();
} else {
// if (this.location === "USA") {
// this.$i18n.locale = "en";
// this.setLanguage("en");
// this.$updateDictionary();
// } else {
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
}
// }
if (this.$route.query.token) {
this.loginLoading = true
this.TJUserLoginInfo(this.$route.query.token)
}
},
methods: {
...mapMutations({ setLanguage: "lang/setLanguage" }),
...mapMutations({ setLanguage: 'lang/setLanguage' }),
cancel() {
this.showCode = true
this.loading = false
this.toggleRoleLoading = false
// this.toggleRoleVisible = false
},
// 置换token
async TJUserLoginInfo(Token) {
this.$store
.dispatch('user/loginByToken', { Token }).then(res => {
if (res.length === 1) {
return this.loginByRole({
UserId: res[0].Id, UserTypeId: res[0].UserTypeId
})
}
this.loginLoading = false
this.toggleRoleVisible = true
}).catch(err => {
this.loginLoading = false
console.log(err)
})
},
async saveHospital() {
if (this.form.Id === this.hospital.Id) return this.visible = false
let res = await updateDefaultHospital({
HirHospitalId: this.form.Id
})
if (res.IsSuccess) {
this.visible = false
this.getInfo()
this.getList()
}
},
openHospital() {
if (this.hospitalList.length <= 1) return false
this.form.Id = this.hospital.Id
this.visible = true
},
// 获取医院列表
getList() {
getHIRHospitalList({
HospitalName: null,
Country: null,
City: null,
Province: null,
Address: null,
Phone: null,
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 1000,
})
.then((res) => {
this.hospitalList = res.Result.CurrentPageData
})
.catch(() => {
})
},
// 获取医院信息
async getInfo() {
try {
let res = await getHospital();
let res = await getHospital()
if (res.IsSuccess) {
Object.keys(this.hospital).forEach((key) => {
this.hospital[key] = res.Result[key];
});
this.hospital[key] = res.Result[key]
})
}
} catch (err) {
console.log(err);
console.log(err)
}
},
showPwd() {
if (this.passwordType === "password") {
this.passwordType = "";
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = "password";
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus();
});
this.$refs.password.focus()
})
},
handleLogin() {
this.loginType = this.$route.query.loginType;
this.loginType = this.$route.query.loginType
this.$refs.loginForm.validate((valid) => {
if (valid) {
// this.isShow = true
this.loginIn();
this.loginIn()
} else {
return false;
return false
}
});
})
},
loginIn() {
this.loading = true;
this.loading = true
this.$store
.dispatch("user/login", this.loginForm)
.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"));
this.$message.success(this.$t('login:message:login1'))
setTimeout(() => {
this.$router.push({
path: `/recompose?userName=${this.loginForm.username}`,
});
}, 500);
return;
})
}, 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;
});
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();
this.isShow = false
this.loginIn()
},
handleResetPwd() {
this.$router.push({ name: "Resetpassword" });
this.$router.push({ name: 'Resetpassword' })
},
},
};
}
</script>
<style lang="scss">
@@ -364,20 +506,36 @@ $cursor: #fff;
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #606266;
.file_a_box {
a {
margin-bottom: 5px;
display: block;
&:last-child {
margin: 0;
}
}
}
.login-container {
position: relative;
width: 100%;
height: 100%;
overflow: auto;
background: rgb(249, 249, 249);
.login-header {
margin: 10px 0px 20px 10px;
height: 3rem;
width: 720px;
.login-logo {
height: 100%;
}
}
.login-body {
position: absolute;
left: 50%;
@@ -391,30 +549,41 @@ $light_gray: #606266;
box-sizing: border-box;
background: rgb(255, 255, 255);
border-radius: 10px 0px 0px 10px;
.login-l {
position: relative;
float: left;
width: 50%;
height: 100%;
.login-logo {
position: absolute;
top: 35px;
left: 50px;
img {
height: 40px;
}
// img {
// max-height: 60px;
// max-width: 250px;
// }
// .usa-logo {
// height: 60px;
// }
}
.login-image {
position: absolute;
top: 10px;
left: 0px;
// transform: translateY(-50%);
height: 100%;
img {
height: 100%;
}
}
}
.login-r {
position: relative;
float: left;
@@ -423,7 +592,7 @@ $light_gray: #606266;
.login-form {
position: absolute;
top: 50%;
top: 55%;
// transform: translateY(-50%);
left: 50%;
transform: translate(-50%, -50%);
@@ -432,9 +601,12 @@ $light_gray: #606266;
margin: 0 auto;
overflow: hidden;
}
.title-container {
// margin-bottom: 50px;
margin-top: 15%;
text-align: center;
margin-top: 20%;
.title {
font-size: 35px;
color: $light_gray;
@@ -474,6 +646,7 @@ $light_gray: #606266;
}
}
}
.login-footer {
position: absolute;
bottom: 50px;
@@ -487,6 +660,7 @@ $light_gray: #606266;
align-items: center;
// color: rgb(180, 190, 199);
color: #909399;
a {
display: inline-block;
text-decoration: none;
@@ -495,13 +669,16 @@ $light_gray: #606266;
display: flex;
justify-content: center;
}
span {
margin: 0 2px;
}
img {
height: 20px;
line-height: 20px;
}
// p{
// display: inline-block;
// height:20px;
+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;
@@ -3,7 +3,7 @@
:visible.sync="visible"
:close-on-click-modal="false"
:title="title"
width="500px"
width="600px"
custom-class="base-dialog-wrapper"
append-to-body
:before-close="handleCancel"
@@ -14,9 +14,27 @@
:model="form"
:rules="rules"
size="small"
label-width="100px"
label-width="150px"
>
<div class="base-dialog-body">
<!--PacsTypeEnum-->
<el-form-item
:label="$t('system:dicom:form:PacsTypeEnum')"
prop="PacsTypeEnum"
>
<el-select
v-model="form.PacsTypeEnum"
placeholder=""
style="width: 100%"
>
<el-option
v-for="item in $d.PacsType"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<!--AE Title-->
<el-form-item :label="$t('system:dicom:form:AETitle')" prop="CalledAE">
<el-input v-model.trim="form.CalledAE" clearable maxlength="16" />
@@ -30,8 +48,46 @@
<el-input v-model.number="form.Port" type="number" clearable />
</el-form-item>
<!--Modality-->
<el-form-item :label="$t('system:dicom:form:Modality')" prop="Modality">
<el-input v-model="form.Modality" clearable />
<el-form-item
:label="$t('system:dicom:form:Modality')"
prop="ModalityList"
>
<el-select
v-model="form.ModalityList"
placeholder=""
style="width: 100%"
clearable
multiple
>
<el-option
v-for="item in $d.modalType"
:key="item.id"
:label="item.label"
:value="item.label"
/>
</el-select>
</el-form-item>
<!--影像时间范围-->
<el-form-item
:label="$t('system:dicom:form:timeFrame')"
prop="PacsSearchMaxDays"
>
<el-input
v-model.number="form.PacsSearchMaxDays"
type="number"
clearable
/>
</el-form-item>
<!--最大拉取数量-->
<el-form-item
:label="$t('system:dicom:form:MaxStudyCount')"
prop="MaxStudyCount"
>
<el-input
v-model.number="form.MaxStudyCount"
type="number"
clearable
/>
</el-form-item>
<!--Description-->
<el-form-item
@@ -40,6 +96,20 @@
>
<el-input v-model="form.Description" clearable />
</el-form-item>
<!--是否支持多模态-->
<el-form-item
:label="$t('system:dicom:form:IsSupportMutiModality')"
prop="IsSupportMutiModality"
>
<el-switch
v-model="form.IsSupportMutiModality"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
:active-value="true"
:inactive-value="false"
>
</el-switch>
</el-form-item>
</div>
<div
class="base-dialog-footer"
@@ -52,7 +122,7 @@
:disabled="btnLoading"
@click="handleCancel"
>
{{ $t("common:button:cancel") }}
{{ $t('common:button:cancel') }}
</el-button>
<el-button
size="small"
@@ -60,7 +130,7 @@
:loading="btnLoading"
@click="setAE"
>
{{ $t("common:button:save") }}
{{ $t('common:button:save') }}
</el-button>
</el-form-item>
</div>
@@ -68,9 +138,9 @@
</el-dialog>
</template>
<script>
import { setDiicomAE } from "@/api/dicomAE.js";
import { setDiicomAE } from '@/api/dicomAE.js'
export default {
name: "editDicom",
name: 'editDicom',
props: {
visible: {
require: true,
@@ -78,12 +148,12 @@ export default {
},
title: {
require: true,
default: "",
default: '',
},
dicom: {
type: Object,
default: () => {
return {};
return {}
},
},
},
@@ -93,95 +163,177 @@ export default {
CalledAE: null,
IP: null,
Port: null,
Modality: null,
ModalityList: null,
Description: null,
Id: null,
PacsTypeEnum: null,
PacsSearchMaxDays: null,
MaxStudyCount: null,
IsSupportMutiModality: false
},
rules: {
PacsTypeEnum: [
{
required: true,
message: this.$t('common:ruleMessage:select'),
trigger: 'blur',
},
],
ModalityList: [
{
required: true,
message: this.$t('common:ruleMessage:select'),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (!value || (Array.isArray(value) && value.length <= 0)) {
callback(new Error(this.$t('common:ruleMessage:select')))
} else {
callback()
}
},
},
],
CalledAE: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
{
pattern: /[a-zA-Z0-9]/,
message: this.$t("common:ruleMessage:CalledAEPattern"),
trigger: "blur",
message: this.$t('common:ruleMessage:CalledAEPattern'),
trigger: 'blur',
},
{
min: 1,
max: 16,
message: this.$t("common:ruleMessage:CalledAEPattern"),
trigger: "blur",
message: this.$t('common:ruleMessage:CalledAEPattern'),
trigger: 'blur',
},
],
IP: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (
value === "" ||
typeof value === "undefined" ||
value === '' ||
typeof value === 'undefined' ||
value == null
) {
callback(new Error(this.$t("common:ruleMessage:ipPattern")));
callback(new Error(this.$t('common:ruleMessage:ipPattern')))
} else {
const reg =
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
if (!reg.test(value) && value !== "") {
callback(new Error(this.$t("common:ruleMessage:ipPattern")));
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
if (!reg.test(value) && value !== '') {
callback(new Error(this.$t('common:ruleMessage:ipPattern')))
} else {
callback();
callback()
}
}
},
message: this.$t("common:ruleMessage:ipPattern"),
trigger: "blur",
message: this.$t('common:ruleMessage:ipPattern'),
trigger: 'blur',
},
],
Port: [
PacsSearchMaxDays: [
{
required: true,
message: this.$t("common:ruleMessage:portPattern"),
trigger: "blur",
message: this.$t('common:ruleMessage:PacsSearchMaxDaysPattern'),
trigger: 'blur',
},
{
type: "number",
type: 'number',
min: 0,
max: 65535,
message: this.$t("common:ruleMessage:portPattern"),
trigger: "blur",
// max: 365,
message: this.$t('common:ruleMessage:PacsSearchMaxDaysPattern'),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (
value &&
(String(value).includes(".") ||
(String(value).includes('.') ||
new RegExp(/\D/g).test(String(value)))
) {
callback(new Error(this.$t("common:ruleMessage:portPattern")));
callback(
new Error(
this.$t('common:ruleMessage:PacsSearchMaxDaysPattern')
)
)
} else {
callback();
callback()
}
},
trigger: "blur",
trigger: 'blur',
},
],
MaxStudyCount: [
// {
// required: true,
// message: this.$t('common:ruleMessage:MaxStudyCountPattern'),
// trigger: 'blur',
// },
{
validator: (rule, value, callback) => {
if (
value &&
(String(value).includes('.') ||
new RegExp(/\D/g).test(String(value)))
) {
callback(
new Error(this.$t('common:ruleMessage:MaxStudyCountPattern'))
)
} else {
callback()
}
},
trigger: 'blur',
},
],
Port: [
{
required: true,
message: this.$t('common:ruleMessage:portPattern'),
trigger: 'blur',
},
{
type: 'number',
min: 0,
max: 65535,
message: this.$t('common:ruleMessage:portPattern'),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (
value &&
(String(value).includes('.') ||
new RegExp(/\D/g).test(String(value)))
) {
callback(new Error(this.$t('common:ruleMessage:portPattern')))
} else {
callback()
}
},
trigger: 'blur',
},
],
},
btnLoading: false,
};
}
},
watch: {
dicom: {
handler() {
Object.keys(this.form).forEach((key) => {
this.form[key] = this.dicom[key];
});
this.form[key] = this.dicom[key]
})
},
deep: true,
immediate: true,
@@ -190,37 +342,35 @@ export default {
methods: {
handleCancel() {
Object.keys(this.form).forEach((key) => {
this.form[key] = null;
});
this.$refs.editVisitForm.clearValidate();
this.$emit("update:visible", false);
this.form[key] = null
})
this.$refs.editVisitForm.clearValidate()
this.$emit('update:visible', false)
},
// 新增或修改
async setAE() {
try {
let validate = await this.$refs.editVisitForm.validate();
if (!validate) return;
this.btnLoading = true;
let res = await setDiicomAE(this.form);
let validate = await this.$refs.editVisitForm.validate()
if (!validate) return
this.btnLoading = true
let res = await setDiicomAE(this.form)
if (res.IsSuccess) {
if (this.form.Id) {
this.$message.success(
this.$t("common:message:updatedSuccessfully")
);
this.$message.success(this.$t('common:message:updatedSuccessfully'))
} else {
this.$message.success(this.$t("common:message:addedSuccessfully"));
this.$message.success(this.$t('common:message:addedSuccessfully'))
}
this.btnLoading = false;
this.handleCancel();
this.$emit("getList");
this.btnLoading = false
this.handleCancel()
this.$emit('getList')
} else {
this.$message.error(res.errorMessage);
this.$message.error(res.errorMessage)
}
} catch (err) {
this.btnLoading = false;
console.log(err);
this.btnLoading = false
console.log(err)
}
},
},
};
}
</script>
+131 -67
View File
@@ -2,6 +2,24 @@
<div class="dicomAE">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item
:label="$t('system:dicom:search:PacsTypeEnum')"
prop="PacsTypeEnum"
>
<el-select
v-model="searchData.PacsTypeEnum"
placeholder=""
style="width: 140px"
clearable
>
<el-option
v-for="item in $d.PacsType"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<!--AE Title-->
<el-form-item
:label="$t('system:dicom:search:AETitle')"
@@ -23,17 +41,17 @@
</el-form-item>
<el-form-item>
<el-button type="primary" size="mini" @click="getList">{{
$t("system:dicom:search:search")
$t('system:dicom:search:search')
}}</el-button>
<el-button type="primary" size="mini" @click="reset">{{
$t("system:dicom:search:reset")
$t('system:dicom:search:reset')
}}</el-button>
<el-button
type="primary"
size="mini"
v-hasPermi="['system:dicom:add']"
@click="openDialog('add')"
>{{ $t("system:dicom:search:add") }}</el-button
>{{ $t('system:dicom:search:add') }}</el-button
>
</el-form-item>
</el-form>
@@ -51,7 +69,7 @@
<el-table-column
:label="$t('system:dicom:table:AETitle')"
prop="CalledAE"
min-width="120"
min-width="100"
show-overflow-tooltip
sortable="custom"
/>
@@ -59,7 +77,7 @@
<el-table-column
:label="$t('system:dicom:table:IP')"
prop="IP"
min-width="120"
min-width="100"
show-overflow-tooltip
sortable="custom"
/>
@@ -67,37 +85,80 @@
<el-table-column
:label="$t('system:dicom:table:Port')"
prop="Port"
min-width="120"
min-width="80"
show-overflow-tooltip
sortable="custom"
/>
<!--PacsTypeEnum-->
<el-table-column
:label="$t('system:dicom:table:PacsTypeEnum')"
prop="PacsTypeEnum"
min-width="120"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd('PacsType', scope.row.PacsTypeEnum) }}</span>
</template>
</el-table-column>
<!--Modality-->
<el-table-column
:label="$t('system:dicom:table:Modality')"
prop="Modality"
prop="ModalityList"
min-width="120"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ scope.row.ModalityList.join(', ') }}</span>
</template>
</el-table-column>
<!--PacsSearchMaxDays-->
<el-table-column
:label="$t('system:dicom:table:PacsSearchMaxDays')"
prop="PacsSearchMaxDays"
min-width="140"
show-overflow-tooltip
sortable="custom"
/>
<!--MaxStudyCount-->
<el-table-column
:label="$t('system:dicom:table:MaxStudyCount')"
prop="MaxStudyCount"
min-width="110"
show-overflow-tooltip
sortable="custom"
/>
<!--Description-->
<el-table-column
:label="$t('system:dicom:table:Description')"
prop="Description"
min-width="120"
min-width="100"
show-overflow-tooltip
sortable="custom"
/>
<!--IsSupportMutiModality-->
<el-table-column
:label="$t('system:dicom:table:IsSupportMutiModality')"
prop="IsSupportMutiModality"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd('YesOrNo', scope.row.IsSupportMutiModality) }}</span>
</template>
</el-table-column>
<!--测试状态-->
<el-table-column
:label="$t('system:dicom:table:IsTestOK')"
prop="IsTestOK"
min-width="120"
min-width="80"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<el-tag :type="scope.row.IsTestOK ? 'success' : 'danger'">{{
$fd("IsTestOK", String(scope.row.IsTestOK))
$fd('IsTestOK', String(scope.row.IsTestOK))
}}</el-tag>
</template>
</el-table-column>
@@ -122,6 +183,7 @@
fixed="right"
prop="UserTypeShortName"
show-overflow-tooltip
min-width="120px"
>
<template slot-scope="scope">
<el-button
@@ -129,17 +191,17 @@
type="text"
v-hasPermi="['system:dicom:edit']"
@click="openDialog('edit', scope.row)"
>{{ $t("system:dicom:action:edit") }}</el-button
>{{ $t('system:dicom:action:edit') }}</el-button
>
<el-button
size="mini"
type="text"
v-hasPermi="['system:dicom:del']"
@click="delAE(scope.row)"
>{{ $t("system:dicom:action:remove") }}</el-button
>{{ $t('system:dicom:action:remove') }}</el-button
>
<el-button size="mini" type="text" @click="test(scope.row)">{{
$t("system:dicom:action:test")
$t('system:dicom:action:test')
}}</el-button>
</template>
</el-table-column>
@@ -154,6 +216,7 @@
</div>
</div>
<editDicom
v-if="editDicomVisible"
:visible.sync="editDicomVisible"
:title="editDicomTitle"
:dicom="DICOM"
@@ -162,22 +225,23 @@
</div>
</template>
<script>
import Pagination from "@/components/Pagination";
import editDicom from "./components/edit-dicom";
import { getDicomAEList, deleteDiicomAE, testConnect } from "@/api/dicomAE.js";
import Pagination from '@/components/Pagination'
import editDicom from './components/edit-dicom'
import { getDicomAEList, deleteDiicomAE, testConnect } from '@/api/dicomAE.js'
const defaultSearchData = () => {
return {
CalledAE: null,
IP: null,
Port: null,
PacsTypeEnum: null,
PageIndex: 1,
PageSize: 10,
SortField: "CreateTime",
PageSize: 20,
SortField: 'CreateTime',
Asc: false,
};
};
}
}
export default {
name: "dicomAE",
name: 'dicomAE',
components: { Pagination, editDicom },
data() {
return {
@@ -189,98 +253,98 @@ export default {
list: [],
// 弹窗
editDicomVisible: false,
editDicomTitle: "",
editDicomTitle: '',
DICOM: {},
};
}
},
created() {
this.getList();
this.getList()
},
methods: {
// 表格排序
handleSortChange(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
// 获取列表
async getList() {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data[key] = this.searchData[key]
})
try {
this.loading = true;
let res = await getDicomAEList(data);
this.loading = false;
this.loading = true
let res = await getDicomAEList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
console.log(err);
console.log(err)
}
},
// 重置
reset() {
this.searchData = defaultSearchData();
this.$refs.dicomAeTable.clearSort();
this.getList();
this.searchData = defaultSearchData()
this.$refs.dicomAeTable.clearSort()
this.getList()
},
// 打开弹框
openDialog(key, item = {}) {
this.editDicomVisible = true;
this.editDicomTitle = this.$t("system:dicom:action:edit");
if (key === "add") {
this.editDicomTitle = this.$t("system:dicom:search:add");
this.editDicomVisible = true
this.editDicomTitle = this.$t('system:dicom:action:edit')
if (key === 'add') {
this.editDicomTitle = this.$t('system:dicom:search:add')
}
this.DICOM = JSON.parse(JSON.stringify(item));
this.DICOM = JSON.parse(JSON.stringify(item))
},
// 删除
async delAE(item) {
try {
let confirm = await this.$confirm(
this.$t("trials:staffResearch:message:confirmDel"),
this.$t("trials:uploadDicomList:label:prompt"),
this.$t('trials:staffResearch:message:confirmDel'),
this.$t('trials:uploadDicomList:label:prompt'),
{
confirmButtonText: this.$t("trials:reviewTrack:impactList:save"),
cancelButtonText: this.$t("common:button:cancel"),
type: "warning",
confirmButtonText: this.$t('trials:reviewTrack:impactList:save'),
cancelButtonText: this.$t('common:button:cancel'),
type: 'warning',
}
);
if (confirm !== "confirm") return;
let res = await deleteDiicomAE(item.Id);
)
if (confirm !== 'confirm') return
let res = await deleteDiicomAE(item.Id)
if (res.IsSuccess) {
this.$message.success(
this.$t("trials:crcUpload:message:deleteVisitSuccessfully")
);
this.getList();
this.$t('trials:crcUpload:message:deleteVisitSuccessfully')
)
this.getList()
}
} catch (err) {
console.log(err);
console.log(err)
}
},
// 测试连通性
async test(item) {
try {
this.loading = true;
let res = await testConnect(item.Id);
this.loading = false;
this.loading = true
let res = await testConnect(item.Id)
this.loading = false
if (res.IsSuccess && res.Result) {
this.$message.success(this.$t("system:dicomAE:connect:success"));
this.$message.success(this.$t('system:dicomAE:connect:success'))
} else {
this.$message.error(this.$t("system:dicomAE:connect:error"));
this.$message.error(this.$t('system:dicomAE:connect:error'))
}
this.getList();
this.getList()
} catch (err) {
console.log(err);
this.loading = false;
console.log(err)
this.loading = false
}
},
},
};
}
</script>
<style lang="scss" scoped>
.dicomAE {
@@ -0,0 +1,232 @@
<template>
<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: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>
</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, groupList },
props: {
status: {
type: String,
default: "default" // add edit default
},
rowData: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
activeTab: 'hospital',
hospital: {
HospitalName: null,
HospitalAliasName: null,
HospitalCode: null,
Country: null,
City: null,
Province: null,
Address: null,
Phone: null,
IsCanConnectInternet: true,
Id: null,
TrialKeepCount: null,
HospitalLogoPath: null,
IsDefault: false
},
hospitalFormRules: {
HospitalName: [
{ required: true, message: 'Please specify', trigger: "blur" },
],
HospitalCode: [
{ required: true, message: 'Please specify', trigger: "blur" },
],
// HospitalLogoPath: [
// { required: true, message: "请上传医院logo", trigger: "blur" },
// ],
TrialKeepCount: [
{ required: true, message: 'Please specify', trigger: "blur" },
],
// HospitalAliasName: [
// { required: true, message: "请输入医院别称", trigger: "blur" },
// ],
// Country: [{ required: true, message: "请输入国家", trigger: "blur" }],
// City: [{ required: true, message: "请输入所在城市", trigger: "blur" }],
// Province: [
// { required: true, message: "请输入所在省份", trigger: "blur" },
// ],
// Address: [
// { required: true, message: "请输入医院地址", trigger: "blur" },
// ],
// Phone: [
// { required: true, message: "请输入医院联系方式", trigger: "blur" },
// ],
},
btnLoading: false,
};
},
mounted() {
if (this.status === 'default') {
this.getInfo();
}
if (this.status === 'edit') {
Object.keys(this.hospital).forEach(key => {
this.hospital[key] = this.rowData[key]
})
}
},
computed: {
disabled() {
return !this.hasPermi(["system:hospital:edit"]);
},
},
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 {
let validate = await this.$refs.hospitalForm.validate();
if (!validate) return;
this.btnLoading = true;
let res = await addOrUpdateHIRHospital(this.hospital);
this.btnLoading = false;
if (res.IsSuccess) {
this.$message.success(this.$t("common:message:savedSuccessfully"));
if (this.status !== 'default') {
this.$emit("getList")
this.$emit("close")
}
}
} catch (err) {
this.btnLoading = false;
console.log(err);
}
},
// 获取医院信息
async getInfo() {
try {
let res = await getHospital();
if (res.IsSuccess) {
Object.keys(this.hospital).forEach((key) => {
this.hospital[key] = res.Result[key];
});
}
} catch (err) {
console.log(err);
}
},
handleCancel() {
this.$emit("close")
}
},
};
</script>
<style scoped>
::v-deep .is-error.my_new_pwd {
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%;
overflow-y: auto;
}
.btnBox {
display: flex;
align-items: center;
justify-content: flex-end;
}
</style>
@@ -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>
@@ -0,0 +1,223 @@
<template>
<div class="log">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item :label="$t('system:hospital:table:hospitalName')" prop="Version">
<el-input v-model="searchData.HospitalName" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:table:country')" prop="Version">
<el-input v-model="searchData.Country" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:table:city')" prop="UpdateContent">
<el-input v-model="searchData.City" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:table:province')" prop="UpdateContent">
<el-input v-model="searchData.Province" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:table:address')" prop="UpdateContent">
<el-input v-model="searchData.Address" size="small" clearable style="width:100px" />
</el-form-item>
<el-form-item :label="$t('system:hospital:table:phone')" prop="UpdateContent">
<el-input v-model="searchData.Phone" size="small" clearable style="width:100px" />
</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>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 65 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn" :default-sort="{ prop: 'PublishTime', order: 'descending' }">
<el-table-column type="index" width="50" />
<el-table-column :label="$t('system:hospital:table:hospitalName')" prop="HospitalName" min-width="120"
show-overflow-tooltip sortable="custom" />
<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: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"
show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:isCanConnectInternet')" prop="IsCanConnectInternet"
show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ $fd("YesOrNo", scope.row.IsCanConnectInternet) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('system:hospital:table:hospitalCode')" prop="HospitalCode"
show-overflow-tooltip />
<el-table-column :label="$t('system:hospital:table:isDefault')" prop="IsDefault" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ $fd("YesOrNo", scope.row.IsDefault) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('system:hospital:table:createTime')" prop="CreateTime" min-width="150"
show-overflow-tooltip />
<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="250"
show-overflow-tooltip>
<template slot-scope="scope">
<el-button size="mini" :disabled="scope.row.IsDefault" type="text" icon="el-icon-circle-check"
@click="setDefault(scope.row)">
{{ $t('system:hospital:button:setDefault') }}
</el-button>
<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" :fullscreen="true">
<system-hospital v-if="visible" :status="status" :rowData="rowData" @getList="getList" @close="close" />
</el-dialog>
</div>
</template>
<script>
import { getHIRHospitalList, deleteHIRHospital, updateDefaultHospital } from '@/api/admin'
import Pagination from '@/components/Pagination'
import systemHospital from './form.vue'
import moment from 'moment'
const searchDataDefault = () => {
return {
HospitalName: null,
Country: null,
City: null,
Province: null,
Address: null,
Phone: null,
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 20,
}
}
export default {
components: { Pagination, systemHospital },
data() {
return {
moment,
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
visible: false,
status: 'default',
rowData: {}
}
},
mounted() {
this.getList()
},
methods: {
async setDefault(row) {
try {
this.$confirm(this.$t('system:hospital:message:setDefault'), {
type: 'warning',
distinguishCancelAndClose: true,
}).then(async () => {
let res = await updateDefaultHospital({ HirHospitalId: row.Id })
if (res.IsSuccess) {
this.getList()
}
}).catch(err => {
console.log(err)
this.loading = false
})
} catch (err) {
console.log(err)
}
},
close() {
this.visible = false
this.rowData = {}
this.status = "default"
},
getList() {
this.loading = true
getHIRHospitalList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
handleAdd() {
this.status = 'add'
this.visible = true
},
handleEdit(row) {
this.status = 'edit'
this.rowData = row
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
deleteHIRHospital(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>
.log {
padding-top: 20px;
::v-deep .el-dialog__body {
padding-bottom: 5px;
}
}
</style>
@@ -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;
+12 -184
View File
@@ -1,199 +1,27 @@
<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-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: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-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>
<hospital-list v-if="isAdmin" />
<hospital-form v-else />
</div>
</template>
<script>
import { setHospital, getHospital } from "@/api/hospital.js";
import uploadLogo from "./uploadLogo.vue";
import hospitalList from "./components/list"
import hospitalForm from "./components/form"
export default {
name: "systemHospital",
components: { "upload-logo": uploadLogo },
components: { hospitalList, hospitalForm },
data() {
return {
hospital: {
HospitalName: null,
HospitalAliasName: null,
HospitalCode: null,
Country: null,
City: null,
Province: null,
Address: null,
Phone: null,
IsCanConnectInternet: true,
Id: null,
TrialKeepCount: null,
HospitalLogoPath: null,
},
hospitalFormRules: {
HospitalName: [
{ required: true, message: "请输入医院名称", trigger: "blur" },
],
HospitalCode: [
{ required: true, message: "请输入医院编码", trigger: "blur" },
],
// HospitalLogoPath: [
// { required: true, message: "请上传医院logo", trigger: "blur" },
// ],
TrialKeepCount: [
{ required: true, message: "请输入未激活项目数", trigger: "blur" },
],
// HospitalAliasName: [
// { required: true, message: "请输入医院别称", trigger: "blur" },
// ],
// Country: [{ required: true, message: "请输入国家", trigger: "blur" }],
// City: [{ required: true, message: "请输入所在城市", trigger: "blur" }],
// Province: [
// { required: true, message: "请输入所在省份", trigger: "blur" },
// ],
// Address: [
// { required: true, message: "请输入医院地址", trigger: "blur" },
// ],
// Phone: [
// { required: true, message: "请输入医院联系方式", trigger: "blur" },
// ],
},
btnLoading: false,
};
},
created() {
this.getInfo();
}
},
computed: {
disabled() {
return !this.hasPermi(["system:hospital:edit"]);
},
isAdmin() {
return this.hasPermi(['role:admin', 'role:dev'])
}
},
methods: {
async handleSave() {
if (this.btnLoading) return;
try {
let validate = await this.$refs.hospitalForm.validate();
if (!validate) return;
this.btnLoading = true;
let res = await setHospital(this.hospital);
this.btnLoading = false;
if (res.IsSuccess) {
this.$message.success(this.$t("common:message:savedSuccessfully"));
}
} catch (err) {
this.btnLoading = false;
console.log(err);
}
},
// 获取医院信息
async getInfo() {
try {
let res = await getHospital();
if (res.IsSuccess) {
Object.keys(this.hospital).forEach((key) => {
this.hospital[key] = res.Result[key];
});
}
} catch (err) {
console.log(err);
}
},
},
};
</script>
@@ -201,10 +29,10 @@ export default {
::v-deep .is-error.my_new_pwd {
margin-bottom: 40px;
}
.hospital {
width: 100%;
height: 100%;
overflow-y: auto;
}
</style>
+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="开始日期"
end-placeholder="结束日期"
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));
+362 -321
View File
@@ -1,162 +1,118 @@
<template>
<el-form
ref="userForm"
size="small"
:model="user"
:rules="userFormRules"
label-width="150px"
style="width: 800px"
>
<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-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-form-item :label="$t('system:userlist:table:UserName')" class="my_new_pwd" prop="UserName">
<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-form-item :label="$t('system:userlist:table:LastName')" prop="LastName">
<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-form-item :label="$t('system:userlist:table:FirstName')" prop="FirstName">
<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
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 :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="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 :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="$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"
>
<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-form-item :label="$t('system:userlist:table:Department')" prop="DepartmentName">
<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-form-item :label="$t('system:userlist:table:Position')" prop="PositionName">
<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
>
<el-button type="primary" size="small" :disabled="isDisabled" style="margin: 10px 15px" @click="handleSave">{{
$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>
@@ -165,254 +121,339 @@ 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, // 1为编辑,0为新增
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("Updated successfully");
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, // 1为编辑,0为新增
}
},
}
</script>
<style scoped>
::v-deep .is-error.my_new_pwd {
margin-bottom: 40px;
}
</style>
@@ -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"])) {
@@ -19,7 +19,7 @@
:model="submitMessage"
class="demo-form-inline"
:rules="rules"
label-width="130px"
:label-width="isEN?'170px':'130px'"
>
<div>
<!--项目-->
@@ -53,7 +53,7 @@
:label="
item.ShortName || item.Sex
? `${item.SubjectCode}${item.ShortName}${
item.Sex ? $fd('sex', item.Sex) : ''
item.Sex ? $fd('Sex', item.Sex) : ''
}`
: item.SubjectCode
"
@@ -132,7 +132,7 @@
clearable
@input="
addSubjectForm.SubjectCode = addSubjectForm.SubjectCode.replace(
/[^0-9a-zA-Z]/g,
/[^0-9a-zA-Z\_\-]/g,
''
)
"
@@ -264,6 +264,9 @@ export default {
if (PatientList.length <= 0) return false;
return PatientList;
},
isEN(){
return this.$i18n.locale !== 'zh'
}
},
created() {
this.getTrialList();
@@ -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="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
>
<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']">
</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;
}
@@ -0,0 +1,783 @@
<template>
<div>
<span class="title">
{{ $t('trials:inspection:title:pullImage') }}
<span>{{ tip }}</span>
</span>
<div class="search">
<el-form :inline="true" class="base-search-form">
<!-- pacsDicomAEId -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:pacsDicomAEId')">
<el-select v-model="searchData.PacsDicomAEId" style="width: 140px" @change="pacsDicomAEIdChange">
<el-option v-for="(item, index) of AElist" :key="index.Id" :label="item.CalledAE" :value="item.Id">
</el-option>
</el-select>
</el-form-item>
<!-- patientID -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:patientID')">
<el-input v-model="searchData.PatientID" clearable style="width: 100px" :maxlength="400"></el-input>
</el-form-item>
<!-- patientName -->
<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>
<!-- modalitiesInStudy -->
<el-form-item :label="$t('trials:inspection:pullImage:search:modalitiesInStudy')">
<el-select v-model="searchData.ModalitiesInStudyList" placeholder="" clearable multiple collapse-tags
style="width: 140px">
<el-option v-for="item in ModalityList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<!-- studyDate -->
<el-form-item :label="$t('trials:inspection:pullImage:search:studyDate')">
<el-date-picker v-model="StudyDate" type="daterange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" value-format="yyyyMMdd"
:picker-options="pickerOptions">
</el-date-picker>
</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-button type="primary" :disabled="!multipleSelection || multipleSelection.length <= 0"
@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>
<!--检查列表-->
<el-table ref="viewStudyList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="PageList" stripe
height="100" @sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column type="index" width="50">
<template slot-scope="scope">
<span style="
display: flex;
align-items: center;
justify-content: flex-end;
">
<el-tooltip class="item" effect="dark" :content="$t('trials:inspection:pullImage:tip:has')" placement="top"
style="margin-right: 3px">
<i v-if="scope.row.IsStudyExist" class="el-icon-success icon-i"></i>
</el-tooltip>
<span>{{ scope.$index + 1 }}</span>
</span>
</template>
</el-table-column>
<!--patientID-->
<el-table-column prop="PatientID" :label="$t('trials:inspection:pullImage:table:patientID')" show-overflow-tooltip
min-width="120" sortable="custom" />
<!--patientName-->
<el-table-column prop="PatientName" :label="$t('trials:inspection:pullImage:table:patientName')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--patientSex-->
<el-table-column prop="PatientSex" :label="$t('trials:inspection:pullImage:table:patientSex')"
show-overflow-tooltip min-width="80" sortable="custom">
<template slot-scope="scope">
<span>{{ $fd('Sex', scope.row.PatientSex) }}</span>
</template>
</el-table-column>
<!--patientBirthDate-->
<el-table-column prop="PatientBirthDate" :label="$t('trials:inspection:pullImage:table:patientBirthDate')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--studyID-->
<!-- <el-table-column
prop="StudyID"
:label="$t('trials:inspection:pullImage:table:studyID')"
show-overflow-tooltip
min-width="120"
/> -->
<!--AccessionNumber-->
<el-table-column prop="AccessionNumber" :label="$t('trials:inspection:pullImage:table:AccessionNumber')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--modalitiesInStudy-->
<el-table-column prop="ModalitiesInStudy" :label="$t('trials:inspection:pullImage:table:modalitiesInStudy')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--studyDate-->
<el-table-column prop="StudyDate" :label="$t('trials:inspection:pullImage:table:studyDate')" show-overflow-tooltip
min-width="120" sortable="custom" />
<!--studyTime-->
<el-table-column prop="StudyTime" :label="$t('trials:inspection:pullImage:table:studyTime')" show-overflow-tooltip
min-width="120" sortable="custom" />
<!--bodyPartExamined-->
<!-- <el-table-column
prop="BodyPartExamined"
:label="$t('trials:inspection:pullImage:table:bodyPartExamined')"
show-overflow-tooltip
min-width="120"
sortable="custom"
/> -->
<!--studyDescription-->
<el-table-column prop="StudyDescription" :label="$t('trials:inspection:pullImage:table:studyDescription')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--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="160">
<template slot-scope="scope">
<el-button circle icon="el-icon-refresh" class="refreshBtn" :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)" />
<!-- 转发 -->
<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>
import Pagination from '@/components/Pagination'
import {
getCFindStudyList,
cmoveStudyList,
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,
PatientID: null,
PatientName: null,
ModalitiesInStudyList: null,
StudyDate: null,
PatientSex: null,
PatientBirthDate: null,
StudyID: null,
StudyTime: null,
BodyPartExamined: null,
StudyDescription: null,
StudyInstanceUID: null,
AccessionNumber: null,
}
}
export default {
name: 'byPatient',
components: { Pagination, BaseModel },
props: {
calledAeList: {
required: true,
default: () => {
return []
},
},
callingAeList: {
required: true,
default: () => {
return []
},
},
},
data() {
return {
//
searchData: defaultSearchData(),
ModalityList: [],
timeFrame: null,
MaxStudyCount: null,
PatientBirthDate: [],
StudyDate: [],
//
loading: false,
list: [],
PageList: [],
total: 0,
PageIndex: 1,
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: {
pickerOptions() {
return {
shortcuts: [
{
text: this.$t('trials:inspection:pullImage:picker:today'),
onClick: (picker) => {
const end = new Date()
const start = new Date()
// picker.$emit('pick', [start, end])
this.StudyDate = [start, end]
},
},
{
text: this.$t('trials:inspection:pullImage:picker:week'),
onClick: (picker) => {
const end = new Date()
const start = new Date()
if (!this.timeFrame || this.timeFrame > 3) {
start.setTime(start.getTime() - 3600 * 1000 * 24 * 2)
} else {
start.setTime(
start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
)
}
// picker.$emit('pick', [start, end])
this.StudyDate = [start, end]
},
},
{
text: this.$t('trials:inspection:pullImage:picker:month'),
onClick: (picker) => {
const end = new Date()
const start = new Date()
let month = this.$moment().subtract(1, 'months')
let day = this.$moment().diff(month, 'day')
if (!this.timeFrame || this.timeFrame > day) {
start.setTime(start.getTime() - 3600 * 1000 * 24 * (day - 1))
} else {
start.setTime(
start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
)
}
// picker.$emit('pick', [start, end])
this.StudyDate = [start, end]
},
},
{
text: this.$t('trials:inspection:pullImage:picker:trimester'),
onClick: (picker) => {
const end = new Date()
const start = new Date()
let month = this.$moment().subtract(3, 'months')
let day = this.$moment().diff(month, 'day')
if (!this.timeFrame || this.timeFrame > day) {
start.setTime(start.getTime() - 3600 * 1000 * 24 * (day - 1))
} else {
start.setTime(
start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
)
}
// picker.$emit('pick', [start, end])
this.StudyDate = [start, end]
},
},
],
disabledDate: (time) => {
if (!this.timeFrame) return false
let curDate = new Date().getTime()
let three = this.timeFrame * 24 * 3600 * 1000
let threeMonths = curDate - three
return time.getTime() >= Date.now() || time.getTime() <= threeMonths
},
}
},
tip() {
if (!this.searchData.PacsDicomAEId) return ''
let message = `( ${this.$t('trials:inspection:pullImage:PacsTip')} )`
message = message.replace(
'xxx',
this.AElist.find((item) => item.Id === this.searchData.PacsDicomAEId)
.CalledAE
)
if (!this.timeFrame) {
message = message.replace(
'yyy',
this.$t('trials:inspection:pullImage:unlimit')
)
} else {
message = message.replace(
'yyy',
`${this.timeFrame}${this.$t('trials:inspection:unit:day')}`
)
}
if (!this.MaxStudyCount) {
message = message.replace(
'zzz',
this.$t('trials:inspection:pullImage:unlimit')
)
} else {
message = message.replace(
'zzz',
`${this.MaxStudyCount}${this.$t('trials:inspection:unit:article')}`
)
}
message = message.replace('kkk', this.ModalityList.join(''))
return message
},
},
created() {
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
this.timeFrame = pacs.PacsSearchMaxDays
this.MaxStudyCount = pacs.MaxStudyCount
if (!f) {
this.handleReset()
}
},
// pacs
async cMoveVerify(data) {
try {
let res = await cMoveVerify(data)
if (res.IsSuccess) {
return res.Result
}
return false
} catch (err) {
console.log(err)
return false
}
},
async getList() {
if (!this.searchData.PacsDicomAEId)
return this.$message.warning(
this.$t('trials:inspection:pullImage:message:mustPacsDicomAEId')
)
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key]
})
if (this.StudyDate && this.StudyDate[0] && this.StudyDate[1]) {
data.StudyDate =
this.$moment(this.StudyDate[0]).format('YYYYMMDD') +
'-' +
this.$moment(this.StudyDate[1]).format('YYYYMMDD')
} else {
data.StudyDate = null
}
try {
this.loading = true
let res = await getCFindStudyList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result
this.total = res.Result.length
this.paging()
let MaxStudyCount = this.MaxStudyCount || 50
if (this.total >= MaxStudyCount) {
let message = this.$t(
'trials:inspection:pullImage:confirm:limit50'
).replace('xxx', MaxStudyCount)
this.$confirm(message, '', {
type: 'warning',
showCancelButton: false,
})
}
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
async getAEList(f = false, isFirst = false) {
let data = {
CalledAE: null,
IP: null,
Port: null,
PacsTypeEnum: 2,
IsTestOK: true,
PageIndex: 1,
PageSize: 1000,
SortField: 'CreateTime',
Asc: false,
}
try {
this.loading = true
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) {
this.searchData.PacsDicomAEId = this.AElist[0].Id
this.ModalityList = this.AElist[0].ModalityList
this.timeFrame = this.AElist[0].PacsSearchMaxDays
this.MaxStudyCount = this.AElist[0].MaxStudyCount
this.searchData.ModalitiesInStudyList = [this.ModalityList[0]]
this.StudyDate = [new Date(), new Date()]
} else {
this.pacsDicomAEIdChange(this.searchData.PacsDicomAEId, true)
}
if (!isFirst) {
this.getList()
}
}
}
} catch (err) {
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 = []
if (!this.list || this.list.length <= 0) return false
this.PageList = this.list.slice(
(this.PageIndex - 1) * this.PageSize,
this.PageIndex * this.PageSize
)
},
//
handleSearch() {
// this.searchData.PageIndex = 1
this.getAEList(true)
},
//
handleReset() {
this.reset()
this.getAEList(true)
},
//
reset() {
// this.searchData = defaultSearchData()
Object.keys(this.searchData).forEach((key) => {
if (key !== 'PacsDicomAEId') {
this.searchData[key] = null
}
})
// this.PatientBirthDate = []
this.StudyDate = []
// this.StudyTime = [new Date(new Date().getTime() - 10800000), new Date()]
},
//
handleSortByColumn(sort) {
if (sort.order === 'ascending') {
this.list.sort((a, b) => (a[sort.prop] > b[sort.prop] ? 1 : -1))
}
if (sort.order === 'descending') {
this.list.sort((a, b) => (b[sort.prop] > a[sort.prop] ? 1 : -1))
}
this.paging()
},
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],
}
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(
(item) => item.StudyInstanceUID
)
}
let r = await this.cMoveVerify(data)
if (!r) return false
let isPullList = []
Object.keys(r).forEach((key) => {
if (r[key]) {
isPullList.push(key)
}
})
let message = this.$t('trials:inspection:pullImage:confirm:pull')
let patientMessage = ''
if (isPullList.length > 0) {
isPullList.forEach((key) => {
patientMessage += `患者:${r[key].PatientName},检查申请号:${r[key].AccessionNumber}<br/>`
})
if (patientMessage) {
message =
patientMessage +
'<br/>' +
this.$t('trials:inspection:pullImage:message:isHasPull') +
'' +
message
}
}
let confirm = await this.$confirm(message, '', {
dangerouslyUseHTMLString: true,
})
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)
}
},
handleSelectionChange(val) {
this.multipleSelection = val
},
},
}
</script>
<style lang="scss" scoped>
.icon-i {
color: #67c23a;
cursor: pointer;
}
.refreshBtn {
// transform: rotate(0);
transition: 0.5s;
&:hover {
transform: rotate(180deg);
transition: 0.5s;
}
}
</style>
@@ -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>
@@ -0,0 +1,818 @@
<template>
<div>
<span class="title">
{{ $t('trials:inspection:title:pullImage') }}
<span>{{ tip }}</span>
</span>
<div class="search">
<el-form :inline="true" class="base-search-form">
<!-- TrialId -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:TrialId')">
<el-select v-model="searchData.TrialId" style="width: 140px" @change="searchData.PatientID = null">
<el-option v-for="(item) of trialList" :key="item.TrialId" :label="item.ExperimentName"
:value="item.TrialId">
</el-option>
</el-select>
</el-form-item>
<!-- pacsDicomAEId -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:pacsDicomAEId')">
<el-select v-model="searchData.PacsDicomAEId" style="width: 140px" @change="pacsDicomAEIdChange">
<el-option v-for="(item) of AElist" :key="item.Id" :label="item.CalledAE" :value="item.Id">
</el-option>
</el-select>
</el-form-item>
<!-- patientID -->
<el-form-item class="my_multiple" :label="$t('trials:inspection:pullImage:search:patientID')">
<el-select v-model="searchData.PatientID" style="width: 140px" clearable>
<el-option v-for="(item, index) of patientList" :key="index.PatientIdStr"
:label="item.PatientName" :value="item.PatientIdStr">
</el-option>
</el-select>
</el-form-item>
<!-- patientName -->
<!-- <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 style="width: 140px">
<el-option v-for="item in ModalityList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item> -->
<!-- studyDate -->
<!-- <el-form-item :label="$t('trials:inspection:pullImage:search:studyDate')">
<el-date-picker v-model="StudyDate" type="daterange" range-separator="至" start-placeholder="开始日期"
end-placeholder="结束日期" value-format="yyyyMMdd" :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">
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<!-- 拉取 -->
<el-button type="primary" :disabled="!multipleSelection || multipleSelection.length <= 0"
@click="openGroup({}, 2)">
{{ $t('trials:inspection:button:pull') }}
</el-button>
</el-form-item>
</el-form>
</div>
<!--检查列表-->
<el-table ref="viewStudyList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="PageList" stripe
height="100" @sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column type="index" width="50">
<template slot-scope="scope">
<span style="
display: flex;
align-items: center;
justify-content: flex-end;
">
<el-tooltip class="item" effect="dark" :content="$t('trials:inspection:pullImage:tip:has')"
placement="top" style="margin-right: 3px">
<i v-if="scope.row.IsStudyExist" class="el-icon-success icon-i"></i>
</el-tooltip>
<span>{{ scope.$index + 1 }}</span>
</span>
</template>
</el-table-column>
<!--patientID-->
<el-table-column prop="PatientID" :label="$t('trials:inspection:pullImage:table:patientID')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--patientName-->
<el-table-column prop="PatientName" :label="$t('trials:inspection:pullImage:table:patientName')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--patientSex-->
<el-table-column prop="PatientSex" :label="$t('trials:inspection:pullImage:table:patientSex')"
show-overflow-tooltip min-width="80" sortable="custom">
<template slot-scope="scope">
<span>{{ $fd('Sex', scope.row.PatientSex) }}</span>
</template>
</el-table-column>
<!--patientBirthDate-->
<el-table-column prop="PatientBirthDate" :label="$t('trials:inspection:pullImage:table:patientBirthDate')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--studyID-->
<!-- <el-table-column
prop="StudyID"
:label="$t('trials:inspection:pullImage:table:studyID')"
show-overflow-tooltip
min-width="120"
/> -->
<!--AccessionNumber-->
<el-table-column prop="AccessionNumber" :label="$t('trials:inspection:pullImage:table:AccessionNumber')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--modalitiesInStudy-->
<el-table-column prop="ModalitiesInStudy" :label="$t('trials:inspection:pullImage:table:modalitiesInStudy')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--studyDate-->
<el-table-column prop="StudyDate" :label="$t('trials:inspection:pullImage:table:studyDate')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--studyTime-->
<el-table-column prop="StudyTime" :label="$t('trials:inspection:pullImage:table:studyTime')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--bodyPartExamined-->
<!-- <el-table-column
prop="BodyPartExamined"
:label="$t('trials:inspection:pullImage:table:bodyPartExamined')"
show-overflow-tooltip
min-width="120"
sortable="custom"
/> -->
<!--studyDescription-->
<el-table-column prop="StudyDescription" :label="$t('trials:inspection:pullImage:table:studyDescription')"
show-overflow-tooltip min-width="120" sortable="custom" />
<!--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="120">
<template slot-scope="scope">
<el-button circle icon="el-icon-refresh" class="refreshBtn"
: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>
import Pagination from '@/components/Pagination'
import {
getCFindStudyList,
cmoveStudyList,
cMoveVerify,
getUserJoinedTrialPatientList
} from '@/api/inspection.js'
import { getDicomAEList } from '@/api/dicomAE.js'
import BaseModel from '@/components/BaseModel'
const defaultSearchData = () => {
return {
PacsDicomAEId: null,
PatientID: null,
PatientName: null,
// ModalitiesInStudyList: null,
StudyDate: null,
TrialId: null,
PatientSex: null,
PatientBirthDate: null,
StudyID: null,
StudyTime: null,
BodyPartExamined: null,
StudyDescription: null,
StudyInstanceUID: null,
AccessionNumber: null,
}
}
export default {
name: 'byTrials',
components: { Pagination, BaseModel },
props: {
calledAeList: {
required: true,
default: () => {
return []
},
},
callingAeList: {
required: true,
default: () => {
return []
},
},
},
data() {
return {
//
searchData: defaultSearchData(),
ModalityList: [],
timeFrame: null,
MaxStudyCount: null,
PatientBirthDate: [],
// StudyDate: [],
//
loading: false,
list: [],
PageList: [],
total: 0,
PageIndex: 1,
PageSize: 50,
AElist: [],
multipleSelection: [],
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: {
// pickerOptions() {
// return {
// shortcuts: [
// {
// text: this.$t('trials:inspection:pullImage:picker:today'),
// onClick: (picker) => {
// const end = new Date()
// const start = new Date()
// // picker.$emit('pick', [start, end])
// this.StudyDate = [start, end]
// },
// },
// {
// text: this.$t('trials:inspection:pullImage:picker:week'),
// onClick: (picker) => {
// const end = new Date()
// const start = new Date()
// if (!this.timeFrame || this.timeFrame > 3) {
// start.setTime(start.getTime() - 3600 * 1000 * 24 * 2)
// } else {
// start.setTime(
// start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
// )
// }
// // picker.$emit('pick', [start, end])
// this.StudyDate = [start, end]
// },
// },
// {
// text: this.$t('trials:inspection:pullImage:picker:month'),
// onClick: (picker) => {
// const end = new Date()
// const start = new Date()
// let month = this.$moment().subtract(1, 'months')
// let day = this.$moment().diff(month, 'day')
// if (!this.timeFrame || this.timeFrame > day) {
// start.setTime(start.getTime() - 3600 * 1000 * 24 * (day - 1))
// } else {
// start.setTime(
// start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
// )
// }
// // picker.$emit('pick', [start, end])
// this.StudyDate = [start, end]
// },
// },
// {
// text: this.$t('trials:inspection:pullImage:picker:trimester'),
// onClick: (picker) => {
// const end = new Date()
// const start = new Date()
// let month = this.$moment().subtract(3, 'months')
// let day = this.$moment().diff(month, 'day')
// if (!this.timeFrame || this.timeFrame > day) {
// start.setTime(start.getTime() - 3600 * 1000 * 24 * (day - 1))
// } else {
// start.setTime(
// start.getTime() - 3600 * 1000 * 24 * (this.timeFrame - 1)
// )
// }
// // picker.$emit('pick', [start, end])
// this.StudyDate = [start, end]
// },
// },
// ],
// disabledDate: (time) => {
// if (!this.timeFrame) return false
// let curDate = new Date().getTime()
// let three = this.timeFrame * 24 * 3600 * 1000
// let threeMonths = curDate - three
// return time.getTime() >= Date.now() || time.getTime() <= threeMonths
// },
// }
// },
tip() {
if (!this.searchData.PacsDicomAEId) return ''
let message = `( ${this.$t('trials:inspection:pullImage:PacsTip')} )`
message = message.replace(
'xxx',
this.AElist.find((item) => item.Id === this.searchData.PacsDicomAEId)
.CalledAE
)
if (!this.timeFrame) {
message = message.replace(
'yyy',
this.$t('trials:inspection:pullImage:unlimit')
)
} else {
message = message.replace(
'yyy',
`${this.timeFrame}${this.$t('trials:inspection:unit:day')}`
)
}
if (!this.MaxStudyCount) {
message = message.replace(
'zzz',
this.$t('trials:inspection:pullImage:unlimit')
)
} else {
message = message.replace(
'zzz',
`${this.MaxStudyCount}${this.$t('trials:inspection:unit:article')}`
)
}
message = message.replace('kkk', this.ModalityList.join(''))
return message
},
patientList() {
let arr = []
if (this.searchData.TrialId) {
arr = this.trialList.find(item => item.TrialId === this.searchData.TrialId).PatientList
}
return arr
}
},
created() {
this.getTrialList()
},
methods: {
//
async getTrialList() {
try {
let res = await getUserJoinedTrialPatientList()
if (res.IsSuccess) {
this.trialList = res.Result
if (!this.trialList || this.trialList.length <= 0) return false
this.searchData.TrialId = this.trialList[0].TrialId
this.getAEList(false, true)
}
} catch (err) {
console.log(err)
}
},
pacsDicomAEIdChange(val, f = false) {
let pacs = this.AElist.find((item) => item.Id === val)
this.ModalityList = pacs.ModalityList
this.timeFrame = pacs.PacsSearchMaxDays
this.MaxStudyCount = pacs.MaxStudyCount
if (!f) {
this.handleReset()
}
},
// pacs
async cMoveVerify(data) {
try {
let res = await cMoveVerify(data)
if (res.IsSuccess) {
return res.Result
}
return false
} catch (err) {
console.log(err)
return false
}
},
async getList() {
if (!this.searchData.TrialId) return false
if (!this.searchData.PacsDicomAEId)
return this.$message.warning(
this.$t('trials:inspection:pullImage:message:mustPacsDicomAEId')
)
let data = {}
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') +
// '-' +
// this.$moment(this.StudyDate[1]).format('YYYYMMDD')
// } 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)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result
this.total = res.Result.length
this.paging()
let MaxStudyCount = this.MaxStudyCount || 50
if (this.total >= MaxStudyCount) {
let message = this.$t(
'trials:inspection:pullImage:confirm:limit50'
).replace('xxx', MaxStudyCount)
this.$confirm(message, '', {
type: 'warning',
showCancelButton: false,
})
}
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
async getAEList(f = false, isFirst = false) {
let data = {
CalledAE: null,
IP: null,
Port: null,
PacsTypeEnum: 2,
IsTestOK: true,
PageIndex: 1,
PageSize: 1000,
SortField: 'CreateTime',
Asc: false,
}
try {
this.loading = true
let res = await getDicomAEList(data)
this.loading = false
if (res.IsSuccess) {
this.AElist = res.Result.CurrentPageData
if (this.AElist.length > 0) {
if (!f) {
this.searchData.PacsDicomAEId = this.AElist[0].Id
this.ModalityList = this.AElist[0].ModalityList
this.timeFrame = this.AElist[0].PacsSearchMaxDays
this.MaxStudyCount = this.AElist[0].MaxStudyCount
// this.searchData.ModalitiesInStudyList = [this.ModalityList[0]]
// this.StudyDate = [new Date(), new Date()]
} else {
this.pacsDicomAEIdChange(this.searchData.PacsDicomAEId, true)
}
if (!isFirst) {
this.getList()
}
}
}
} catch (err) {
console.log(err)
}
},
//
paging() {
this.PageList = []
if (!this.list || this.list.length <= 0) return false
this.PageList = this.list.slice(
(this.PageIndex - 1) * this.PageSize,
this.PageIndex * this.PageSize
)
},
//
handleSearch() {
// this.searchData.PageIndex = 1
this.getAEList(true)
},
//
handleReset() {
this.reset()
this.getAEList(true)
},
//
reset() {
// this.searchData = defaultSearchData()
Object.keys(this.searchData).forEach((key) => {
if (key !== 'PacsDicomAEId' && key !== 'TrialId') {
this.searchData[key] = null
}
})
// this.PatientBirthDate = []
// this.StudyDate = []
// this.StudyTime = [new Date(new Date().getTime() - 10800000), new Date()]
},
//
handleSortByColumn(sort) {
if (sort.order === 'ascending') {
this.list.sort((a, b) => (a[sort.prop] > b[sort.prop] ? 1 : -1))
}
if (sort.order === 'descending') {
this.list.sort((a, b) => (b[sort.prop] > a[sort.prop] ? 1 : -1))
}
this.paging()
},
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 && Object.keys(row).length !== 0) {
data.StudyInstanceUIDList = [row.StudyInstanceUID]
} else {
data.StudyInstanceUIDList = this.multipleSelection.map(
(item) => item.StudyInstanceUID
)
}
let r = await this.cMoveVerify(data)
if (!r) return false
let isPullList = []
Object.keys(r).forEach((key) => {
if (r[key]) {
isPullList.push(key)
}
})
let message = this.$t('trials:inspection:pullImage:confirm:pull')
let patientMessage = ''
if (isPullList.length > 0) {
isPullList.forEach((key) => {
patientMessage += `患者:${r[key].PatientName},检查申请号:${r[key].AccessionNumber}<br/>`
})
if (patientMessage) {
message =
patientMessage +
'<br/>' +
this.$t('trials:inspection:pullImage:message:isHasPull') +
'' +
message
}
}
let confirm = await this.$confirm(message, '', {
dangerouslyUseHTMLString: true,
})
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)
}
},
handleSelectionChange(val) {
this.multipleSelection = val
},
},
}
</script>
<style lang="scss" scoped>
.icon-i {
color: #67c23a;
cursor: pointer;
}
.refreshBtn {
// transform: rotate(0);
transition: 0.5s;
&:hover {
transform: rotate(180deg);
transition: 0.5s;
}
}
</style>
@@ -0,0 +1,76 @@
<template>
<el-dialog :visible.sync="visible" :close-on-click-modal="false" :fullscreen="true" custom-class="upload-dialog"
:before-close="beforeCloseStudyDig">
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane :label="$t('trials:inspection:pullImage:title:byPatient')" name="byPatient">
<byPatient :calledAeList="calledAeList" :callingAeList="callingAeList"
v-if="activeName === 'byPatient'" />
</el-tab-pane>
<el-tab-pane :label="$t('trials:inspection:pullImage:title:byTrials')" name="byTrials">
<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, byTool },
props: {
visible: {
required: true,
default: false,
},
calledAeList: {
required: true,
default: () => {
return []
},
},
callingAeList: {
required: true,
default: () => {
return []
},
},
},
data() {
return {
activeName: 'byPatient', // byPatient byTrials
}
},
methods: {
handleClick() { },
beforeCloseStudyDig() {
this.$setOpenWindow()
this.$emit('update:visible', false)
this.$emit('getList')
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__header {
padding: 0;
padding-top: 10px;
}
::v-deep .title {
line-height: 24px;
font-size: 18px;
color: #303133;
padding: 20px 0;
padding-bottom: 10px;
}
::v-deep .el-dialog__headerbtn {
z-index: 99;
}
</style>
@@ -1,142 +1,67 @@
<template>
<el-dialog
:visible.sync="visible"
:close-on-click-modal="false"
:fullscreen="true"
custom-class="upload-dialog"
:before-close="beforeCloseStudyDig"
>
<span slot="title"> </span>
<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="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
>
<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']">
</el-date-picker>
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t("common:button:search") }}
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
<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 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,
@@ -199,14 +130,14 @@ const defaultSearchData = () => {
StartTime: null,
EndTime: null,
PageIndex: 1,
PageSize: 10,
PageSize: 20,
Asc: false,
SortField: "StartTime",
};
};
SortField: 'StartTime',
}
}
export default {
name: "pushRecordList",
components: { Pagination },
name: 'pushRecordList',
components: { Pagination, BaseModel },
props: {
visible: {
required: true,
@@ -215,13 +146,13 @@ export default {
calledAeList: {
required: true,
default: () => {
return [];
return []
},
},
callingAeList: {
required: true,
default: () => {
return [];
return []
},
},
},
@@ -234,77 +165,88 @@ 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();
this.getList()
},
methods: {
view(row) {
this.detailData = JSON.parse(row.UploadJsonStr).UploadList
this.detail_model.visible = true
},
async getList() {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data[key] = this.searchData[key]
})
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.StartTime = this.$moment(this.dateValue[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
data.EndTime = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.StartTime = null;
data.EndTime = null;
data.StartTime = null
data.EndTime = null
}
try {
this.loading = true;
let res = await getSCPImageUploadList(data);
this.loading = false;
this.loading = true
let res = await getSCPImageUploadList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.reset();
this.getList();
this.reset()
this.getList()
},
//
reset() {
this.searchData = defaultSearchData();
this.dateValue = [];
this.searchData = defaultSearchData()
this.dateValue = []
},
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
beforeCloseStudyDig() {
this.$setOpenWindow();
this.$emit("update:visible", false);
this.$setOpenWindow()
this.$emit('update:visible', false)
},
//
image(item) {
let token = getToken();
let token = getToken()
const routeData = this.$router.resolve({
path: `/showdicom?studyId=${item.SCPStudyId}&TokenKey=${token}&type=Patient`,
});
let newWindow = window.open(routeData.href, "_blank");
this.$setOpenWindow(newWindow);
})
let newWindow = window.open(routeData.href, '_blank')
this.$setOpenWindow(newWindow)
},
},
};
}
</script>
@@ -6,22 +6,33 @@
custom-class="upload-dialog"
:before-close="beforeCloseStudyDig"
>
<div class="top">
<span slot="title">
<span
>{{ $t('trials:uploadDicomList:table:patientInfo') }}{{
Patient.PatientIdStr
}}{{ Patient.PatientName }}</span
>|<span>
{{
$t('trials:inspection:research-trials-list:table:joinTrialsNumber')
}}{{ total }}</span
></span
>
<!-- <div class="top">
<p>
<span
>{{ $t("trials:uploadDicomList:table:patientInfo") }}{{
>{{ $t('trials:uploadDicomList:table:patientInfo') }}{{
Patient.PatientIdStr
}}{{ Patient.PatientName }}</span
>|<span>
{{
$t("trials:inspection:research-trials-list:table:joinTrialsNumber")
$t('trials:inspection:research-trials-list:table:joinTrialsNumber')
}}{{ total }}</span
>
</p>
<!-- <el-button type="primary" @click="addTrials">
<el-button type="primary" @click="addTrials">
{{ $t("trials:inspection:button:addTrials") }}
</el-button> -->
</div>
</el-button>
</div> -->
<!--参与项目列表-->
<el-table
ref="researchTrialsList"
@@ -30,6 +41,7 @@
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
:default-sort="{ prop: 'CreateTime', order: 'descending' }"
>
<el-table-column type="index" width="40" />
@@ -90,7 +102,7 @@
sortable
>
<template slot-scope="scope">
<span>{{ $fd("sex", scope.row.Sex) }}</span>
<span>{{ $fd('Sex', scope.row.Sex) }}</span>
</template>
</el-table-column>
<!--状态-->
@@ -110,7 +122,7 @@
)
]
"
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
>{{ $fd('TrialStatusEnum', scope.row.TrialStatusStr) }}</el-tag
>
</template></el-table-column
>
@@ -145,23 +157,31 @@
</el-table>
<!-- 分页组件 -->
<!-- <pagination
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/> -->
/>
</el-dialog>
</template>
<script>
import Pagination from "@/components/Pagination";
import Pagination from '@/components/Pagination'
import {
getPatientJoinedTrialList,
deleteSubjectPatientBinding,
} from "@/api/inspection.js";
} from '@/api/inspection.js'
const defaultSearchData = () => {
return {
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: 'CreateTime',
}
}
export default {
name: "researchTrialsList",
name: 'researchTrialsList',
components: { Pagination },
props: {
visible: {
@@ -171,95 +191,105 @@ export default {
Patient: {
required: true,
default: () => {
return {};
return {}
},
},
},
created() {
this.getList();
this.getList()
},
data() {
return {
//
searchData: defaultSearchData(),
total: 0,
loading: false,
list: [],
};
}
},
methods: {
//
beforeCloseStudyDig() {
this.$emit("update:visible", false);
this.$emit('update:visible', false)
},
//
addTrials() {
this.$emit("update:visible", false);
this.$emit("handleOpenDialog", this.Patient, "add");
this.$emit('update:visible', false)
this.$emit('handleOpenDialog', this.Patient, 'add')
},
//
async getList() {
let data = {
PatientId: this.Patient.PatientId,
};
...this.searchData,
}
try {
this.loading = true;
let res = await getPatientJoinedTrialList(data);
this.loading = false;
this.loading = true
let res = await getPatientJoinedTrialList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result;
this.total = this.list.length;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
//
detail(item) {
this.$emit("update:visible", false);
this.$emit('update:visible', false)
let query = {
trialId: item.TrialId,
trialCode: item.Code,
researchProgramNo: item.ResearchProgramNo,
};
}
this.$router.push({
path: "/trials/trials-panel/subject/subject-list",
path: '/trials/trials-panel/subject/subject-list',
query,
});
})
},
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
//
async remove(item) {
try {
let confirm = await this.$confirm(
this.$t("trials:sitesList:message:removeSite"),
this.$t('trials:sitesList:message:removeSite'),
{
type: "warning",
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("recompose:button:cancel"),
confirmButtonText: this.$t('common:button:confirm'),
cancelButtonText: this.$t('recompose:button:cancel'),
}
);
if (confirm !== "confirm") return;
)
if (confirm !== 'confirm') return
let params = {
PatientId: this.Patient.PatientId,
SubjectId: item.SubjectId,
TrialId: item.TrialId,
};
this.loading = true;
let res = await deleteSubjectPatientBinding(params);
this.loading = false;
}
this.loading = true
let res = await deleteSubjectPatientBinding(params)
this.loading = false
if (res.IsSuccess) {
this.getList();
this.$message.success(this.$t("common:message:removedSuccessfully"));
this.$emit("getList");
this.getList()
this.$message.success(this.$t('common:message:removedSuccessfully'))
this.$emit('getList')
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
},
};
}
</script>
<style lang="scss" scoped>
.top {
@@ -49,7 +49,7 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 80px;
width: 130px;
"
>
{{ $t("trials:trials-list:table:sponsor") }}
@@ -1,193 +1,220 @@
<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="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
>
<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']">
</el-date-picker>
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t("common:button:search") }}
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
<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="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 { getToken } from "@/utils/auth";
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,
PatientId: null,
Asc: false,
SortField: "StudyTime",
};
};
SortField: 'StudyTime',
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: "viewStudyList",
components: { Pagination },
name: 'viewStudyList',
components: { Pagination, BaseModel },
props: {
visible: {
required: true,
@@ -196,7 +223,29 @@ export default {
Patient: {
required: true,
default: () => {
return {};
return {}
},
},
isAll: {
required: true,
default: false,
},
calledAeList: {
type: Array,
default: () => {
return []
},
},
callingAeList: {
type: Array,
default: () => {
return []
},
},
hospitalGroupList: {
type: Array,
default: () => {
return []
},
},
},
@@ -208,111 +257,200 @@ 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();
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 {
let confirm = await this.$confirm(
this.$t("trials:inspection:message:remove"),
this.$t('trials:inspection:message:remove'),
{
type: "warning",
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("common:button:cancel"),
confirmButtonText: this.$t('common:button:confirm'),
cancelButtonText: this.$t('common:button:cancel'),
}
);
if (confirm !== "confirm") return;
)
if (confirm !== 'confirm') return
let params = {
PatiendId: item.PatientId,
ScpStudyId: item.SCPStudyId,
};
let res = await deletePatientStudy(params);
}
let res = await deletePatientStudy(params)
if (res.IsSuccess) {
this.getList();
this.$emit("getList");
this.$message.success(this.$t("common:message:deletedSuccessfully"));
this.getList()
this.$emit('getList')
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
} catch (err) {
console.log(err);
console.log(err)
}
},
//
beforeCloseStudyDig() {
this.$setOpenWindow();
this.$emit("update:visible", false);
this.$setOpenWindow()
this.$emit('update:visible', false)
},
//
async getList() {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data.PatientId = this.Patient.PatientId;
data[key] = this.searchData[key]
})
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"
);
'YYYY-MM-DD HH:mm:ss'
)
data.LatestStudyTime = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.EarliestStudyTime = null;
data.LatestStudyTime = null;
data.EarliestStudyTime = null
data.LatestStudyTime = null
}
try {
this.loading = true;
let res = await getPatientStudyList(data);
this.loading = false;
this.loading = true
let res = await getPatientStudyList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.reset();
this.getList();
this.reset()
this.getList()
},
//
reset() {
this.searchData = defaultSearchData();
this.dateValue = [];
this.searchData = defaultSearchData()
this.dateValue = []
},
//
image(item) {
let token = getToken();
let token = getToken()
const routeData = this.$router.resolve({
path: `/showdicom?studyId=${item.SCPStudyId}&TokenKey=${token}&type=Patient`,
});
let newWindow = window.open(routeData.href, "_blank");
this.$setOpenWindow(newWindow);
})
let newWindow = window.open(routeData.href, '_blank')
this.$setOpenWindow(newWindow)
},
//
report() {},
report() { },
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
},
};
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>
+464 -290
View File
@@ -5,97 +5,84 @@
<el-form :inline="true" class="base-search-form">
<!-- 患者ID/患者姓名 -->
<el-form-item :label="$t('trials:uploadDicomList:table:pId')">
<el-input
v-model="searchData.PatientIdStr"
style="width: 100px"
clearable
/>
<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-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-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-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-list:table:researchName')">
<el-input
v-model="searchData.ExperimentName"
style="width: 100px"
clearable
/>
<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="开始日期"
end-placeholder="结束日期"
: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>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t("common:button:search") }}
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
<el-form-item>
<!-- 推送记录 -->
<el-button type="primary" @click="handleOpenDialog({}, 'push')">
{{ $t("common:button:push") }}
{{ $t('common:button:push') }}
</el-button>
</el-form-item>
<el-form-item>
<!-- pacs拉取 -->
<el-button type="primary" @click="handleOpenDialog({}, 'pull')"
v-hasPermi="['trials:trialsInspection:pullPACS']">
{{ $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>
@@ -103,103 +90,53 @@
<!-- 检查列表 -->
<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" />
<el-table ref="inspectionList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
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>
<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="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="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"
>
<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>
<span>{{ $fd('Sex', scope.row.PatientSex) }}</span>
</template>
</el-table-column>
<!--Called AE-->
<el-table-column
prop="CalledAEList"
:label="$t('trials:inspection:table:CalledAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CalledAEList" :label="$t('trials:inspection:table:CalledAE')" show-overflow-tooltip
min-width="120">
<template slot-scope="scope">
<span
v-for="(item, index) in scope.row.CalledAEList"
:key="`CalledAEList${index}`"
>{{
index === scope.row.CalledAEList.length - 1 ? item : `${item}, `
}}</span
>
<span v-for="(item, index) in scope.row.CalledAEList" :key="`CalledAEList${index}`">{{
index === scope.row.CalledAEList.length - 1 ? item : `${item}, `
}}</span>
</template>
</el-table-column>
<!--Calling AE-->
<el-table-column
prop="CallingAEList"
:label="$t('trials:inspection:table:CallingAE')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="CallingAEList" :label="$t('trials:inspection:table:CallingAE')" show-overflow-tooltip
min-width="120">
<template slot-scope="scope">
<span
v-for="(item, index) in scope.row.CallingAEList"
:key="`CallingAEList${index}`"
>{{
index === scope.row.CallingAEList.length - 1
? item
: `${item}, `
}}</span
>
<span v-for="(item, index) in scope.row.CallingAEList" :key="`CallingAEList${index}`">{{
index === scope.row.CallingAEList.length - 1
? item
: `${item}, `
}}</span>
</template>
</el-table-column>
<!-- 研究名称 -->
<el-table-column
prop="TrialList"
:label="$t('trials:trials-list:table:researchName')"
show-overflow-tooltip
min-width="120"
>
<el-table-column prop="TrialList" :label="$t('trials:trials-list:table:researchName')" show-overflow-tooltip
min-width="120">
<template slot-scope="scope">
<el-button
type="text"
@click="handleOpenDialog(scope.row, 'research')"
v-for="(item, index) in scope.row.TrialList"
:key="`TrialList${index}`"
>
<el-button type="text" @click="handleOpenDialog(scope.row, 'research')"
v-for="(item, index) in scope.row.TrialList" :key="`TrialList${index}`">
<span>{{
index === scope.row.TrialList.length - 1
? `${item.ExperimentName}${item.VisitCount}`
@@ -209,116 +146,105 @@
<!-- <span v-else>{{ scope.row.VisitName }}</span> -->
</template>
</el-table-column>
<!-- 检查数 -->
<el-table-column
prop="StudyCount"
:label="$t('trials:studyList:table:count')"
show-overflow-tooltip
min-width="100"
sortable="custom"
>
<!--课题组-->
<el-table-column prop="ViewHospitalGroupList" :label="$t('trials:trials-myinfo:form:StudyHospitalGroupList')"
show-overflow-tooltip min-width="100">
<template slot-scope="scope">
<el-button
v-if="scope.row.StudyCount >= 1"
type="text"
@click="handleOpenDialog(scope.row, 'study')"
>
<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">
<template slot-scope="scope">
<el-button v-if="scope.row.StudyCount >= 1" type="text" @click="handleOpenDialog(scope.row, 'study')">
<span>{{ scope.row.StudyCount }}</span>
</el-button>
<span v-else>{{ scope.row.StudyCount }}</span>
</template>
</el-table-column>
<!--最新接收时间-->
<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 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
v-hasPermi="['trials:trialsInspection:addTrials']"
icon="el-icon-plus"
:title="$t('trials:inspection:button:addTrials')"
@click.stop="handleOpenDialog(scope.row, 'add')"
/>
<el-button
<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"
v-hasPermi="['trials:trialsInspection:delPatient']"
:title="$t('trials:inspection:button:delete')"
@click.stop="deletePatientStudyAllData(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>
<!--研究项目列表-->
<researchTrialsList
v-if="researchTrialsVisible"
:visible.sync="researchTrialsVisible"
:Patient="selectPatient"
@getList="getList"
@handleOpenDialog="handleOpenDialog"
/>
<researchTrialsList v-if="researchTrialsVisible" :visible.sync="researchTrialsVisible" :Patient="selectPatient"
@getList="getList" @handleOpenDialog="handleOpenDialog" />
<!--可加入项目列表-->
<addTrialsList
v-if="addTrialsVisible"
:visible.sync="addTrialsVisible"
:Patient="selectPatient"
@getList="getList"
@handleOpenDialog="handleOpenDialog"
/>
<addTrialsList v-if="addTrialsVisible" :visible.sync="addTrialsVisible" :Patient="selectPatient" @getList="getList"
@handleOpenDialog="handleOpenDialog" />
<!--查看检查列表-->
<viewStudyList
v-if="studyTrialsVisible"
:visible.sync="studyTrialsVisible"
:Patient="selectPatient"
@getList="getList"
/>
<viewStudyList v-if="studyTrialsVisible" :visible.sync="studyTrialsVisible" :Patient="selectPatient"
:isAll="studyAll" :calledAeList="calledAeList" :callingAeList="callingAeList"
:hospitalGroupList="hospitalGroupList" @getList="getList"
@getDownloadPatientStudyInfo="getDownloadPatientStudyInfo" />
<!--推送记录列表-->
<pushRecordList
v-if="pushTrialsVisible"
:visible.sync="pushTrialsVisible"
:calledAeList="calledAeList"
:callingAeList="callingAeList"
/>
<pushRecordList v-if="pushTrialsVisible" :visible.sync="pushTrialsVisible" :calledAeList="calledAeList"
:callingAeList="callingAeList" />
<!--pacs拉取列表-->
<pullImage v-if="pullTrialsVisible" :visible.sync="pullTrialsVisible" :calledAeList="calledAeList"
: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>
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import researchTrialsList from "./components/research-trials-list";
import addTrialsList from "./components/add-trials-list";
import viewStudyList from "./components/view-study-list";
import pushRecordList from "./components/push-record-list";
import { getPatientList, deletePatientStudyAllData } from "@/api/inspection.js";
import { getDicomCalledAEList, getDicomCallingAEList } from "@/api/dicomAE.js";
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import researchTrialsList from './components/research-trials-list'
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, 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,
@@ -326,16 +252,17 @@ const defaultSearchData = () => {
CalledAEList: [],
callingAE: null,
ExperimentName: null,
HospitalGroupIdList: [],
Asc: false,
BeginPushTime: null,
EndPushTime: null,
SortField: "LatestPushTime",
SortField: 'LatestPushTime',
PageIndex: 1,
PageSize: 10,
};
};
PageSize: 20,
}
}
export default {
name: "inspection",
name: 'inspection',
components: {
BaseContainer,
Pagination,
@@ -343,6 +270,8 @@ export default {
addTrialsList,
viewStudyList,
pushRecordList,
pullImage,
downloadRecord
},
data() {
return {
@@ -355,6 +284,9 @@ export default {
total: 0,
loading: false,
list: [],
multipleSelection: [],
downloadId: null,
RecordVisible: false,
//
selectPatient: {},
//
@@ -365,117 +297,359 @@ export default {
studyTrialsVisible: false,
//
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.getDicomCalledAEList()
this.getDicomCallingAEList()
this.getList()
this.getHospitalGroupList()
},
methods: {
//
async deletePatientStudyAllData(item) {
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 confirm = await this.$confirm(
this.$t("trials:inspection:message:remove"),
{
type: "warning",
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("common:button:cancel"),
}
);
if (confirm !== "confirm") return;
let params = {
PatientId: item.PatientId,
};
let res = await deletePatientStudyAllData(params);
if (res.IsSuccess) {
this.getList();
this.$message.success(this.$t("common:message:removedSuccessfully"));
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);
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();
let res = await getDicomCalledAEList()
if (res.IsSuccess) {
this.calledAeList = res.Result;
this.calledAeList = res.Result
}
} catch (err) {
console.log(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 {
let confirm = await this.$confirm(
this.$t('trials:inspection:message:remove'),
{
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: this.$t('common:button:confirm'),
cancelButtonText: this.$t('common:button:cancel'),
}
)
if (confirm !== 'confirm') return
let params = {
PatientId: item.PatientId,
}
let res = await deletePatientStudyAllData(params)
if (res.IsSuccess) {
this.getList()
this.$message.success(this.$t('common:message:removedSuccessfully'))
}
} catch (err) {
console.log(err)
}
},
// callingAE
async getDicomCallingAEList() {
try {
let res = await getDicomCallingAEList();
let res = await getDicomCallingAEList()
if (res.IsSuccess) {
this.callingAeList = res.Result;
this.callingAeList = res.Result
}
} catch (err) {
console.log(err);
console.log(err)
}
},
//
async getList() {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data[key] = this.searchData[key]
})
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.BeginPushTime = this.$moment(this.dateValue[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
data.EndPushTime = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.BeginPushTime = null;
data.EndPushTime = null;
data.BeginPushTime = null
data.EndPushTime = null
}
try {
this.loading = true;
let res = await getPatientList(data);
this.loading = false;
this.loading = true
let res = await getPatientList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
console.log(err);
console.log(err)
}
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = defaultSearchData();
this.$refs.inspectionList.clearSort();
this.dateValue = [];
this.getList();
this.searchData = defaultSearchData()
this.$refs.inspectionList.clearSort()
this.dateValue = []
this.getList()
},
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
//
handleOpenDialog(item, key) {
this[`${key}TrialsVisible`] = true;
this.selectPatient = item;
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) => {
window.location.reload()
});
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-progress {
display: flex;
align-items: center;
}
</style>
@@ -1,131 +1,82 @@
<template>
<div class="notice-marquee_wrapper">
<marquee
ref="mar"
hspace="0"
direction="left"
width="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 || [];
},
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;
}
@@ -1,73 +1,52 @@
<template>
<div class="trials-navbar" style="position: relative">
<div class="leftMenu">
<img
v-if="language === 'zh'"
:src="
hospital.HospitalLogoPath
? OSSclientConfig.basePath + hospital.HospitalLogoPath
: logoImg
"
alt=""
/>
<img v-else src="@/assets/zzlogo3.png" alt="" />
<!-- <img v-if="language === 'zh' && hospital.HospitalLogoPath" -->
<img v-if="hospital.HospitalLogoPath" :src="OSSclientConfig.basePath + hospital.HospitalLogoPath"
crossOrigin="anonymous" alt="" :class="{ img_en: NODE_ENV === 'usa' }"
:style="`max-height:50px;max-width:${config.logoScale.page * 50}px`" />
<div v-else style="width: 170px;"></div>
<!-- <img v-else src="@/assets/zzlogo3.png" alt="" /> -->
<span style="white-space: nowrap">
<!-- 中心影像系统EICS -->
{{ $t("trials:trials:title:eics") }}
{{ $t('trials:trials:title:eics') }}
</span>
</div>
<div class="center-menu">
<NoticeMarquee />
</div>
<div class="right-menu">
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
size="mini"
@select="handleSelect"
>
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" size="mini" @select="handleSelect">
<!-- <el-menu-item v-if="!hasPermi(['role:air', 'role:rpm', 'role:radmin', 'role:rcrc', 'role:rir'])" index="1">
<i class="el-icon-odometer" /> -->
<!-- 工作台 -->
<!-- <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>
<span slot="title">{{ $t('trials:menuTitle:inspection') }}</span>
</el-menu-item>
<el-menu-item
v-if="!hasPermi(['role:zys'])"
index="2"
:disabled="TotalNeedSignSystemDocCount !== 0"
>
<el-menu-item v-if="!hasPermi(['role:zys'])" index="2" :disabled="TotalNeedSignSystemDocCount !== 0">
<i class="el-icon-box" />
<!-- 我的项目 -->
<span slot="title">
{{ $t("trials:tab:trials") }}
{{ $t('trials:tab:trials') }}
</span>
</el-menu-item>
<el-menu-item
v-if="
!hasPermi([
'role:air',
'role:rpm',
'role:radmin',
'role:rcrc',
'role:rir',
'role:zys',
'role:qa',
])
"
index="3"
>
<el-menu-item v-if="
!hasPermi([
'role:air',
'role:rpm',
'role:radmin',
'role:rcrc',
'role:rir',
'role:zys',
])
" index="3">
<i class="el-icon-chat-dot-square" />
<!-- 通知消息 -->
<span slot="title">{{ $t("trials:tab:notice") }}</span>
<span slot="title">{{ $t('trials:tab:notice') }}</span>
</el-menu-item>
<el-submenu index="4" class="my_info">
@@ -79,148 +58,242 @@
</span>
<!-- 账户信息 -->
<el-menu-item v-if="!hasPermi(['role:air'])" index="4-2">{{
$t("trials:trials-myinfo:title:accountInfo")
$t('trials:trials-myinfo:title:accountInfo')
}}</el-menu-item>
<!-- 管理后台 -->
<el-menu-item
v-if="hasPermi(['role:dev', 'role:oa', 'role:admin'])"
index="4-4"
>{{ $t("trials:trials-myinfo:title:system") }}</el-menu-item
>
<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">{{
$t('trials:trials-myinfo:title:toggleRole')
}}</el-menu-item>
<!-- 退出 -->
<el-menu-item index="4-3">{{
$t("trials:trials-myinfo:button:loginout")
$t('trials:trials-myinfo:button:loginout')
}}</el-menu-item>
</el-submenu>
</el-menu>
<!-- <TopLang />-->
<TopLang v-if="isDev" />
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
@save="loginByRole" />
</div>
</div>
</template>
<script>
import { loginOut } from "@/api/user";
import { mapGetters, mapMutations } from "vuex";
import TopLang from "./topLang";
import NoticeMarquee from "./noticeMarquee";
import { getHospital } from "@/api/hospital.js";
import logoImg from "@/assets/zzlogo2.png";
import { loginOut } from '@/api/user'
import { mapGetters, mapMutations } from 'vuex'
import TopLang from './topLang'
import NoticeMarquee from './noticeMarquee'
import { getHospital } from '@/api/hospital.js'
import logoImg from '@/assets/zzlogo2.png'
import { resetRouter } from '@/router'
import toggleRole from '@/components/toggleRole'
export default {
components: { TopLang, NoticeMarquee },
components: { TopLang, NoticeMarquee, toggleRole },
data() {
return {
logoImg,
activeIndex: "2",
config: WINDOW_CONFIG,
NODE_ENV: process.env.NODE_ENV, // process.env.NODE_ENV
activeIndex: '2',
isReviewer: false,
userTypeShortName: zzSessionStorage.getItem("userTypeShortName"),
notice: "",
// userTypeShortName: zzSessionStorage.getItem('userTypeShortName'),
notice: '',
hospital: {
HospitalLogoPath: null,
HospitalName: null,
},
};
toggleRoleVisible: false,
toggleRoleLoading: false,
}
},
computed: {
...mapGetters([
"sidebar",
"name",
"userName",
"device",
"TotalNeedSignSystemDocCount",
"language",
'sidebar',
'name',
'userName',
'device',
'TotalNeedSignSystemDocCount',
'language',
'userTypeShortName'
]),
roles() {
return this.$store.state.user.roles
},
hasRole() {
return (
this.roles &&
this.roles.length > 1 &&
this.roles.filter((item) => !item.IsUserRoleDisabled).length > 1
)
},
isDev() {
return process.env.VUE_APP_OSS_PATH === "/hir_test/dist"
},
isEN() {
return this.$i18n.locale !== 'zh'
}
},
watch: {
$route(v) {
this.changeRoute(v);
this.changeRoute(v)
},
},
created() {
this.isReviewer = JSON.parse(zzSessionStorage.getItem("IsReviewer"));
this.changeRoute(this.$route);
this.getInfo();
// this.isReviewer = JSON.parse(zzSessionStorage.getItem('IsReviewer'))
this.changeRoute(this.$route)
this.getInfo()
this.$store.dispatch('user/getUserInfo')
},
methods: {
...mapMutations({ setLanguage: "lang/setLanguage" }),
...mapMutations({ setLanguage: 'lang/setLanguage' }),
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', { userRoleId })
.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: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
this.$message.warning(this.$t('login:message:login2'))
}
})
.catch((err) => {
this.toggleRoleLoading = false
})
} else {
this.toggleRoleLoading = false
}
})
.catch(() => {
this.toggleRoleLoading = false
})
},
//
async getInfo() {
try {
let res = await getHospital();
let res = await getHospital()
if (res.IsSuccess) {
Object.keys(this.hospital).forEach((key) => {
this.hospital[key] = res.Result[key];
});
this.hospital[key] = res.Result[key]
})
}
} catch (err) {
console.log(err);
console.log(err)
}
},
changeRoute(v) {
if (v.path === "/trials/trials-inspection") {
this.activeIndex = "1";
if (v.path === '/trials/trials-inspection') {
this.activeIndex = '1'
}
if (
v.path === "/trials/trials-list" ||
~v.path.indexOf("/trials/trials-panel")
v.path === '/trials/trials-list' ||
~v.path.indexOf('/trials/trials-panel')
) {
this.activeIndex = "2";
this.activeIndex = '2'
}
if (v.path === "/trials/trials-notice") {
this.activeIndex = "3";
if (v.path === '/trials/trials-notice') {
this.activeIndex = '3'
}
if (v.path === "/trials/trials-myinfo") {
this.activeIndex = "4-2";
if (v.path === '/trials/trials-myinfo') {
this.activeIndex = '4-2'
}
},
handleSelect(key, keyPath) {
switch (key) {
case "4-2":
this.go("/trials/trials-myinfo");
break;
case "4-3":
this.logout();
break;
case "4-4":
this.go("/system");
break;
case "1":
this.go("/trials/trials-inspection");
break;
case "2":
if (~this.$route.path.indexOf("/trials/trials-panel")) {
return;
case '4-2':
this.go('/trials/trials-myinfo')
break
case '4-3':
this.logout()
break
case '4-4':
this.go('/system')
break
case '4-5':
this.$store.dispatch('user/getUserInfo').then((res) => {
this.toggleRoleVisible = true
})
break
case '1':
this.go('/trials/trials-inspection')
break
case '2':
if (~this.$route.path.indexOf('/trials/trials-panel')) {
return
}
var lastWorkbench = zzSessionStorage.getItem("lastWorkbench");
var lastWorkbench = zzSessionStorage.getItem('lastWorkbench')
if (lastWorkbench) {
this.go(lastWorkbench);
this.go(lastWorkbench)
} else {
this.go("/trials/trials-list");
this.go('/trials/trials-list')
}
break;
case "3":
this.go("/trials/trials-notice");
break;
break
case '3':
this.go('/trials/trials-notice')
break
}
},
toggleSideBar() {
this.$store.dispatch("app/toggleSideBar");
this.$store.dispatch('app/toggleSideBar')
},
async logout() {
await loginOut();
await this.$store.dispatch("user/logout");
this.$router.push(`/login`);
this.$i18n.locale = "zh";
this.setLanguage("zh");
this.$updateDictionary();
// await loginOut()
await this.$store.dispatch('user/logout')
this.$router.push(`/login`)
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
},
go(value) {
this.$router.push({ path: value });
this.$router.push({ path: value })
},
account() {
this.$router.push({ name: "Account" });
this.$router.push({ name: 'Account' })
},
},
};
}
</script>
<style lang="scss" scoped>
@@ -232,33 +305,46 @@ export default {
overflow: hidden;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.el-breadcrumb__item {
font-size: 16px;
}
.leftMenu {
display: flex;
align-items: center;
padding-left: 20px;
img {
height: 28px;
// max-height: 50px;
margin-right: 10px;
// max-width: 170px;
}
// .img_en {
// height: 36px;
// min-width: 10px;
// }
span {
font-size: 20px;
position: relative;
top: -1px;
}
}
.right-menu,
.center-menu {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100%;
// line-height: 70px;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
@@ -276,9 +362,11 @@ export default {
}
}
}
.avatar-container {
display: inline-block;
margin-right: 200px;
.user-avatar {
margin-top: 5px;
width: 40px;
@@ -286,12 +374,15 @@ export default {
border-radius: 10px;
}
}
.dropdown-container {
cursor: pointer;
.el-icon-caret-bottom {
font-size: 12px;
}
}
.el-dropdown-link {
color: #999c9e;
cursor: pointer;
@@ -300,7 +391,7 @@ export default {
}
</style>
<style>
.el-menu--horizontal > .my_info.el-submenu .el-submenu__icon-arrow {
.el-menu--horizontal>.my_info.el-submenu .el-submenu__icon-arrow {
margin-top: 0;
}
</style>
@@ -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,53 +1,43 @@
<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"
>
<el-dialog v-dialogDrag :visible.sync="visible" :close-on-click-modal="false"
: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>
<!-- 单位名称 -->
<el-form-item
:label="$t('trials:trials-list:activate:organizationName')"
>
<el-form-item :label="$t('trials:trials-list:activate:organizationName')">
<span>{{ form.HospitalName }}</span>
</el-form-item>
<!-- 机构编码 -->
<el-form-item :label="$t('trials:trials-list:activate:hospitalCode')">
<span>{{ form.HospitalCode }}</span>
</el-form-item>
<!-- 项目编号 -->
<el-form-item :label="$t('trials:trials-list:table:trialId')">
<span>{{ form.TrialCode }}</span>
</el-form-item>
<!-- 评估标准 -->
<el-form-item
:label="$t('trials:trials-list:activate:evaluationCriteria')"
>
<el-form-item :label="$t('trials:trials-list:activate:evaluationCriteria')">
<span>{{
form.CriterionTypeList.map((item) =>
$fd("CriterionType", Number(item))
).join(",")
}}</span>
</el-form-item>
<!-- 项目码 -->
<el-form-item :label="$t('trials:trials-list:table:trialGuid')">
<span>{{ form.TrialId }}</span>
</el-form-item>
<!-- 机器码 -->
<el-form-item :label="$t('trials:trials-list:table:CreateUserId')">
<span>{{ form.CreateUserId }}</span>
</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 :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')">
@@ -58,47 +48,23 @@
<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
>
<span class="copy" style="margin-left: 10px" @click.stop="getCode">{{ $t("trials:reading:button:download")
}}</span>
</p>
</el-form-item>
<!-- 激活码 -->
<el-form-item
:label="$t('trials:trials-list:form:activateCode')"
prop="Activate"
>
<el-form-item :label="$t('trials:trials-list:form:activateCode')" prop="Activate">
<el-input v-model="form.Activate" :disabled="isActivate" />
<input
type="file"
id="uploadFileInp"
@change="uploadFile"
style="display: none"
/>
<label
class="copy"
style="margin-left: 10px"
for="uploadFileInp"
v-if="!isActivate"
>{{ $t("trials:activate:button:upload") }}</label
>
<span
v-if="form.Activate"
class="copy"
@click.stop="getActivationCodeInfo"
style="margin-left: 10px"
>{{ $t("trials:reviewTrack:impactList:save") }}</span
>
<input type="file" id="uploadFileInp" @change="uploadFile" style="display: none" />
<label class="copy" style="margin-left: 10px" for="uploadFileInp" v-if="!isActivate">{{
$t("trials:activate:button:upload") }}</label>
<span v-if="form.Activate" class="copy" @click.stop="getActivationCodeInfo" style="margin-left: 10px">{{
$t("trials:reviewTrack:impactList:save") }}</span>
</el-form-item>
<div v-if="isActivate">
<p class="title">{{ $t("trials:activate:Message") }}</p>
<!-- 单位名称 -->
<el-form-item
:label="$t('trials:trials-list:activate:organizationName')"
>
<el-form-item :label="$t('trials:trials-list:activate:organizationName')">
<span>{{ ActivateData.HospitalName }}</span>
</el-form-item>
<!-- 项目编号 -->
@@ -106,9 +72,7 @@
<span>{{ ActivateData.TrialCode }}</span>
</el-form-item>
<!-- 评估标准 -->
<el-form-item
:label="$t('trials:trials-list:activate:evaluationCriteria')"
>
<el-form-item :label="$t('trials:trials-list:activate:evaluationCriteria')">
<span>{{
ActivateData.CriterionTypeList.map((item) =>
$fd("CriterionType", Number(item))
@@ -116,35 +80,19 @@
}}</span>
</el-form-item>
<!-- 授权时长 -->
<el-form-item
:label="$t('trials:trials-list:activate:durationAuthorized')"
>
<el-form-item :label="$t('trials:trials-list:activate:durationAuthorized')">
<span>{{ ActivateData.PurchaseDuration }}</span>
</el-form-item>
</div>
</div>
<div
class="base-dialog-footer"
style="text-align: right; margin-top: 10px"
>
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
<el-form-item>
<!-- 取消 -->
<el-button
:disabled="btnLoading"
size="small"
type="primary"
@click="handleCancel"
>
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancel">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button
size="small"
type="primary"
:disabled="!isActivate"
:loading="btnLoading"
@click="handleSave"
>
<el-button size="small" type="primary" :disabled="!isActivate" :loading="btnLoading" @click="handleSave">
{{ $t("trials:trials-list:action:activate") }}
</el-button>
</el-form-item>
@@ -212,6 +160,11 @@ export default {
timer: null,
};
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
}
},
created() {
this.getTrialAuthorizationInfo();
},
@@ -360,6 +313,7 @@ export default {
padding-bottom: 10px;
padding-top: 0;
}
.Authorization {
width: 70%;
display: inline-block;
@@ -367,25 +321,30 @@ export default {
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;
}
+91 -275
View File
@@ -5,51 +5,26 @@
<el-form :inline="true">
<!-- 项目类型 -->
<el-form-item :label="$t('trials:trials-list:form:trialType')">
<el-select
v-model="searchData.trialType"
style="width: 150px"
clearable
>
<el-option
v-for="item in $d.TrialType"
:key="item.id"
:label="item.label"
:value="item.value"
/>
<el-select v-model="searchData.trialType" style="width: 150px" clearable>
<el-option v-for="item in $d.TrialType" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 项目编号 -->
<el-form-item :label="$t('trials:trials-list:table:trialId')">
<el-input
v-model="searchData.TrialCode"
style="width: 100px"
clearable
/>
<el-input v-model="searchData.TrialCode" style="width: 100px" clearable />
</el-form-item>
<!-- 研究方案号 -->
<el-form-item :label="$t('trials:trials-list:table:researchNumber')">
<el-input
v-model="searchData.ResearchProgramNo"
style="width: 100px"
clearable
/>
<el-input v-model="searchData.ResearchProgramNo" style="width: 100px" clearable />
</el-form-item>
<!-- 试验名称 -->
<el-form-item :label="$t('trials:trials-list:table:experimentName')">
<el-input
v-model="searchData.ExperimentName"
style="width: 100px"
clearable
/>
<el-input v-model="searchData.ExperimentName" style="width: 100px" clearable />
</el-form-item>
<!-- Sponsor -->
<el-form-item :label="$t('trials:trials-list:table:sponsor')">
<el-input
v-model="searchData.SponsorName"
style="width: 100px"
clearable
/>
<el-input v-model="searchData.SponsorName" style="width: 100px" clearable />
</el-form-item>
<el-form-item>
@@ -58,11 +33,7 @@
{{ $t("common:button:search") }}
</el-button>
<!-- Reset -->
<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>
<!-- Export -->
@@ -79,12 +50,7 @@
</el-form>
<span style="margin-left: auto">
<!-- New -->
<el-button
v-hasPermi="['trials:trials-list:new']"
icon="el-icon-plus"
type="primary"
@click="handleNew"
>
<el-button v-hasPermi="['trials:trials-list:new']" icon="el-icon-plus" type="primary" @click="handleNew">
{{ $t("common:button:new") }}
</el-button>
</span>
@@ -92,123 +58,59 @@
<!-- 项目列表 -->
<template slot="main-container">
<el-table
v-adaptive="{ bottomOffset: 60 }"
v-loading="listLoading"
:data="list"
stripe
height="100"
@sort-change="handleSortChange"
@row-click="handleDetail"
:default-sort="{ prop: 'createTime', order: 'descending' }"
>
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="listLoading" :data="list" stripe height="100"
@sort-change="handleSortChange" @row-click="handleDetail"
:default-sort="{ prop: 'createTime', order: 'descending' }">
<!-- <el-table-column type="selection" align="left" width="45" /> -->
<el-table-column width="40">
<template slot-scope="scope">
<i
v-if="!scope.row.AuthorizationEncrypt"
class="el-icon-warning-outline"
:title="$t('trials:trials-list:tipMessage:tipOne')"
style="color: red; font-size: 20px"
></i>
<i
v-if="
scope.row.AuthorizationEncrypt &&
scope.row.AuthorizationDate &&
!trialExpired(scope.row.AuthorizationDate, 15)
"
class="el-icon-warning-outline"
:title="$t('trials:trials-list:tipMessage:tipTwo')"
style="color: #e6a23c; font-size: 20px"
></i>
<i
v-if="
scope.row.AuthorizationEncrypt &&
scope.row.AuthorizationDate &&
!trialExpired(scope.row.AuthorizationDate)
"
class="el-icon-warning-outline"
:title="$t('trials:trials-list:tipMessage:tipThree')"
style="color: red; font-size: 20px"
></i>
<i v-if="!scope.row.AuthorizationEncrypt" class="el-icon-warning-outline"
:title="$t('trials:trials-list:tipMessage:tipOne')" style="color: red; font-size: 20px"></i>
<i v-else-if="
scope.row.AuthorizationEncrypt &&
scope.row.AuthorizationDate &&
!trialExpired(scope.row.AuthorizationDate)
" class="el-icon-warning-outline" :title="$t('trials:trials-list:tipMessage:tipThree')"
style="color: red; font-size: 20px"></i>
<i v-else-if="
scope.row.AuthorizationEncrypt &&
scope.row.AuthorizationDate &&
!trialExpired(scope.row.AuthorizationDate, 15)
" class="el-icon-warning-outline" :title="$t('trials:trials-list:tipMessage:tipTwo')"
style="color: #e6a23c; font-size: 20px"></i>
</template>
</el-table-column>
<el-table-column
prop="trialType"
:label="$t('trials:trials-list:form:trialType')"
show-overflow-tooltip
>
<el-table-column prop="trialType" :label="$t('trials:trials-list:form:trialType')" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ $fd("TrialType", scope.row.TrialType) }}</span>
</template>
</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="Sponsor"
:label="$t('trials:trials-list:table:sponsor')"
min-width="90"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="TrialStatusStr"
:label="$t('trials:trials-list:table:status')"
show-overflow-tooltip
sortable="custom"
>
<el-table-column prop="TrialCode" :label="$t('trials:trials-list:table:trialId')" show-overflow-tooltip
min-width="100" 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">
<el-tag
v-if="scope.row.TrialStatusStr === 'Initializing'"
type="info"
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
>
<el-tag
v-if="scope.row.TrialStatusStr === 'Ongoing'"
type="primary"
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
>
<el-tag
v-if="scope.row.TrialStatusStr === 'Completed'"
type="warning"
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
>
<el-tag
v-if="scope.row.TrialStatusStr === 'Stopped'"
type="danger"
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
>
<el-tag v-if="scope.row.TrialStatusStr === 'Initializing'" type="info">{{ $fd("TrialStatusEnum",
scope.row.TrialStatusStr) }}</el-tag>
<el-tag v-if="scope.row.TrialStatusStr === 'Ongoing'" type="primary">{{ $fd("TrialStatusEnum",
scope.row.TrialStatusStr) }}</el-tag>
<el-tag v-if="scope.row.TrialStatusStr === 'Completed'" type="warning">{{ $fd("TrialStatusEnum",
scope.row.TrialStatusStr) }}</el-tag>
<el-tag v-if="scope.row.TrialStatusStr === 'Stopped'" type="danger">{{ $fd("TrialStatusEnum",
scope.row.TrialStatusStr) }}</el-tag>
</template>
</el-table-column>
<!--阅片标准-->
<el-table-column
prop="CriterionTypeList"
:label="$t('trials:trials-list:table:CriterionTypeList')"
show-overflow-tooltip
v-if="hasPermi(['role:pm', 'role:pi', 'role:sr'])"
min-width="130"
>
<el-table-column prop="CriterionTypeList" :label="$t('trials:trials-list:table:CriterionTypeList')"
show-overflow-tooltip v-if="hasPermi(['role:pm', 'role:pi', 'role:sr'])" min-width="130">
<template slot-scope="scope">
<span>{{
scope.row.CriterionTypeList.map((item) =>
@@ -218,38 +120,16 @@
</template>
</el-table-column>
<!--待提交访视数量-->
<el-table-column
prop="UnSubmitCount"
:label="$t('trials:trials-list:table:UnSubmitCount')"
show-overflow-tooltip
min-width="90"
v-if="hasPermi(['role:pm'])"
sortable="custom"
/>
<el-table-column prop="UnSubmitCount" :label="$t('trials:trials-list:table:UnSubmitCount')"
show-overflow-tooltip min-width="90" v-if="hasPermi(['role:pm'])" sortable="custom" />
<!--待阅片数量-->
<el-table-column
prop="UnReadCount"
:label="$t('trials:trials-list:table:UnReadCount')"
show-overflow-tooltip
min-width="90"
v-if="hasPermi(['role:pm', 'role:pi', 'role:sr'])"
sortable="custom"
/>
<el-table-column
prop="CreateTime"
:label="$t('trials:trials-list:table:createDate')"
show-overflow-tooltip
min-width="170"
sortable="custom"
/>
<el-table-column prop="UnReadCount" :label="$t('trials:trials-list:table:UnReadCount')" show-overflow-tooltip
min-width="90" v-if="hasPermi(['role:pm', 'role:pi', 'role:sr'])" sortable="custom" />
<el-table-column prop="CreateTime" :label="$t('trials:trials-list:table:createDate')" show-overflow-tooltip
min-width="170" sortable="custom" />
<!--到期日-->
<el-table-column
prop="AuthorizationDate"
:label="$t('trials:trials-list:table:dateAuthorized')"
show-overflow-tooltip
min-width="170"
sortable="custom"
/>
<el-table-column prop="AuthorizationDate" :label="$t('trials:trials-list:table:dateAuthorized')"
show-overflow-tooltip min-width="170" sortable="custom" />
<!--授权时长-->
<!-- <el-table-column
prop="AuthorizationDuration"
@@ -257,125 +137,56 @@
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"
:disabled="scope.row.IsDeleted"
:title="$t('trials:trials-list:action:panel')"
@click.stop="handleDetail(scope.row)"
/>
<el-button v-hasPermi="['trials:trials-list:panel']" circle icon="el-icon-info"
:disabled="scope.row.IsDeleted" :title="$t('trials:trials-list:action:panel')"
@click.stop="handleDetail(scope.row)" />
<!-- 编辑项目基本信息 -->
<el-button
v-hasPermi="['trials:trials-list:edit']"
circle
icon="el-icon-edit-outline"
:disabled="scope.row.IsDeleted"
:title="$t('trials:trials-list:action:edit')"
@click.stop="handleEdit(scope.row)"
/>
<el-button v-hasPermi="['trials:trials-list:edit']" circle icon="el-icon-edit-outline"
:disabled="scope.row.IsDeleted" :title="$t('trials:trials-list:action:edit')"
@click.stop="handleEdit(scope.row)" />
<!-- 修改项目状态 -->
<el-button
v-hasPermi="['trials:trials-list:status']"
circle
icon="el-icon-edit"
:disabled="scope.row.IsDeleted"
:title="$t('trials:trials-list:action:status')"
@click.stop="handleStatus(scope.row)"
/>
<el-button v-hasPermi="['trials:trials-list:status']" circle icon="el-icon-edit"
:disabled="scope.row.IsDeleted" :title="$t('trials:trials-list:action:status')"
@click.stop="handleStatus(scope.row)" />
<!-- 废除项目 -->
<el-button
v-hasPermi="['trials:trials-list:abolish']"
circle
icon="el-icon-delete"
:disabled="
scope.row.IsDeleted ||
scope.row.TrialStatusStr !== 'Initializing'
"
:title="$t('trials:trials-list:action:abolition')"
@click.stop="handleAbandon(scope.row)"
/>
<el-button v-hasPermi="['trials:trials-list:abolish']" circle icon="el-icon-delete" :disabled="scope.row.IsDeleted ||
scope.row.TrialStatusStr !== 'Initializing'
" :title="$t('trials:trials-list:action:abolition')" @click.stop="handleAbandon(scope.row)" />
<!-- 激活 -->
<el-button
v-if="!scope.row.AuthorizationEncrypt"
v-hasPermi="['trials:trials-list:activate']"
circle
icon="el-icon-key"
:title="$t('trials:trials-list:action:activate')"
@click.stop="handleActivate(scope.row)"
/>
<el-button v-if="!scope.row.AuthorizationEncrypt" v-hasPermi="['trials:trials-list:activate']" circle
icon="el-icon-key" :title="$t('trials:trials-list:action:activate')"
@click.stop="handleActivate(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>
<!-- 新增/编辑项目 -->
<el-dialog
v-if="dialogVisible"
:visible.sync="dialogVisible"
:title="title"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<TrialForm
:trial-id="currentId"
@getList="getList"
@closeDialog="closeDialog"
/>
<el-dialog v-if="dialogVisible" :visible.sync="dialogVisible" :title="title" :fullscreen="true" append-to-body
custom-class="base-dialog-wrapper">
<TrialForm :trial-id="currentId" @getList="getList" @closeDialog="closeDialog" />
</el-dialog>
<!-- 修改项目状态 -->
<el-dialog
v-dialogDrag
v-if="statusVisible"
:visible.sync="statusVisible"
:close-on-click-modal="false"
:title="$t('trials:trials-list:dialogTitle:changeStatus')"
width="700px"
custom-class="base-dialog-wrapper"
append-to-body
>
<TrialStatusForm
:data="currentRow"
@close="closeStatusDialog"
@getList="getList"
/>
<el-dialog v-dialogDrag v-if="statusVisible" :visible.sync="statusVisible" :close-on-click-modal="false"
:title="$t('trials:trials-list:dialogTitle:changeStatus')" width="700px" custom-class="base-dialog-wrapper"
append-to-body>
<TrialStatusForm :data="currentRow" @close="closeStatusDialog" @getList="getList" />
</el-dialog>
<el-dialog
v-if="doneDialogVisible"
:visible.sync="doneDialogVisible"
:title="doneTitle"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<DoneList
:trial-id="currentId"
@getList="getList"
@closeDialog="doneDialogVisible = false"
/>
<el-dialog v-if="doneDialogVisible" :visible.sync="doneDialogVisible" :title="doneTitle" :fullscreen="true"
append-to-body custom-class="base-dialog-wrapper">
<DoneList :trial-id="currentId" @getList="getList" @closeDialog="doneDialogVisible = false" />
</el-dialog>
<!--项目激活-->
<activateProject
v-if="activateVisible"
:visible.sync="activateVisible"
:data="currentRow"
@getList="getList"
/>
<activateProject v-if="activateVisible" :visible.sync="activateVisible" :data="currentRow" @getList="getList" />
</BaseContainer>
</template>
<script>
@@ -479,6 +290,11 @@ export default {
created() {
this.initPage();
},
mounted() {
this.$EventBus.$on('reload', (data) => {
window.location.reload()
})
},
methods: {
//
moment(data) {
@@ -592,7 +408,7 @@ export default {
this.currentRow = { ...row };
this.abandonTrial();
})
.catch(() => {});
.catch(() => { });
},
//
abandonTrial() {

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