Compare commits

...

301 Commits

Author SHA1 Message Date
hang 1e9efd6d40 提交后发布事件 2026-08-21 15:34:56 +08:00
hang 80d78cb989 修改 2026-07-31 18:53:15 +08:00
hang 681ba17e37 修改清理缓存 2026-07-31 18:03:46 +08:00
hang 3385b65967 修复后处理增加数量bug 2026-07-30 17:52:21 +08:00
hang d6045ef7e7 Merge branch 'irc-add-image' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into irc-add-image 2026-07-30 17:43:17 +08:00
hang f66829ca62 上传记录屏蔽+IR已下载修改 2026-07-30 17:43:17 +08:00
he 471ea524b7 查询修改 2026-07-30 17:38:50 +08:00
he 34e9269916 提交答案取消签名验证 2026-07-30 16:03:57 +08:00
he 29d50fdd2d 稽查修改 2026-07-30 16:02:04 +08:00
hang 9f19dfceac 临时屏蔽CRC 上传监控 以及稽查 2026-07-30 16:00:30 +08:00
hang 799c579121 质控 -ivus 空检查过滤
continuous-integration/drone/push Build is running
2026-07-29 15:08:06 +08:00
hang 4841a9ac1e Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-29 11:47:27 +08:00
hang 287dd5d0bf 导表拆分查询修改 2026-07-29 11:47:24 +08:00
he 32e23ca0a2 修改字典 加英文 2026-07-29 09:34:37 +08:00
he b7d7b8c815 字典修改
continuous-integration/drone/push Build is passing
2026-07-29 09:19:22 +08:00
he 96fd034c5a 必填修改
continuous-integration/drone/push Build is running
2026-07-28 14:32:21 +08:00
he 6118e0a4f8 重新发布
continuous-integration/drone/push Build is running
2026-07-27 14:06:40 +08:00
he c00d1fb89c 重新发布 2026-07-27 14:03:54 +08:00
he 900f4dfb64 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-27 13:53:14 +08:00
he 11f8c9ca56 获取单个问题 2026-07-27 13:53:11 +08:00
hang 026f63c730 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-27 13:43:00 +08:00
hang e322952ff4 IR下载增加字段记录 2026-07-27 13:42:59 +08:00
he e762da2bf5 IUVS和OCT修改
continuous-integration/drone/push Build is running
2026-07-27 13:39:28 +08:00
he 822a4331aa 合并 2026-07-27 11:00:19 +08:00
he 2b2ba2a551 配置文件修改 2026-07-27 10:57:29 +08:00
hang 317fbc2ea7 修改生产配置文件
continuous-integration/drone/push Build is running
2026-07-27 10:53:20 +08:00
he 0cd9d666c1 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-20 16:05:21 +08:00
he 187ea3b92f 配置文件修改 2026-07-20 16:05:18 +08:00
hang d2beb399dd 阅片任务相关 访视信息赋值
continuous-integration/drone/push Build is running
2026-07-17 11:08:13 +08:00
he 15623ab515 配置文件修改
continuous-integration/drone/push Build is pending
2026-07-16 14:24:03 +08:00
he f771a23c2a Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-07-16 14:23:04 +08:00
he f20b8708a3 参数修改 2026-07-16 14:23:02 +08:00
hang 536ed731ed 一致性核查绑定模板修改
continuous-integration/drone/push Build is running
2026-07-14 17:27:43 +08:00
he 5b10619460 消息通知
continuous-integration/drone/push Build is running
2026-07-14 17:12:38 +08:00
he 311ac85419 重复请求code改为-4 取消Get类型验证
continuous-integration/drone/push Build is running
2026-07-14 16:58:17 +08:00
he dba3351195 Prod Ray plus bucker 修改
continuous-integration/drone/push Build is passing
2026-07-14 13:27:38 +08:00
he 506d6504c7 添加睿佳生产环境配置
continuous-integration/drone/push Build is running
2026-07-14 11:35:53 +08:00
he 1eede7832b 配置修改
continuous-integration/drone/push Build is running
2026-07-14 11:02:24 +08:00
he 5ec79bb61b 邮箱配置修改
continuous-integration/drone/push Build is running
2026-07-14 11:00:31 +08:00
hang 548863845b 修改睿佳数据库配置文件
continuous-integration/drone/push Build is passing
2026-07-13 16:28:31 +08:00
hang 2f73376ff6 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-13 16:22:46 +08:00
hang 9a8ee3a6aa 增加睿佳部署配置文件 2026-07-13 16:22:45 +08:00
he 28e367eb88 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-07-10 18:05:16 +08:00
he 7d642b46c9 维护项目受试者名称 2026-07-10 18:05:14 +08:00
hang 2be6757e23 盲态名称修改
continuous-integration/drone/push Build is running
2026-07-10 14:26:35 +08:00
hang 4ca67212aa 双重阅片,盲态名称不一样
continuous-integration/drone/push Build is passing
2026-07-10 11:13:42 +08:00
hang 503f99ccbe 修改部署配置文件读取方式
continuous-integration/drone/push Build is running
2026-07-10 10:39:43 +08:00
hang 93410b4075 增加1s延时测试热更新
continuous-integration/drone/push Build is passing
2026-07-10 09:45:20 +08:00
hang a96945201f 盲态名称查询
continuous-integration/drone/push Build is passing
2026-07-09 16:27:05 +08:00
hang 35c495f8a8 搜索条件
continuous-integration/drone/push Build is running
2026-07-09 16:22:54 +08:00
hang 9abd8e2c54 医学反馈仓储查询修改
continuous-integration/drone/push Build is passing
2026-07-09 14:00:03 +08:00
hang b9a79f0658 修改随机阅片任务盲态名字
continuous-integration/drone/push Build is passing
2026-07-09 13:48:39 +08:00
hang 83111d3338 增加缓存类别
continuous-integration/drone/push Build is running
2026-07-09 09:53:34 +08:00
hang 92072d3640 中心调研退出后改加入逻辑修改
continuous-integration/drone/push Build is passing
2026-07-09 09:07:51 +08:00
hang fd0ea313c2 中心调研人员退出bug
continuous-integration/drone/push Build is running
2026-07-08 17:30:39 +08:00
hang 79a15a08cc Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-08 16:14:23 +08:00
hang 1af798fb04 修改重复影像bug 2026-07-08 16:14:22 +08:00
he c19eb5bab7 添加校验
continuous-integration/drone/push Build is running
2026-07-08 14:57:55 +08:00
he db693de576 备注添加
continuous-integration/drone/push Build is running
2026-07-08 14:55:34 +08:00
he 651fa35018 自定义复制 2026-07-08 14:52:46 +08:00
he 36f1e9e8dd Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-08 14:42:20 +08:00
he 7e454467d1 赋值分割 2026-07-08 14:42:20 +08:00
hang 978caf8e9c 修改拷贝影像bug
continuous-integration/drone/push Build is passing
2026-07-08 13:56:39 +08:00
hang 2bf4e5d8fd 修改变量名错误
continuous-integration/drone/push Build is passing
2026-07-08 10:42:21 +08:00
hang dfb0c5a61c 优化写法
continuous-integration/drone/push Build is passing
2026-07-08 10:00:18 +08:00
hang 9d54fac8c5 无序阅片没有拷贝后续表单
continuous-integration/drone/push Build is passing
2026-07-08 09:36:16 +08:00
hang 5842590f6d 修改拷贝影像
continuous-integration/drone/push Build is running
2026-07-08 09:35:18 +08:00
hang 06a60cac38 拷贝影像不跟拷贝表单绑定
continuous-integration/drone/push Build is running
2026-07-08 09:29:21 +08:00
hang dac5eb0d7d 修改稽查报错
continuous-integration/drone/push Build is passing
2026-07-07 17:10:16 +08:00
hang 923edf166b subject状态变更撤销修改
continuous-integration/drone/push Build is passing
2026-07-07 10:20:43 +08:00
hang a0776e5462 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-07 09:47:51 +08:00
hang 9ac6d3df70 IR申请重阅,拷贝dicom 非dicom 影像 2026-07-07 09:47:50 +08:00
he a8a3104019 任务Id修改 2026-07-07 09:32:17 +08:00
he 7cd476028a 受试者图表数据修改
continuous-integration/drone/push Build is running
2026-07-07 09:24:54 +08:00
he fe96ff5924 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-06 17:49:07 +08:00
he 890d349ee9 获取项目链接过期时间 返回研究方案号 2026-07-06 17:49:06 +08:00
hang 895eaa42c8 列表接口返回状态字段
continuous-integration/drone/push Build is running
2026-07-06 17:13:01 +08:00
hang 2e4457b56d Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-06 16:58:05 +08:00
hang b30638fa82 增加访视状态退回原因 2026-07-06 16:58:03 +08:00
he a3fac7bcb1 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-06 15:58:31 +08:00
he 7228bdd9e9 修改项目受试者名称 2026-07-06 15:58:30 +08:00
hang fa84171da4 写配置文件加锁
continuous-integration/drone/push Build is running
2026-07-06 11:31:35 +08:00
hang f4c3f685eb 区分标准判断逻辑bug
continuous-integration/drone/push Build is running
2026-07-03 18:09:17 +08:00
he db17d23360 功能修改
continuous-integration/drone/push Build is passing
2026-07-03 16:42:57 +08:00
he 76fe1e12d3 邮件内容修改
continuous-integration/drone/push Build is running
2026-07-03 16:25:19 +08:00
he d7f455c740 邮件名称替换
continuous-integration/drone/push Build is running
2026-07-03 14:24:01 +08:00
he d62d7172d0 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-03 11:05:23 +08:00
he 9bfdb2f06a 答案异常 与裁判异常 发邮件给PM 2026-07-03 11:05:22 +08:00
hang d6436b01d4 中心调研,仅仅上传文件,不用验证
continuous-integration/drone/push Build is passing
2026-07-02 15:38:17 +08:00
hang e848ee1972 修改密码设置状态
continuous-integration/drone/push Build is passing
2026-07-02 14:42:30 +08:00
hang 2716b462b1 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-01 17:31:47 +08:00
hang 10f3db1ec2 优化查询,增加字段 2026-07-01 17:31:46 +08:00
he 0848a441b1 阅片问题重复提示修改
continuous-integration/drone/push Build is passing
2026-07-01 15:59:55 +08:00
he 00c59958e6 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-07-01 14:38:04 +08:00
he 9cc438a647 邮件发送修改 2026-07-01 14:38:03 +08:00
hang 1053fdc8a8 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-07-01 11:33:11 +08:00
hang e1ee129f41 中心调研增加上传文件 2026-07-01 11:33:11 +08:00
he dae0cab261 修改编辑 重新发布
continuous-integration/drone/push Build is passing
2026-07-01 11:20:49 +08:00
he 5871d054d3 系统文档区分语言
continuous-integration/drone/push Build is passing
2026-07-01 09:25:24 +08:00
he a69e8969a4 请求时间修改
continuous-integration/drone/push Build is passing
2026-06-30 16:45:34 +08:00
he dd05e26feb 邮件修改
continuous-integration/drone/push Build is running
2026-06-30 15:33:55 +08:00
he 8cd8b7cf43 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-30 14:04:12 +08:00
he 1d90aba7cd 添加重复请求通知 2026-06-30 14:04:11 +08:00
hang 826aff3d36 中心调研增加字段
continuous-integration/drone/push Build is passing
2026-06-30 10:22:05 +08:00
he 718294f776 接口加锁
continuous-integration/drone/push Build is running
2026-06-30 09:10:07 +08:00
he 7a003eb490 添加任务名称
continuous-integration/drone/push Build is running
2026-06-30 09:09:21 +08:00
he bcceb5d42d 数据通知 2026-06-30 09:09:18 +08:00
he b1802d7d79 修改名称 2026-06-30 09:09:15 +08:00
he e14eeb4da3 异常提醒修改 2026-06-30 09:09:13 +08:00
he f726088cc9 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-29 15:55:51 +08:00
he 4082850b7a 只限制 changeDicomReadingQuestionAnswer 接口 以及微信通知 2026-06-29 15:55:51 +08:00
hang 641d61d242 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-29 15:43:01 +08:00
hang e2b67bb3f5 返回有序无序 2026-06-29 15:43:00 +08:00
he 1f3e1ceb37 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-29 15:35:34 +08:00
he 254e9508b6 任务答案数量验证 2026-06-29 15:35:33 +08:00
hang 631be6d7c7 返回重置密码字段
continuous-integration/drone/push Build is running
2026-06-29 15:11:51 +08:00
hang ca31e9a062 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-29 14:36:56 +08:00
hang 9fd7d9928a 非dicom 匿名图像 以及用户重置密码 2026-06-29 14:36:55 +08:00
he 9362b2fb23 Revert "临时去掉锁"
This reverts commit e045302d38.
2026-06-29 12:28:49 +08:00
he 1735a4621e 重新发布
continuous-integration/drone/push Build is running
2026-06-29 12:18:55 +08:00
he 6ff332367d Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-06-29 11:40:10 +08:00
he e045302d38 临时去掉锁 2026-06-29 11:40:09 +08:00
hang 88793cf011 修改过滤
continuous-integration/drone/push Build is running
2026-06-29 11:13:30 +08:00
hang a4181f819b 修改受试者状态退回,逻辑判断
continuous-integration/drone/push Build is running
2026-06-26 16:33:47 +08:00
hang 79aeb663c6 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-26 14:32:51 +08:00
hang 169301836a 修改标准相关邮件过滤 2026-06-26 14:32:50 +08:00
he 71bd67ba01 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-26 14:14:55 +08:00
he 3e94dc6518 生效通知改为单独发 2026-06-26 14:14:54 +08:00
hang 503322d57e pd 入组邮件筛选过滤修改
continuous-integration/drone/push Build is running
2026-06-26 13:03:50 +08:00
hang 0c9ffbf5e4 修改项目邮件查询列表
continuous-integration/drone/push Build is running
2026-06-26 11:45:17 +08:00
he fae7889995 演示用户不发送邮局
continuous-integration/drone/push Build is running
2026-06-25 13:48:13 +08:00
he 532e514060 培训过期改为每个人单独发送
continuous-integration/drone/push Build is running
2026-06-25 09:55:01 +08:00
he b3a5047ba8 验证重复请求加锁
continuous-integration/drone/push Build is running
2026-06-24 15:15:12 +08:00
he 810e6ccb19 禁用的用户不发邮件
continuous-integration/drone/push Build is running
2026-06-23 17:15:24 +08:00
he 352e719fae Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-23 10:42:55 +08:00
he d8e0c73f56 修改 试验参与者 2026-06-23 10:42:54 +08:00
hang 46374be4c0 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is passing
2026-06-22 15:28:27 +08:00
hang 020c5280b3 修改匿名化配置,更新缓存,同时增加代码自动替换excel 关键字 2026-06-22 15:28:25 +08:00
he 4beba23f99 发布
continuous-integration/drone/push Build is running
2026-06-18 17:55:05 +08:00
he 59f36cceb4 修改字段名 2026-06-18 17:50:40 +08:00
he d08b409f0e Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-18 13:10:44 +08:00
he 1612201101 重新发布 2026-06-18 13:10:43 +08:00
hang 924347361a 去重提交
continuous-integration/drone/push Build is running
2026-06-18 11:38:29 +08:00
he 061d212623 修改验证
continuous-integration/drone/push Build is running
2026-06-18 11:32:48 +08:00
he af937b3f53 验证不用加token
continuous-integration/drone/push Build is passing
2026-06-18 11:18:49 +08:00
he 1faa72c5ea 修改关键帧排序
continuous-integration/drone/push Build is running
2026-06-18 10:37:38 +08:00
he db53e5a60b 修改
continuous-integration/drone/push Build is passing
2026-06-17 17:37:09 +08:00
he 802e768bad Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-17 17:33:09 +08:00
he 67f17cffe0 添加LinkVerificationCode 2026-06-17 17:33:09 +08:00
hang 70160cb937 更新状态,不忽略null值
continuous-integration/drone/push Build is running
2026-06-17 17:17:01 +08:00
hang 6e22246555 中心接口增加参数
continuous-integration/drone/push Build is running
2026-06-16 17:16:57 +08:00
hang 7ed0258cfd 中心调研增加字段返回禁用的中心 2026-06-16 17:16:55 +08:00
he ddd06c8313 添加中心调研链接过期时间
continuous-integration/drone/push Build is running
2026-06-16 15:42:33 +08:00
he d33b84c245 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10
continuous-integration/drone/push Build is running
2026-06-16 13:50:08 +08:00
he 14cd5dd91c 替换字典中项目关键字 2026-06-16 13:50:07 +08:00
hang 2b29ebc29b 项目配置增加培训类型呢
continuous-integration/drone/push Build is passing
2026-06-16 13:32:15 +08:00
hang 84b65ee122 关键图里增加分割路径,支持下载
continuous-integration/drone/push Build is passing
2026-06-16 11:31:06 +08:00
hang c3e9024a57 受试者进展表导表排序变更
continuous-integration/drone/push Build is passing
2026-06-16 09:20:50 +08:00
hang d49b5663ba 阅片期查询bug
continuous-integration/drone/push Build is running
2026-06-15 14:27:47 +08:00
hang e1386da5ae CRC CRA退出,过滤重传审批列表
continuous-integration/drone/push Build is running
2026-06-15 11:10:00 +08:00
hang b9f9af06f4 屏蔽swager 报错接口 2026-06-11 09:44:44 +08:00
he 01a79e0612 新增接口 GetNoneDicomMarkList
continuous-integration/drone/push Build is passing
2026-06-10 15:12:07 +08:00
he 3e69d72597 添加标记名称字段
continuous-integration/drone/push Build is passing
2026-06-10 14:13:15 +08:00
he f69c7af9d6 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-06-09 16:33:19 +08:00
he ae03503d76 添加NumberOfFrames 2026-06-09 16:33:18 +08:00
hang 39eade67f0 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-06-09 16:32:55 +08:00
hang e6d7a0c0e0 返回默认值,如果没有任务 2026-06-09 16:32:53 +08:00
he 98103451e9 添加 SopInstanceUid
continuous-integration/drone/push Build is passing
2026-06-09 16:18:33 +08:00
he b64eed88cf 高亮修改
continuous-integration/drone/push Build is passing
2026-06-09 16:07:12 +08:00
he bafe61ae64 Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-06-09 15:45:53 +08:00
he 0579c4aeda 功能添加 2026-06-09 15:45:52 +08:00
hang 7599e06b9d 重新触发测试
continuous-integration/drone/push Build is passing
2026-06-09 15:19:51 +08:00
hang 8e77d2e3ed 请求改为post 2026-06-09 15:05:46 +08:00
hang c2a129c56a Merge branch 'Test_IRC_Net10' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net10 2026-06-09 15:05:21 +08:00
hang 111d5509bc 医生阅片统计+受试者完成任务状态返回 2026-06-09 15:05:19 +08:00
he 7c9987f3de 获取标记信息
continuous-integration/drone/push Build is passing
2026-06-09 14:58:02 +08:00
hang f1471b6424 访视结束,状态回退
continuous-integration/drone/push Build is running
2026-06-08 11:35:26 +08:00
hang 935369c05c zip流方式下载影像
continuous-integration/drone/push Build is running
2026-06-05 11:27:27 +08:00
hang 2b03f382bd 术语替换-先完整准确匹配,匹配了就跳过,否则就关键字匹配替换
continuous-integration/drone/push Build is running
2026-06-04 16:28:17 +08:00
he 152a142d82 添加新增修改表格问题限制
continuous-integration/drone/push Build is failing
2026-06-04 14:41:26 +08:00
hang f55ce703b0 升级net10 自动打包分支修改
continuous-integration/drone/push Build is running
2026-06-04 14:12:09 +08:00
hang a08c8a0d64 升级除开收费包以外所有其他包 2026-06-04 13:45:31 +08:00
hang 76dd0c46ae 处理.net10编译错误 2026-06-04 13:19:38 +08:00
hang 1e8056f689 .net10 -合并编译错误 2026-06-04 13:19:17 +08:00
hang d719015fa2 zip 流方式demo
continuous-integration/drone/push Build is failing
2026-06-04 13:08:37 +08:00
hang 73fa62e6a2 增加续期备注 2026-06-03 17:56:07 +08:00
hang bb3f612772 临时token 续期以服务器时间比较
continuous-integration/drone/push Build is running
2026-06-03 17:44:31 +08:00
hang 99b6c63de7 开启压缩包任务索引增加
continuous-integration/drone/push Build is running
2026-06-03 15:33:03 +08:00
hang 8b046e61ab 后端长时间下载,临时token 续期bug 修复
continuous-integration/drone/push Build is running
2026-06-03 14:34:25 +08:00
hang ff2c619df7 增加下载额外日志提示
continuous-integration/drone/push Build is running
2026-06-03 14:09:12 +08:00
hang c9ffa64560 遮盖影像修改
continuous-integration/drone/push Build is running
2026-06-03 13:54:10 +08:00
hang 2969306d1e 合并多帧不保留偏移表
continuous-integration/drone/push Build is running
2026-06-03 11:07:04 +08:00
hang 2fb558d388 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-06-02 17:23:27 +08:00
hang 9a0859f915 后端增加默认排序 2026-06-02 17:23:27 +08:00
he 19bf8210f6 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-06-02 16:25:42 +08:00
he 7a30fd0f28 验证修改 2026-06-02 16:25:41 +08:00
hang 432bf1ae12 项目删除,导致参与项目列表查询bug
continuous-integration/drone/push Build is running
2026-06-02 16:03:55 +08:00
hang 967c0114d8 导出下载访视修改
continuous-integration/drone/push Build is pending
2026-06-02 15:03:00 +08:00
hang 0f55c6da9d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-06-02 14:13:20 +08:00
hang 5e345418fb 分配阅片人bug 2026-06-02 14:13:17 +08:00
he de19c5bc32 修改密码发送邮件 2026-06-02 10:55:47 +08:00
he 1998842200 验证修改
continuous-integration/drone/push Build is pending
2026-06-02 10:38:15 +08:00
he 25a18e8366 项目查询排序
continuous-integration/drone/push Build is passing
2026-06-02 10:04:42 +08:00
he a2966e761c Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-06-02 09:27:44 +08:00
he 0508b8ffb3 功能修改 2026-06-02 09:27:41 +08:00
hang 9d4c69b39a 通过Excel 读取信息进行下载
continuous-integration/drone/push Build is running
2026-06-02 01:17:01 +08:00
hang e11790ea92 合并多帧失败,日志记录修改
continuous-integration/drone/push Build is running
2026-06-01 23:30:51 +08:00
he e559c2503b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-06-01 16:41:44 +08:00
he c0a383ef58 MRIPDFF 修改1 2026-06-01 16:41:40 +08:00
hang 9b6ddb0f16 不压缩打包
continuous-integration/drone/push Build is running
2026-06-01 15:52:06 +08:00
hang 45db942f66 修改下载代码
continuous-integration/drone/push Build is running
2026-06-01 15:37:01 +08:00
hang 41efcbfdf1 修改事件环境配置,增加windows部署识别环境参数
continuous-integration/drone/push Build is running
2026-06-01 12:41:54 +08:00
hang 76c69a8464 下载增加区间
continuous-integration/drone/push Build is running
2026-05-29 17:51:27 +08:00
hang abe42ef3cf Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-29 15:16:36 +08:00
hang 40f744ea4a 后端下载影像打成压缩包 2026-05-29 15:16:35 +08:00
he 7bc0d7f3dc 功能修改
continuous-integration/drone/push Build is running
2026-05-29 11:02:24 +08:00
he 9bbac291b6 邮件内容替换
continuous-integration/drone/push Build is passing
2026-05-29 09:29:43 +08:00
hang d7da7b69d4 修改字段类型 2026-05-28 16:49:11 +08:00
hang f6530cfb32 删除多余的分号
continuous-integration/drone/push Build is failing
2026-05-28 16:08:14 +08:00
hang 376dcc5bd5 增加创建项目调研默认值
continuous-integration/drone/push Build is running
2026-05-28 15:47:57 +08:00
hang 89546b9874 修改默认配置
continuous-integration/drone/push Build is passing
2026-05-28 14:55:00 +08:00
hang 385c40c895 修改默认值
continuous-integration/drone/push Build is running
2026-05-28 13:48:56 +08:00
hang 8b9580abc8 修改中心调研增加字段
continuous-integration/drone/push Build is running
2026-05-28 13:28:52 +08:00
hang 3b9c8efeba 配置生产bucket 信息
continuous-integration/drone/push Build is failing
2026-05-27 15:35:49 +08:00
hang 5ba831c044 测试模型默认值
continuous-integration/drone/push Build is running
2026-05-27 10:31:53 +08:00
hang 1141cc20e9 修改配置字段更新位置
continuous-integration/drone/push Build is running
2026-05-27 09:31:14 +08:00
hang 11a439a48f 质控下载默认值修改
continuous-integration/drone/push Build is running
2026-05-26 17:12:50 +08:00
hang 9ef3e53d77 修改项目配置默认值
continuous-integration/drone/push Build is running
2026-05-26 16:31:49 +08:00
hang 104f46c9db 修改oss 配置文件 2026-05-26 13:56:45 +08:00
hang 0f0c670ec8 增加参数判断,是否导出阅片影像
continuous-integration/drone/push Build is running
2026-05-26 13:34:44 +08:00
hang c901f0e3d1 增加uat scp 同步配置 2026-05-25 16:49:42 +08:00
he 63e9428d6d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-25 16:38:42 +08:00
he cbe7270f4b 稽查功能修改 2026-05-25 16:38:38 +08:00
hang fd67dad4b2 增加uat 部署测试lili同步配置
continuous-integration/drone/push Build is failing
2026-05-25 13:14:05 +08:00
hang 38b8f0085b 调整中心调研视图接收模型
continuous-integration/drone/push Build is running
2026-05-21 14:28:22 +08:00
hang ab0e7afdb8 中心调研国际化修改 2026-05-21 14:23:13 +08:00
hang 8045f96106 修改中心调研配置字段
continuous-integration/drone/push Build is running
2026-05-21 14:13:09 +08:00
hang 6481aa37e7 将项目配置从json中挪出来
continuous-integration/drone/push Build is running
2026-05-21 11:35:54 +08:00
hang 0b9ee87039 增加系统配置修改
continuous-integration/drone/push Build is running
2026-05-21 09:22:51 +08:00
hang 9b0d68d26d 修改order
continuous-integration/drone/push Build is passing
2026-05-20 15:28:57 +08:00
hang 8ee7d7018f 修改默认值
continuous-integration/drone/push Build is running
2026-05-20 15:27:16 +08:00
hang 7c1c45417f 中心调研初步调整
continuous-integration/drone/push Build is running
2026-05-20 14:10:10 +08:00
hang 1fbda0327c 修改dcm默认值
continuous-integration/drone/push Build is running
2026-05-20 11:49:25 +08:00
hang 12f91c3b99 dicom没有类型时,给默认值dcm
continuous-integration/drone/push Build is passing
2026-05-20 09:23:46 +08:00
hang 7d7c350df6 修改scp默认设置的区域
continuous-integration/drone/push Build is running
2026-05-19 13:24:23 +08:00
hang caffff259e 删除检查不删除pacs推送过来的
continuous-integration/drone/push Build is running
2026-05-19 10:10:59 +08:00
hang 80b3defd37 从pacs 添加检查修改项目检查最大编号
continuous-integration/drone/push Build is running
2026-05-18 17:57:10 +08:00
hang bbe1642786 回更同步记录的 subjectId svId
continuous-integration/drone/push Build is running
2026-05-18 17:30:22 +08:00
hang 4a2b9fdb41 输入错误修改
continuous-integration/drone/push Build is passing
2026-05-18 17:15:43 +08:00
hang f7bc32ed90 修改绑定配置
continuous-integration/drone/push Build is running
2026-05-18 17:13:59 +08:00
hang 592de4deb4 增加同步配置
continuous-integration/drone/push Build is running
2026-05-18 16:53:26 +08:00
hang ad5c36930e 修改SCP服务配置文件
continuous-integration/drone/push Build is running
2026-05-18 16:22:04 +08:00
hang c4570ebe62 修改SCP服务同步
continuous-integration/drone/push Build is pending
2026-05-18 15:33:09 +08:00
hang fdaf7180c0 修改医学审核判断
continuous-integration/drone/push Build is passing
2026-05-15 18:06:35 +08:00
hang ee9152bbc4 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-15 13:54:43 +08:00
hang 413503e0f4 一致性核查 核查结果根据中心设置的语言进行调整 2026-05-15 13:54:41 +08:00
he 27c41af918 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8 2026-05-15 13:39:02 +08:00
he fd21cf2539 项目文档 中英文 2026-05-15 13:39:00 +08:00
hang da485e1dde 修改周期性邮件语言设置
continuous-integration/drone/push Build is passing
2026-05-15 13:31:58 +08:00
hang 24dfa32ad4 优化liquid 生成模板
continuous-integration/drone/push Build is running
2026-05-14 11:11:26 +08:00
hang 1f9d9b2831 修改文档统计数字
continuous-integration/drone/push Build is failing
2026-05-14 09:06:21 +08:00
he 6211506aee Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-13 17:54:50 +08:00
he e1bd659dc5 过期邮件修改 2026-05-13 17:54:48 +08:00
hang b56d45f411 外部人员邮件
continuous-integration/drone/push Build is running
2026-05-13 16:45:23 +08:00
hang 35a2a0cc61 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-13 16:02:02 +08:00
hang ff43a5e71b 修改创建用户语言赋值 2026-05-13 16:02:01 +08:00
hang 8bdbc67535 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-13 15:20:22 +08:00
hang 85261bc3cf 入组和PD 邮件修改 2026-05-13 15:20:21 +08:00
he 311359f6b8 邮件内容修改
continuous-integration/drone/push Build is running
2026-05-13 14:38:13 +08:00
he 0cb3646554 修改邮件中英文
continuous-integration/drone/push Build is running
2026-05-13 14:25:24 +08:00
he cd02042d63 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is pending
2026-05-13 13:40:44 +08:00
he db73a841b2 修改删除阅片期操作逻辑 2026-05-13 13:40:43 +08:00
hang a3e773cb4f Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8 2026-05-13 13:36:07 +08:00
hang 09ed4adc93 访视质控以及一致性核查相关邮件根据收件人工作语言进行分组发送 2026-05-13 13:36:06 +08:00
he 530e4d412c Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-13 13:29:08 +08:00
he bff593394f 重新发布 2026-05-13 13:29:07 +08:00
hang 32c38e9f95 整理MailServer 修改发送邮件根据工作语言
continuous-integration/drone/push Build is running
2026-05-13 13:08:49 +08:00
hang 005b0b9e0d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-13 11:05:25 +08:00
hang fdb124b12e 邮件根据接收人工作语言,动态设置邮件模板 2026-05-13 11:05:22 +08:00
he 652a446737 修改阅片期删除的逻辑
continuous-integration/drone/push Build is running
2026-05-13 10:47:56 +08:00
he 098196b599 修改分割版本
continuous-integration/drone/push Build is running
2026-05-12 17:05:31 +08:00
he 01c5b96bc7 修改
continuous-integration/drone/push Build is passing
2026-05-12 16:33:17 +08:00
he 334743f3f0 修改分割
continuous-integration/drone/push Build is running
2026-05-12 16:17:14 +08:00
he bd60f48cd1 修改版本
continuous-integration/drone/push Build is running
2026-05-12 15:32:16 +08:00
he 4fe915cfd8 修改版本 2026-05-12 15:24:02 +08:00
he 14cc78cffc 修改
continuous-integration/drone/push Build is passing
2026-05-12 14:46:34 +08:00
he a04ae45402 修改 2026-05-12 14:40:32 +08:00
he 0f68f170ad 重新发布
continuous-integration/drone/push Build is running
2026-05-12 14:29:05 +08:00
he 4033c8d004 重新发布 2026-05-12 14:23:38 +08:00
he 68d320d9cf Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2026-05-12 14:10:25 +08:00
he 603a522c4b 修改历史版本 2026-05-12 14:10:22 +08:00
hang 030aa36f94 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2026-05-12 11:45:56 +08:00
hang 577f35a3fe 用户增加工作语言,系统文档增加文档适用语言用户 2026-05-12 11:45:55 +08:00
he 790ac40f4e 生成历史版本逻辑修改
continuous-integration/drone/push Build is running
2026-05-11 16:30:33 +08:00
he 44d9c23c0c 添加字段
continuous-integration/drone/push Build is passing
2026-05-11 15:33:41 +08:00
he 547bd54085 修改
continuous-integration/drone/push Build is running
2026-05-11 14:48:13 +08:00
hang 388dac5f8d 删除无用包 2026-04-30 09:01:24 +08:00
hang ec0a4aeef9 降级automapper 2026-04-29 20:39:41 +08:00
hang 8bf0be9699 ClosedXML 替代 npoi 修改 2026-04-29 20:19:01 +08:00
hang 7707b339dc 打印运行时版本 2026-04-29 16:57:27 +08:00
hang 8eaa6606c4 升级.net10 2026-04-29 15:56:41 +08:00
222 changed files with 344520 additions and 3784 deletions
+9
View File
@@ -0,0 +1,9 @@
<Project>
<PropertyGroup>
<!-- 在这里定义所有项目共享的属性 -->
<TargetFramework>net10.0</TargetFramework>
<!-- 如果需要Nullable等全局设置,也可以加在这里 -->
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
+20 -22
View File
@@ -1,37 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> <PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" /> <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="4.0.21" /> <PackageReference Include="AWSSDK.S3" Version="4.0.24" />
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.5.19" /> <PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
<PackageReference Include="DistributedLock.Core" Version="1.0.8" /> <PackageReference Include="DistributedLock.Core" Version="1.0.9" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" /> <PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" />
<PackageReference Include="fo-dicom" Version="5.2.1" /> <PackageReference Include="fo-dicom" Version="5.2.6" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" /> <PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" /> <PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Minio" Version="6.0.4" /> <PackageReference Include="Minio" Version="7.0.0" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0"> <PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.2" /> <PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.9.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+1 -1
View File
@@ -56,7 +56,7 @@ var _configuration = builder.Configuration;
builder.Services.AddHealthChecks(); builder.Services.AddHealthChecks();
//本地化 //本地化
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
+6 -8
View File
@@ -1,8 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
@@ -10,17 +8,17 @@
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" /> <PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" /> <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="4.0.21" /> <PackageReference Include="AWSSDK.S3" Version="4.0.24" />
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.5.19" /> <PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
<PackageReference Include="DistributedLock.Core" Version="1.0.9" /> <PackageReference Include="DistributedLock.Core" Version="1.0.9" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" /> <PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" />
<PackageReference Include="fo-dicom" Version="5.2.6" /> <PackageReference Include="fo-dicom" Version="5.2.6" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.7" /> <PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" /> <PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
<PackageReference Include="AutoMapper" Version="16.1.1" /> <PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Minio" Version="7.0.0" /> <PackageReference Include="Minio" Version="7.0.0" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0"> <PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
@@ -28,7 +26,7 @@
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+1 -2
View File
@@ -13,7 +13,6 @@ using IRaCIS.Core.SCP.Service;
using MassTransit; using MassTransit;
using MassTransit.NewIdProviders; using MassTransit.NewIdProviders;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using Panda.DynamicWebApi; using Panda.DynamicWebApi;
using Serilog; using Serilog;
using Serilog.Events; using Serilog.Events;
@@ -71,7 +70,7 @@ builder.Services.AddHostedService<FileSyncWorker>();
builder.Services.AddHealthChecks(); builder.Services.AddHealthChecks();
//本地化 //本地化
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
+3 -2
View File
@@ -8,6 +8,7 @@ using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.SCP.Service; using IRaCIS.Core.SCP.Service;
using MassTransit;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -95,7 +96,7 @@ namespace IRaCIS.Core.SCP.Service
public Task OnReceiveAssociationRequestAsync(DicomAssociation association) public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
{ {
_upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost }; _upload = new SCPImageUpload() { Id = NewId.NextSequentialGuid(), StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接"); Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
@@ -644,7 +645,7 @@ namespace IRaCIS.Core.SCP.Service
ms.Position = 0; ms.Position = 0;
//irc 从路径最后一截取Guid //irc 从路径最后一截取Guid
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive }); storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive, UploadBatchId = _upload.Id.ToString() });
fileSize = ms.Length; fileSize = ms.Length;
@@ -63,6 +63,8 @@ public class FileUploadRecordAddOrEdit
public bool? IsNeedSync { get; set; } public bool? IsNeedSync { get; set; }
public string UploadRegion { get; set; } public string UploadRegion { get; set; }
public string TargetRegion { get; set; } public string TargetRegion { get; set; }
public bool? IsSync { get; set; }
} }
public interface IFileUploadRecordService public interface IFileUploadRecordService
{ {
@@ -87,6 +89,7 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord) public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord)
{ {
return ResponseOutput.Ok();
addOrEditFileUploadRecord.IP = _userInfo.IP; addOrEditFileUploadRecord.IP = _userInfo.IP;
@@ -113,6 +116,19 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
} }
} }
//SCP推送过来IP为空,后端归档的,设置区域
if (_userInfo.IP.IsNullOrEmpty() && _userInfo.Domain.IsNullOrEmpty())
{
var apiDefalut = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.UploadRegion == ObjectStoreServiceConfig.ApiDeployRegion);
if (apiDefalut != null)
{
addOrEditFileUploadRecord.UploadRegion = apiDefalut.UploadRegion;
addOrEditFileUploadRecord.TargetRegion = apiDefalut.TargetRegion;
}
}
if (addOrEditFileUploadRecord.TrialId != null) if (addOrEditFileUploadRecord.TrialId != null)
{ {
@@ -129,9 +145,9 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
{ {
addOrEditFileUploadRecord.IsNeedSync = true; addOrEditFileUploadRecord.IsNeedSync = true;
addOrEditFileUploadRecord.Priority = 0; addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
addOrEditFileUploadRecord.IsSync = false;
} }
else else
{ {
@@ -147,7 +163,9 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
//系统文件,默认同步 //系统文件,默认同步
addOrEditFileUploadRecord.IsNeedSync = true; addOrEditFileUploadRecord.IsNeedSync = true;
addOrEditFileUploadRecord.Priority = 0; addOrEditFileUploadRecord.IsSync = false;
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
} }
var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true); var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true);
+89 -26
View File
@@ -194,7 +194,7 @@ public interface IOSSService
List<string> GetRootFolderNames(); List<string> GetRootFolderNames();
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null); public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null);
public Task MoveObject(string sourcePath, string destPath, bool overwrite = true); public Task MoveObject(string sourcePath, string destPath, bool overwrite = true);
@@ -825,10 +825,12 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null) if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
{ {
var fileType = Path.GetExtension(returnPath).TrimStart('.');
uploadInfo.FileSize = fileStream.CanSeek ? fileStream.Length : 0; uploadInfo.FileSize = fileStream.CanSeek ? fileStream.Length : 0;
uploadInfo.Path = returnPath; uploadInfo.Path = returnPath;
uploadInfo.FileName = fileRealName; uploadInfo.FileName = fileRealName;
uploadInfo.FileType = Path.GetExtension(returnPath); uploadInfo.FileType = fileType.IsNullOrEmpty()?"dcm": fileType;
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo); await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
@@ -964,10 +966,14 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null) if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
{ {
var fileType = Path.GetExtension(returnPath).TrimStart('.');
uploadInfo.FileSize = fileSize; uploadInfo.FileSize = fileSize;
uploadInfo.Path = returnPath; uploadInfo.Path = returnPath;
uploadInfo.FileName = Path.GetFileName(localFilePath); uploadInfo.FileName = Path.GetFileName(localFilePath);
uploadInfo.FileType = Path.GetExtension(returnPath); uploadInfo.FileType = fileType.IsNullOrEmpty() ? "dcm" : fileType;
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo); await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
@@ -1856,23 +1862,39 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null) public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null)
{
string objectStoreUse = string.Empty;
//使用指定配置
if (objectUse != null)
{
objectStoreUse = objectUse?.Trim() ?? string.Empty;
}
//根据域名动态判断
else
{ {
//如果传递了域名,并且打开了存储同步,根据域名使用的具体存储覆盖之前的配置,否则就用固定的配置 //如果传递了域名,并且打开了存储同步,根据域名使用的具体存储覆盖之前的配置,否则就用固定的配置
if (ObjectStoreServiceOptions.IsOpenStoreSync && domain.IsNotNullOrEmpty()) if (ObjectStoreServiceOptions.IsOpenStoreSync && domain.IsNotNullOrEmpty() && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.Domain == domain))
{ {
var userDomain = domain?.Trim();
var find = ObjectStoreServiceOptions.SyncConfigList.FirstOrDefault(t => t.Domain == userDomain); var find = ObjectStoreServiceOptions.SyncConfigList.FirstOrDefault(t => t.Domain == domain);
if (find != null) if (find != null)
{ {
ObjectStoreServiceOptions.ObjectStoreUse = find.Primary; objectStoreUse = find.Primary;
}
}
else
{
//兜底,如果是本地测试环境,那就使用部署默认配置
objectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse;
} }
} }
var objectStoreDTO = new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, IsOpenStoreSync = ObjectStoreServiceOptions.IsOpenStoreSync, SyncConfigList = ObjectStoreServiceOptions.SyncConfigList };
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS" || isGetAllTempToken == true) var objectStoreDTO = new ObjectStoreDTO() { ObjectStoreUse = objectStoreUse, IsOpenStoreSync = ObjectStoreServiceOptions.IsOpenStoreSync, SyncConfigList = ObjectStoreServiceOptions.SyncConfigList };
if (objectStoreUse == "AliyunOSS" || isGetAllTempToken == true)
{ {
var ossOptions = ObjectStoreServiceOptions.AliyunOSS; var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
@@ -1920,11 +1942,11 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
objectStoreDTO.AliyunOSS = tempToken; objectStoreDTO.AliyunOSS = tempToken;
} }
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") if (objectStoreUse == "MinIO")
{ {
objectStoreDTO.MinIO = ObjectStoreServiceOptions.MinIO; objectStoreDTO.MinIO = ObjectStoreServiceOptions.MinIO;
} }
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS" || isGetAllTempToken == true) if (objectStoreUse == "AWS" || isGetAllTempToken == true)
{ {
var awsOptions = ObjectStoreServiceOptions.AWS; var awsOptions = ObjectStoreServiceOptions.AWS;
@@ -1969,7 +1991,8 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
objectStoreDTO.AWS = tempToken; objectStoreDTO.AWS = tempToken;
} }
else
if (objectStoreUse.IsNullOrEmpty())
{ {
throw new BusinessValidationFailedException("未定义的存储介质类型"); throw new BusinessValidationFailedException("未定义的存储介质类型");
} }
@@ -1980,7 +2003,7 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
public async Task SyncFileAsync(string objectKey, ObjectStoreUse source, ObjectStoreUse destination, CancellationToken ct = default) public async Task SyncFileAsync(string objectKey, ObjectStoreUse source, ObjectStoreUse destination, CancellationToken ct = default)
{ {
GetObjectStoreTempToken(isGetAllTempToken: true); var tempConfig = GetObjectStoreTempToken(isGetAllTempToken: true);
var aliConfig = ObjectStoreServiceOptions.AliyunOSS; var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
@@ -1999,36 +2022,76 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
var amazonS3Client = new AmazonS3Client(credentials, clientConfig); var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
// ⭐ 关键变量
IDisposable? owner = null;
Stream sourceStream;
long contentLength;
// 根据源选择流式下载 // ========= 获取流 + 长度 =========
Stream sourceStream = source switch switch (source)
{
case ObjectStoreUse.AliyunOSS:
{ {
ObjectStoreUse.AliyunOSS => _ossClient.GetObject(aliConfig.BucketName, objectKey).Content,
ObjectStoreUse.AWS => (await amazonS3Client.GetObjectAsync(awsConfig.BucketName, objectKey, ct)).ResponseStream,
_ => throw new BusinessValidationFailedException("未定义的同步类型")
};
if (source == ObjectStoreUse.AliyunOSS) var obj = _ossClient.GetObject(
aliConfig.BucketName,
objectKey);
owner = obj;
sourceStream = obj.Content;
contentLength = obj.ContentLength;
break;
}
case ObjectStoreUse.AWS:
{
var response = await amazonS3Client.GetObjectAsync(
awsConfig.BucketName,
objectKey,
ct);
owner = response;
sourceStream = response.ResponseStream;
contentLength = response.Headers.ContentLength;
break;
}
default:
throw new BusinessValidationFailedException("未定义的同步类型");
}
try
{
// ========= 上传 =========
if (destination == ObjectStoreUse.AWS)
{ {
var putRequest = new Amazon.S3.Model.PutObjectRequest var putRequest = new Amazon.S3.Model.PutObjectRequest
{ {
BucketName = awsConfig.BucketName, BucketName = awsConfig.BucketName,
Key = objectKey, Key = objectKey,
InputStream = sourceStream InputStream = sourceStream,
Headers = { ContentLength = contentLength }
}; };
await amazonS3Client.PutObjectAsync(putRequest, ct); await amazonS3Client.PutObjectAsync(putRequest, ct);
} }
else if (source == ObjectStoreUse.AWS) else if (destination == ObjectStoreUse.AliyunOSS)
{ {
_ossClient.PutObject(aliConfig.BucketName, objectKey, sourceStream); _ossClient.PutObject(
aliConfig.BucketName,
objectKey,
sourceStream);
} }
else else
{ {
throw new BusinessValidationFailedException("未定义的同步类型"); throw new BusinessValidationFailedException("未定义的同步类型");
} }
}
await sourceStream.DisposeAsync(); // 释放流 finally
{
// ⭐⭐⭐ 真正释放 HTTP 连接
owner?.Dispose();
}
} }
} }
+16
View File
@@ -0,0 +1,16 @@
using AutoMapper;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.SCP.Service;
namespace IRaCIS.Core.Application.Service
{
public class CommonConfig : Profile
{
public CommonConfig()
{
CreateMap<FileUploadRecordAddOrEdit, FileUploadRecord>().ReverseMap();
}
}
}
@@ -8,6 +8,26 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "eiirc.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@@ -19,6 +39,18 @@
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-irc-store",
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
"DurationSeconds": 7200
} }
}, },
@@ -0,0 +1,76 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.test.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "rayplus-irc-test-store",
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
@@ -7,7 +7,28 @@
} }
}, },
"ObjectStoreService": { "ObjectStoreService": {
// 使用的对象存储服务类型
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.test.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.test.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@@ -29,6 +50,27 @@
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy", "secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"bucketName": "hir-test", "bucketName": "hir-test",
"viewEndpoint": "http://106.14.89.110:9001/hir-test/" "viewEndpoint": "http://106.14.89.110:9001/hir-test/"
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
} }
}, },
@@ -0,0 +1,76 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.test.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "rayplus-irc-test-store",
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
+32
View File
@@ -8,6 +8,38 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AWS", "ObjectStoreUse": "AWS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "US",
"SyncConfigList": [
{
"Domain": "eilili.elevateimaging.ai",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.elevateimaging.ai",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "zy-lili-store",
"ViewEndpoint": "https://zy-lili-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"AWS": { "AWS": {
"Region": "us-east-1", "Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com", "EndPoint": "s3.us-east-1.amazonaws.com",
@@ -0,0 +1,76 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-test-store",
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HeAnShu;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server101.132.253.119,1435;Database=Uat_HeAnShu_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
+46 -5
View File
@@ -8,17 +8,58 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com", "EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "tl-med-irc-uat-store", "BucketName": "zy-irc-test-store",
"ViewEndpoint": "https://tl-med-irc-uat-store.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
@@ -0,0 +1,76 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "rayplus-irc-uat-store",
"ViewEndpoint": "https://rayplus-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
// AWS S3 对象存储服务的配置
"AWS": {
// AWS S3 的Region
"Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server101.132.253.119,1435;Database=Uat_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
@@ -1,43 +1,21 @@
using AlibabaCloud.SDK.Sts20150401; using AlibabaCloud.SDK.Sts20150401;
using Amazon.Auth.AccessControlPolicy;
using Amazon.SecurityToken; using Amazon.SecurityToken;
using AutoMapper;
using Azure.Core;
using IdentityModel.Client;
using IdentityModel.OidcClient;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MassTransit; using MassTransit;
using MassTransit.Futures.Contracts;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Org.BouncyCastle.Tls;
using RestSharp;
using RestSharp.Authenticators;
using Serilog; using Serilog;
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text; using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using ZiggyCreatures.Caching.Fusion;
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest; using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
namespace IRaCIS.Api.Controllers namespace IRaCIS.Api.Controllers
{ {
@@ -1,11 +1,9 @@
using AutoMapper; using AutoMapper;
using ExcelDataReader; using ExcelDataReader;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.BusinessFilter; using IRaCIS.Core.Application.BusinessFilter;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.Dicom; using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Command; using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.Service; using IRaCIS.Core.Application.Service;
@@ -17,8 +15,6 @@ using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MassTransit.Mediator; using MassTransit.Mediator;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
@@ -27,21 +23,15 @@ using Microsoft.AspNetCore.StaticFiles;
using Microsoft.AspNetCore.WebUtilities; using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using MiniExcelLibs; using MiniExcelLibs;
using Newtonsoft.Json; using Newtonsoft.Json;
using SharpCompress.Archives; using SharpCompress.Archives;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Data; using System.Data;
using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace IRaCIS.Core.API.Controllers namespace IRaCIS.Core.API.Controllers
@@ -132,7 +122,7 @@ namespace IRaCIS.Core.API.Controllers
//处理压缩文件 //处理压缩文件
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase)) if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
{ {
var archive = ArchiveFactory.Open(section.Body); var archive = ArchiveFactory.OpenArchive(section.Body);
foreach (var entry in archive.Entries) foreach (var entry in archive.Entries)
{ {
@@ -213,7 +203,7 @@ namespace IRaCIS.Core.API.Controllers
//处理压缩文件 //处理压缩文件
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase)) if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
{ {
var archive = ArchiveFactory.Open(section.Body); var archive = ArchiveFactory.OpenArchive(section.Body);
foreach (var entry in archive.Entries) foreach (var entry in archive.Entries)
{ {
@@ -857,7 +847,7 @@ namespace IRaCIS.Core.API.Controllers
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_TemplateUploadData"]); throw new BusinessValidationFailedException(_localizer["UploadDownLoad_TemplateUploadData"]);
} }
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/SiteSurvey", realFileName, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId ,BatchDataType=BatchDataType.SiteUserSurvey}); var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/SiteSurvey", realFileName, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.SiteUserSurvey });
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true); await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
@@ -933,7 +923,7 @@ namespace IRaCIS.Core.API.Controllers
} }
//处理好 用户类型 和用户类型枚举 //处理好 用户类型 和用户类型枚举
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList(); var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId = t.Id }).ToList(); var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId = t.Id, t.Country }).ToList();
foreach (var item in excelList) foreach (var item in excelList)
{ {
@@ -955,6 +945,8 @@ namespace IRaCIS.Core.API.Controllers
} }
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).TrialSiteId; item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).TrialSiteId;
item.Country = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).Country;
} }
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList(); var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
+7 -8
View File
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId> <UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>
@@ -10,6 +9,7 @@
<Company>上海展影医疗科技有限公司</Company> <Company>上海展影医疗科技有限公司</Company>
<Product>IRC影像系统 (EICS)</Product> <Product>IRC影像系统 (EICS)</Product>
<Copyright>上海展影医疗科技有限公司版权所有</Copyright> <Copyright>上海展影医疗科技有限公司版权所有</Copyright>
<NoWarn>$(NoWarn);NU1903</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -69,22 +69,21 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" /> <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" /> <PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.20" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.8.23" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" /> <PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" /> <PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" /> <PackageReference Include="Hangfire.SqlServer" Version="1.8.23" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" /> <PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Email" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.2.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+49
View File
@@ -378,6 +378,11 @@
LowerCamelCaseJsonAttribute 可以设置类小写返回给前端 LowerCamelCaseJsonAttribute 可以设置类小写返回给前端
</summary> </summary>
</member> </member>
<member name="T:Program">
<summary>
Auto-generated public partial Program class for top-level statement apps.
</summary>
</member>
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService"> <member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
<summary> <summary>
对称可逆加密 对称可逆加密
@@ -413,5 +418,49 @@
<param name="withPrivate"></param> <param name="withPrivate"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type)">
<summary>
Generates a documentation comment ID for a type.
Example: T:Namespace.Outer+Inner`1 becomes T:Namespace.Outer.Inner`1
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.PropertyInfo)">
<summary>
Generates a documentation comment ID for a property.
Example: P:Namespace.ContainingType.PropertyName or for an indexer P:Namespace.ContainingType.Item(System.Int32)
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type,System.String)">
<summary>
Generates a documentation comment ID for a property given its container type and property name.
Example: P:Namespace.ContainingType.PropertyName
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.MethodInfo)">
<summary>
Generates a documentation comment ID for a method (or constructor).
For example:
M:Namespace.ContainingType.MethodName(ParamType1,ParamType2)~ReturnType
M:Namespace.ContainingType.#ctor(ParamType)
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.GetTypeDocId(System.Type,System.Boolean,System.Boolean)">
<summary>
Generates a documentation ID string for a type.
This method handles nested types (replacing '+' with '.'),
generic types, arrays, pointers, by-ref types, and generic parameters.
The <paramref name="includeGenericArguments"/> flag controls whether
constructed generic type arguments are emitted, while <paramref name="omitGenericArity"/>
controls whether the generic arity marker (e.g. "`1") is appended.
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.NormalizeDocId(System.String)">
<summary>
Normalizes a documentation comment ID to match the compiler-style format.
Strips the return type suffix for ordinary methods but retains it for conversion operators.
</summary>
<param name="docId">The documentation comment ID to normalize.</param>
<returns>The normalized documentation comment ID.</returns>
</member>
</members> </members>
</doc> </doc>
+4 -2
View File
@@ -65,7 +65,8 @@ SerilogExtension.AddSerilogSetup(enviromentName);
var builder = WebApplication.CreateBuilder(new WebApplicationOptions var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{ {
EnvironmentName = enviromentName EnvironmentName = enviromentName,
Args = args
}); });
#region #region
@@ -102,7 +103,7 @@ builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddHealthChecks(); builder.Services.AddHealthChecks();
builder.Services.AddSerilog(); builder.Services.AddSerilog();
//本地化 //本地化
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim() // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
builder.Services.AddControllers(options => builder.Services.AddControllers(options =>
@@ -285,6 +286,7 @@ try
#region #region
Log.Logger.Warning($"当前环境:{enviromentName}"); Log.Logger.Warning($"当前环境:{enviromentName}");
Log.Logger.Warning($".NET 运行时版本:{Environment.Version}");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
+20 -2
View File
@@ -25,6 +25,24 @@
}, },
"applicationUrl": "http://0.0.0.0:6100" "applicationUrl": "http://0.0.0.0:6100"
}, },
"IRaCIS.Test_Rayplus": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_Rayplus",
"ASPNETCORE_OpenSwagger": "true"
},
"applicationUrl": "http://0.0.0.0:6100"
},
"IRaCIS.Uat_Rayplus": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Uat_Rayplus",
"ASPNETCORE_OpenSwagger": "true"
},
"applicationUrl": "http://0.0.0.0:6100"
},
"IRaCIS.Test_IRC_PGSQL": { "IRaCIS.Test_IRC_PGSQL": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
@@ -33,11 +51,11 @@
}, },
"applicationUrl": "http://0.0.0.0:6100" "applicationUrl": "http://0.0.0.0:6100"
}, },
"IRaCIS.Event_IRC": { "IRaCIS.Prod_Event_IRC": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Event_IRC" "ASPNETCORE_ENVIRONMENT": "Prod_Event_IRC"
}, },
"applicationUrl": "http://0.0.0.0:6100" "applicationUrl": "http://0.0.0.0:6100"
}, },
@@ -46,19 +46,19 @@ namespace IRaCIS.Core.API
var emailConfig = new SystemEmailSendConfig(); var emailConfig = new SystemEmailSendConfig();
configuration.GetSection("SystemEmailSendConfig").Bind(emailConfig); configuration.GetSection("SystemEmailSendConfig").Bind(emailConfig);
if (emailConfig.IsOpenErrorNoticeEmail) //if (emailConfig.IsOpenErrorNoticeEmail)
{ //{
config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions() // config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions()
{ // {
From = emailConfig.FromEmail, // From = emailConfig.FromEmail,
To = emailConfig.ErrorNoticeEmailList, // To = emailConfig.ErrorNoticeEmailList,
Host = emailConfig.Host, // Host = emailConfig.Host,
Port = emailConfig.Port, // Port = emailConfig.Port,
Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"), // Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"),
Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode) // Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode)
}, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error); // }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
} //}
#endregion #endregion
Log.Logger = config.CreateLogger(); Log.Logger = config.CreateLogger();
@@ -1,15 +1,7 @@
using Microsoft.AspNetCore.Builder; using Microsoft.OpenApi;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters; using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
namespace IRaCIS.Core.API; namespace IRaCIS.Core.API;
@@ -52,18 +44,21 @@ public static class SwaggerSetup
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
typeof(SwaggerVersion).GetFields(BindingFlags.Public | BindingFlags.Static).ToList() // 使用反射获取字段并动态创建 Swagger 文档
typeof(SwaggerVersion).GetFields(BindingFlags.Public | BindingFlags.Static)
.ToList()
.ForEach(field => .ForEach(field =>
{ {
var description = field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? field.Name; var description = field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? field.Name;
options.SwaggerDoc(field.Name, new Microsoft.OpenApi.Models.OpenApiInfo options.SwaggerDoc(field.Name, new OpenApiInfo
{ {
Version = field.Name, Version = field.Name,
Description = $"{field.Name} API", Description = $"{field.Name} API",
Title = description // 使用Description作为Title Title = description // 使用 Description 作为 Title
}); });
}); });
// 接口排序 // 接口排序
options.OrderActionsBy(o => o.GroupName); options.OrderActionsBy(o => o.GroupName);
+40 -39
View File
@@ -7,8 +7,10 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=101.132.193.237,1433;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
}, },
"WeComNoticeConfig": { "WeComNoticeConfig": {
"IsOpenWeComNotice": true, "IsOpenWeComNotice": true,
@@ -17,9 +19,27 @@
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ] "VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "eiirc.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@@ -28,46 +48,30 @@
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T", "AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access", "RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "tl-med-irc-event-store", "BucketName": "tl-med-irc-event-store",
"ViewEndpoint": "https://tl-med-irc-event-store.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://tl-med-rc-event-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
}, },
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": { "AWS": {
"Region": "us-east-1", "Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com", "EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true, "UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload", "RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z", "AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
"SecretAccessKey": "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", "SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
"BucketName": "ei-med-s3-lili-uat-store", "BucketName": "ei-med-s3-irc-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/", "ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
"DurationSeconds": 7200 "DurationSeconds": 7200
} }
}, },
"BasicSystemConfig": { "BasicSystemConfig": {
// 启用质控风险控制功能 // 启用质控风险控制功能
"QCRiskControl": true, "QCRiskControl": true,
"OpenUserComplexPassword": true, "OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true, "OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true, "OpenLoginLimit": false,
"LoginMaxFailCount": 5, "LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30, "LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120, "AutoLoginOutMinutes": 120,
@@ -82,17 +86,17 @@
"TemplateType": 2, "TemplateType": 2,
//MFA免验证发送天数 //MFA免验证发送天数
"UserMFAVerifyMinutes": 1440 "UserMFAVerifyMinutes": 1440
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
"Port": 465, "Port": 465,
"Host": "smtp.qiye.aliyun.com", "Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com", "Imap": "imap.qiye.aliyun.com",
"ImapPort": 993, "ImapPort": 993,
"FromEmail": "uat@extimaging.com", "FromEmail": "irc@extimaging.com",
"FromName": "Uat IRC Imaging System", "FromName": "EIC Imaging System",
"AuthorizationCode": "SHzyyl2021", "AuthorizationCode": "ExtImg@2022",
"SiteUrl": "http://irc.uat.extimaging.com/login", "SiteUrl": "http://irc.extimaging.com/login",
"PlatformName": "EICS", "PlatformName": "EICS",
"PlatformNameCN": "展影云平台", "PlatformNameCN": "展影云平台",
@@ -104,19 +108,16 @@
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false, "IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN", "CronEmailDefaultCulture": "zh-CN"
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
"Port": "11116", "Port": "11113",
"IP": "101.132.253.119" "IP": "101.132.193.237"
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
+37 -16
View File
@@ -7,10 +7,10 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=10.10.10.49,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", //"RemoteNew": "Server=10.10.10.49,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=10.10.10.49,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true" //"Hangfire": "Server=10.10.10.49,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true", "RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true" "Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
}, },
"WeComNoticeConfig": { "WeComNoticeConfig": {
"IsOpenWeComNotice": true, "IsOpenWeComNotice": true,
@@ -20,6 +20,26 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "eiirc.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
@@ -32,13 +52,16 @@
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
}, },
"MinIO": { "AWS": {
"endpoint": "http://192.168.3.68", "Region": "us-east-1",
"port": "8001", "EndPoint": "s3.us-east-1.amazonaws.com",
"useSSL": false, "UseSSL": true,
"accessKey": "IDFkwEpWej0b4DtiuThL", "RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h", "AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
"bucketName": "test" "SecretAccessKey": "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",
"BucketName": "ei-med-s3-irc-store",
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
"DurationSeconds": 7200
} }
}, },
"BasicSystemConfig": { "BasicSystemConfig": {
@@ -71,7 +94,7 @@
"Imap": "imap.qiye.aliyun.com", "Imap": "imap.qiye.aliyun.com",
"ImapPort": 993, "ImapPort": 993,
"FromEmail": "irc@extimaging.com", "FromEmail": "irc@extimaging.com",
"FromName": "IRC Imaging System", "FromName": "EIC Imaging System",
"AuthorizationCode": "ExtImg@2022", "AuthorizationCode": "ExtImg@2022",
"SiteUrl": "http://irc.extimaging.com/login", "SiteUrl": "http://irc.extimaging.com/login",
@@ -85,10 +108,8 @@
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false, "IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN", "CronEmailDefaultCulture": "zh-CN"
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
"Port": "11113", "Port": "11113",
@@ -96,7 +117,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
@@ -0,0 +1,143 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
},
"WeComNoticeConfig": {
"IsOpenWeComNotice": true,
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
"APINoticeUserList": [ "u", "wait..." ],
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "rayplus-irc-store",
"ViewEndpoint": "https://rayplus-irc-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
// 启用质控风险控制功能
"QCRiskControl": true,
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA免验证发送天数
"UserMFAVerifyMinutes": 1440
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "irc@mail.rayplus.net",
"FromName": "RayPlus Imaging System",
"AuthorizationCode": "QWE1zxcv7632",
"SiteUrl": "https://irc.rayplus.net/login",
"PlatformName": "RayPlus",
"PlatformNameCN": "睿佳影像云平台",
"SystemShortName": "RayPlus",
"OrganizationName": "RayPlus",
"OrganizationNameCN": "RayPlus",
"CompanyName": "RayPlus",
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
"CompanyShortName": "RayPlus",
"CompanyShortNameCN": "睿佳",
"IsEnv_US": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "47.117.165.18"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}
+20 -102
View File
@@ -1,34 +1,30 @@
{ {
// 日志信息
"Logging": { "Logging": {
// 日志等级
"LogLevel": { "LogLevel": {
// 默认日志等级
"Default": "Information", "Default": "Information",
// 调试日志等级
"Microsoft": "Warning", "Microsoft": "Warning",
// ASP.NET Core 日志等级
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
// 数据库链接字符串
"ConnectionStrings": { "ConnectionStrings": {
// 本地数据库链接字符串
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
// Hangfire 定时任务数据库链接字符串
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
}, },
"WeComNoticeConfig": { "WeComNoticeConfig": {
"IsOpenWeComNotice": true, "IsOpenWeComNotice": true,
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322 "WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449",
"APINoticeUserList": [ "u", "wait..." ], "APINoticeUserList": [
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ] "u",
"wait..."
],
"VueNoticeUserList": [
"wangxiaoshuang",
"6b7717a31647293621b97b96f74e6f3d"
]
}, },
// 对象存储服务配置
"ObjectStoreService": { "ObjectStoreService": {
// 使用的对象存储服务类型
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true, "IsOpenStoreSync": false,
"ApiDeployRegion": "CN", "ApiDeployRegion": "CN",
"SyncConfigList": [ "SyncConfigList": [
{ {
@@ -45,169 +41,91 @@
"Target": "AliyunOSS", "Target": "AliyunOSS",
"UploadRegion": "US", "UploadRegion": "US",
"TargetRegion": "CN", "TargetRegion": "CN",
"IsOpenSync": true "IsOpenSync": false
} }
], ],
// 阿里云对象存储服务的配置
"AliyunOSS": { "AliyunOSS": {
// 阿里云 OSS 的 Region ID
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
// 阿里云 OSS 的内部访问端点
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com", "InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
// 阿里云 OSS 的外部访问端点
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com", "EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
// 阿里云 OSS 的访问密钥 ID
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
// 阿里云 OSS 的访问密钥 Secret
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
// 阿里云 OSS 的角色 ARN
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
// 阿里云 OSS 的Bucket名称
"BucketName": "zy-irc-test-store", "BucketName": "zy-irc-test-store",
// 阿里云 OSS 的访问端点
"ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com",
// 阿里云 OSS 的预览端点
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
// 阿里云 OSS 的临时访问凭证有效时间(秒)
"DurationSeconds": 7200, "DurationSeconds": 7200,
// 阿里云 OSS 的预览端点
"PreviewEndpoint": "https://test-oss.test.extimaging.com" "PreviewEndpoint": "https://test-oss.test.extimaging.com"
}, },
// MinIO 对象存储服务的配置
"MinIO": { "MinIO": {
// MinIO 的访问端点
"EndPoint": "hir-oss.test.extimaging.com", "EndPoint": "hir-oss.test.extimaging.com",
// MinIO 的端口
"Port": "443", "Port": "443",
// 是否使用 SSL
"UseSSL": true, "UseSSL": true,
// MinIO 的角色 ARN
"AccessKey": "fbStsVYCIPKHQneeqMwD", "AccessKey": "fbStsVYCIPKHQneeqMwD",
// MinIO 的访问密钥
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy", "SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
// MinIO 的BucketName
"BucketName": "irc-test", "BucketName": "irc-test",
// MinIO 的访问端点
"ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test" "ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
}, },
// AWS S3 对象存储服务的配置
"AWS": { "AWS": {
// AWS S3 的Region
"Region": "us-east-1", "Region": "us-east-1",
// AWS S3 的内部访问端点
"EndPoint": "s3.us-east-1.amazonaws.com", "EndPoint": "s3.us-east-1.amazonaws.com",
// 是否使用 SSL
"UseSSL": true, "UseSSL": true,
// AWS S3 的角色 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access", "RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 的访问密钥 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4", "AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 的访问密钥 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc", "SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 的Bucket名称
"BucketName": "ei-med-s3-lili-uat-store", "BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 的访问端点
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com", "ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3 的持续数秒
"DurationSeconds": 7200 "DurationSeconds": 7200
} }
}, },
// 系统配置
"BasicSystemConfig": { "BasicSystemConfig": {
// 启用质控风险控制功能
"QCRiskControl": true, "QCRiskControl": true,
// 打开用户复杂密码
"OpenUserComplexPassword": false, "OpenUserComplexPassword": false,
// 是否在开始工作前强制签署电子知情同意书
"OpenSignDocumentBeforeWork": false, "OpenSignDocumentBeforeWork": false,
// 是否启用登录失败次数限制(防暴力破解)
"OpenLoginLimit": false, "OpenLoginLimit": false,
// 连续登录失败多少次后触发锁定
"LoginMaxFailCount": 5, "LoginMaxFailCount": 5,
// 触发锁定后账号锁定时长(分钟)
"LoginFailLockMinutes": 1, "LoginFailLockMinutes": 1,
// 无操作自动登出的超时时间(分钟)
"AutoLoginOutMinutes": 10, "AutoLoginOutMinutes": 10,
// 是否启用多因子登录认证(MFA)
"OpenLoginMFA": false, "OpenLoginMFA": false,
// 连续阅片的最长工作时间(分钟),超时后强制休息
"ContinuousReadingTimeMin": 120, "ContinuousReadingTimeMin": 120,
// 强制休息时长(分钟)
"ReadingRestTimeMin": 10, "ReadingRestTimeMin": 10,
// 是否强制用户定期修改密码
"IsNeedChangePassWord": true, "IsNeedChangePassWord": true,
// 密码有效期(天),到期后必须修改
"ChangePassWordDays": 90, "ChangePassWordDays": 90,
// 模板类型 1 ElevateLiLi 2 Extensive(展影)
"TemplateType": 2, "TemplateType": 2,
// 是否打开项目关联删除 "OpenTrialRelationDelete": false,
"OpenTrialRelationDelete": true,
// 转换PDF服务配置
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf", "ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf",
//MFA免验证发送天数
"UserMFAVerifyMinutes": 1440 "UserMFAVerifyMinutes": 1440
}, },
// 邮件服务配置(用于系统通知、找回密码、错误报警等)
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
// SMTP端口
"Port": 465,
// 企业邮箱SMTP服务器地址
"Host": "smtp.qiye.aliyun.com", "Host": "smtp.qiye.aliyun.com",
"Port": 465,
"Imap": "imap.qiye.aliyun.com", "Imap": "imap.qiye.aliyun.com",
"ImapPort": 993, "ImapPort": 993,
// 发件人邮箱地址
"FromEmail": "test@extimaging.com", "FromEmail": "test@extimaging.com",
// 发件人显示名称 "FromName": "Test EIC Imaging System",
"FromName": "Test IRC Imaging System",
// SMTP授权码
"AuthorizationCode": "SHzyyl2021", "AuthorizationCode": "SHzyyl2021",
// 系统对外访问地址
"SiteUrl": "http://irc.test.extimaging.com/login", "SiteUrl": "http://irc.test.extimaging.com/login",
"SystemShortName": "IRC",
"OrganizationName": "ExtImaging",
"OrganizationNameCN": "ExtImaging",
"PlatformName": "EICS", "PlatformName": "EICS",
"PlatformNameCN": "展影云平台", "PlatformNameCN": "展影云平台",
// 系统简称一致性核查使用
"SystemShortName": "IRC",
// 组织英文名称
"OrganizationName": "ExtImaging",
// 组织中文名称
"OrganizationNameCN": "ExtImaging",
// 公司英文全称
"CompanyName": "Extensive Imaging", "CompanyName": "Extensive Imaging",
// 公司中文全称
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
// 公司英文简称
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
// 公司中文简称
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
// 是否为国际版环境
"IsEnv_US": false, "IsEnv_US": false,
// 是否开启系统异常邮件报警
"IsOpenErrorNoticeEmail": false,
// 邮箱格式校验正则表达式
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN", "CronEmailDefaultCulture": "zh-CN"
// 接收系统异常报警的邮箱列表
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
// PACS 连接配置
"SystemPacsConfig": { "SystemPacsConfig": {
// PACS服务器端口
"Port": "11113", "Port": "11113",
// PACS服务器IP地址
"IP": "106.14.89.110" "IP": "106.14.89.110"
}, },
// 重复请求配置
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
// 是否启用重复请求检测
"IsEnabled": true, "IsEnabled": true,
// 重复请求时间窗口(毫秒) "DuplicationWindowMs": 500,
"DuplicationWindowMs": 200,
// 缓存请求时间(秒)
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": []
]
} }
} }
@@ -97,7 +97,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
@@ -0,0 +1,143 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"WeComNoticeConfig": {
"IsOpenWeComNotice": true,
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
"APINoticeUserList": [ "u", "wait..." ],
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.test.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "rayplus-irc-test-store",
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
// 启用质控风险控制功能
"QCRiskControl": true,
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA免验证发送天数
"UserMFAVerifyMinutes": 1440
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "test_irc@mail.rayplus.net",
"FromName": "Test RayPlus Imaging System",
"AuthorizationCode": "QWE1zxcv7632",
"SiteUrl": "https://irc.test.rayplus.net/login",
"PlatformName": "RayPlus",
"PlatformNameCN": "睿佳影像云平台",
"SystemShortName": "RayPlus",
"OrganizationName": "RayPlus",
"OrganizationNameCN": "RayPlus",
"CompanyName": "RayPlus",
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
"CompanyShortName": "RayPlus",
"CompanyShortNameCN": "睿佳",
"IsEnv_US": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.253.119"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}
+33 -13
View File
@@ -20,16 +20,38 @@
}, },
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AWS", "ObjectStoreUse": "AWS",
"MinIO": { "IsOpenStoreSync": true,
"endPoint": "44.210.231.169", "ApiDeployRegion": "US",
"port": "9001", "SyncConfigList": [
"useSSL": false, {
"accessKey": "e9bT1isTOqSAUxb6wd4n", "Domain": "eilili.elevateimaging.ai",
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i", "Primary": "AliyunOSS",
"bucketName": "prod-irc-us", "Target": "AWS",
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/" "UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.elevateimaging.ai",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "zy-lili-store",
"ViewEndpoint": "https://zy-lili-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
}, },
"AWS": { "AWS": {
"Region": "us-east-1", "Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com", "EndPoint": "s3.us-east-1.amazonaws.com",
@@ -90,10 +112,8 @@
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login", "SiteUrl": "https://lili.elevateimaging.ai/login",
"IsEnv_US": true, "IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "en-US", "CronEmailDefaultCulture": "en-US"
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
@@ -102,7 +122,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
+2 -4
View File
@@ -93,9 +93,7 @@
"CompanyShortName": "Elevate Imaging", "CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login", "SiteUrl": "https://lili.test.elevateimaging.ai/login",
"IsEnv_US": true, "IsEnv_US": true
"IsOpenErrorNoticeEmail": false,
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
@@ -104,7 +102,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
+2 -4
View File
@@ -97,10 +97,8 @@
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.uat.elevateimaging.ai/login", "SiteUrl": "https://lili.uat.elevateimaging.ai/login",
"IsEnv_US": true, "IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "en-US", "CronEmailDefaultCulture": "en-US"
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
@@ -109,7 +107,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
@@ -0,0 +1,152 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HeAnShu;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HeAnShu_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"WeComNoticeConfig": {
"IsOpenWeComNotice": true,
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
"APINoticeUserList": [ "u", "wait..." ],
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "heanshu-irc-uat-store",
"ViewEndpoint": "https://heanshu-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
// 启用质控风险控制功能
"QCRiskControl": true,
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA免验证发送天数
"UserMFAVerifyMinutes": 1440
},
"SystemEmailSendConfig": {
//"Port": 465,
//"Host": "smtp.qiye.163.com",
//"Imap": "imap.qiye.163.com",
//"ImapPort": 993,
//"FromEmail": "service@heanshu.com",
//"FromName": "Uat HeAnShu Imaging System",
//"AuthorizationCode": "j#cAPU%XgvcHWn3N",
//"SiteUrl": "https://irc.uat.heanshu.com",
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "service@mail.rayplus.net",
"FromName": "Uat HeAnShu Imaging System",
"AuthorizationCode": "crefHpx3WtenFr6X",
"SiteUrl": "https://irc.uat.heanshu.com",
"PlatformName": "HeAnShu",
"PlatformNameCN": "禾安枢影像云平台",
"SystemShortName": "HeAnShu",
"OrganizationName": "HeAnShu",
"OrganizationNameCN": "HeAnShu",
"CompanyName": "HeAnShu",
"CompanyNameCN": "禾安枢软件科技有限公司",
"CompanyShortName": "HeAnShu",
"CompanyShortNameCN": "禾安枢",
"IsEnv_US": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.253.119"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}
+26 -8
View File
@@ -19,6 +19,26 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.extimaging.com",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": true
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": true
}
],
"AliyunOSS": { "AliyunOSS": {
"RegionId": "cn-shanghai", "RegionId": "cn-shanghai",
@@ -50,9 +70,9 @@
"Region": "us-east-1", "Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com", "EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true, "UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload", "RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z", "AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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", "SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
"BucketName": "ei-med-s3-lili-uat-store", "BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/", "ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200 "DurationSeconds": 7200
@@ -90,7 +110,7 @@
"Imap": "imap.qiye.aliyun.com", "Imap": "imap.qiye.aliyun.com",
"ImapPort": 993, "ImapPort": 993,
"FromEmail": "uat@extimaging.com", "FromEmail": "uat@extimaging.com",
"FromName": "Uat IRC Imaging System", "FromName": "Uat EIC Imaging System",
"AuthorizationCode": "SHzyyl2021", "AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.uat.extimaging.com/login", "SiteUrl": "http://irc.uat.extimaging.com/login",
@@ -104,10 +124,8 @@
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false, "IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN", "CronEmailDefaultCulture": "zh-CN"
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
@@ -116,7 +134,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
@@ -0,0 +1,143 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"WeComNoticeConfig": {
"IsOpenWeComNotice": true,
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
"APINoticeUserList": [ "u", "wait..." ],
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"IsOpenStoreSync": true,
"ApiDeployRegion": "CN",
"SyncConfigList": [
{
"Domain": "irc.uat.rayplus.net",
"Primary": "AliyunOSS",
"Target": "AWS",
"UploadRegion": "CN",
"TargetRegion": "US",
"IsOpenSync": false
},
{
"Domain": "lili.uat.extimaging.com",
"Primary": "AWS",
"Target": "AliyunOSS",
"UploadRegion": "US",
"TargetRegion": "CN",
"IsOpenSync": false
}
],
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "rayplus-irc-uat-store",
"ViewEndpoint": "https://rayplus-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
// 启用质控风险控制功能
"QCRiskControl": true,
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA免验证发送天数
"UserMFAVerifyMinutes": 1440
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "uat@mail.rayplus.net",
"FromName": "Uat RayPlus Imaging System",
"AuthorizationCode": "QWE1zxcv7632",
"SiteUrl": "https://irc.uat.rayplus.net/login",
"PlatformName": "RayPlus",
"PlatformNameCN": "睿佳影像云平台",
"SystemShortName": "RayPlus",
"OrganizationName": "RayPlus",
"OrganizationNameCN": "RayPlus",
"CompanyName": "RayPlus",
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
"CompanyShortName": "RayPlus",
"CompanyShortNameCN": "睿佳",
"IsEnv_US": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"CronEmailDefaultCulture": "zh-CN"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.253.119"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}
+1 -1
View File
@@ -77,7 +77,7 @@
}, },
"RequestDuplicationOptions": { "RequestDuplicationOptions": {
"IsEnabled": true, "IsEnabled": true,
"DuplicationWindowMs": 200, "DuplicationWindowMs": 500,
"CacheTimeSeconds": 5, "CacheTimeSeconds": 5,
"ExcludedPaths": [ "ExcludedPaths": [
] ]
+2 -1
View File
@@ -39,7 +39,8 @@ namespace IRaCIS.Core.Application.Auth
new Claim(JwtIRaCISClaimType.UserTypeShortName,user.UserTypeShortName), new Claim(JwtIRaCISClaimType.UserTypeShortName,user.UserTypeShortName),
new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr), new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr),
new Claim(JwtIRaCISClaimType.IsZhiZhun,user.IsZhiZhun.ToString()), new Claim(JwtIRaCISClaimType.IsZhiZhun,user.IsZhiZhun.ToString()),
new Claim(JwtIRaCISClaimType.IsTestUser,user.IsTestUser.ToString()) new Claim(JwtIRaCISClaimType.IsTestUser,user.IsTestUser.ToString()),
new Claim(JwtIRaCISClaimType.UserWorkLanguage,user.UserWorkLanguage.ToString())
}; };
////创建令牌 ////创建令牌
@@ -23,5 +23,7 @@ namespace IRaCIS.Core.Application.Auth
public bool IsZhiZhun { get; set; } public bool IsZhiZhun { get; set; }
public string UserTypeShortName { get; set; } = string.Empty; public string UserTypeShortName { get; set; } = string.Empty;
public UserWorkLanguage UserWorkLanguage { get; set; }
} }
} }
@@ -8,6 +8,8 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
{ {
using Database.Api; using Database.Api;
using DocumentFormat.OpenXml.InkML; using DocumentFormat.OpenXml.InkML;
using global::MassTransit;
using IRaCIS.Core.Application.Helper.OtherTool;
using IRaCIS.Core.Application.Service.Common; using IRaCIS.Core.Application.Service.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
@@ -17,6 +19,7 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@@ -35,7 +38,7 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
/// </summary> /// </summary>
/// <param name="logger">logger</param> /// <param name="logger">logger</param>
/// <param name="accessor">loggerHelper</param> /// <param name="accessor">loggerHelper</param>
public class RequestDuplicationFilter(ILogger<RequestDuplicationFilter> logger, IHttpContextAccessor accessor, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<RequestDuplicationOptions> RequestDuplicationOptionsMonitor) : ExceptionFilterAttribute, IAsyncActionFilter public class RequestDuplicationFilter(ILogger<RequestDuplicationFilter> logger, IHttpContextAccessor accessor, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<RequestDuplicationOptions> RequestDuplicationOptionsMonitor, IConfiguration _config) : ExceptionFilterAttribute, IAsyncActionFilter
{ {
/// <summary> /// <summary>
/// 传入的参数 /// 传入的参数
@@ -70,6 +73,10 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
{ {
this.RequestDuplication(); this.RequestDuplication();
} }
catch (BusinessValidationFailedException)
{
throw;
}
catch (Exception) catch (Exception)
{ {
@@ -89,8 +96,12 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
{ {
var requestPath = accessor?.HttpContext?.Request?.Path.ToString() ?? string.Empty; var requestPath = accessor?.HttpContext?.Request?.Path.ToString() ?? string.Empty;
var httpMethod = accessor?.HttpContext?.Request?.Method?.ToUpper() ?? string.Empty;
// 验证请求频繁情况 // 验证请求频繁情况
if ( if (
!httpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) &&
!requestPath !requestPath
.Split("/", StringSplitOptions.RemoveEmptyEntries) .Split("/", StringSplitOptions.RemoveEmptyEntries)
.Any(segment => segment.StartsWith("get", StringComparison.OrdinalIgnoreCase)) && .Any(segment => segment.StartsWith("get", StringComparison.OrdinalIgnoreCase)) &&
@@ -106,17 +117,54 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
RequestTime = DateTime.Now RequestTime = DateTime.Now
}; };
IRCSystemInfo.RequestRecordList= IRCSystemInfo.RequestRecordList.Where(x => x.RequestTime >= DateTime.Now.AddSeconds(-RequestDuplicationOptionsMonitor.CurrentValue.CacheTimeSeconds)).ToList(); var isAdded = IRCSystemInfo.TryAddRequestRecord(
requestInfo,
RequestDuplicationOptionsMonitor.CurrentValue.CacheTimeSeconds,
var requestsTimes = IRCSystemInfo.RequestRecordList.Any(x=> RequestDuplicationOptionsMonitor.CurrentValue.DuplicationWindowMs);
x.RequestTime>= requestInfo.RequestTime.AddMilliseconds(-RequestDuplicationOptionsMonitor.CurrentValue.DuplicationWindowMs)&& if (!isAdded)
x.RequestKey== requestInfo.RequestKey);
if (requestsTimes)
{ {
throw new BusinessValidationFailedException(_localizer["RequestDuplicationFilter_RequestDuplication"], ApiResponseCodeEnum.BusinessValidationFailed); SendRequestDuplicationWeComNotice(requestPath);
logger.LogError($"重复请求出现错误:{this.Intoparam}");
throw new BusinessValidationFailedException(_localizer["RequestDuplicationFilter_RequestDuplication"], ApiResponseCodeEnum.NotRemind);
} }
IRCSystemInfo.RequestRecordList.Add(requestInfo); }
}
private void SendRequestDuplicationWeComNotice(string requestPath)
{
try
{
bool isOpenWeComNotice = _config.GetValue<bool>("WeComNoticeConfig:IsOpenWeComNotice");
if (isOpenWeComNotice)
{
string webhook = _config["WeComNoticeConfig:WebhookUrl"] ?? string.Empty;
var uri = new Uri(_config["SystemEmailSendConfig:SiteUrl"]);
var baseUrl = uri.GetLeftPart(UriPartial.Authority);
var userList = _config.GetSection("WeComNoticeConfig:VueNoticeUserList").Get<string[]>();
var request = accessor?.HttpContext?.Request;
_ = WeComNotifier.SendAlertAsync(
webhook: webhook,
alert: new WeComAlert
{
Env = baseUrl,
UserName = _userInfo.UserName.IsNotNullOrEmpty() ? $"{_userInfo.UserName}({_userInfo.UserTypeShortName})" : "匿名",
Api = $"{request?.Method} {requestPath}",
Message = "重复请求拦截",
JsonData = this.Intoparam,
Stack = string.Empty,
AtUsers = userList ?? []
}
);
}
}
catch (Exception ex)
{
logger.LogError($"重复请求过滤器里发送企业微信出现错误:{ex.Message}");
} }
} }
@@ -37,13 +37,13 @@ public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _
#region #region
// 用户类型检查 // 用户类型检查
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower()) //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ //{
//对不起,您的账户没有操作权限 // //对不起,您的账户没有操作权限
context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission"))); // context.Result = new JsonResult(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission")));
return; // return;
} //}
#endregion #endregion
@@ -47,12 +47,12 @@ public class TrialGlobalLimitEndpointFilter(IFusionCache _fusionCache, IUserInfo
} }
#region #region
// 用户类型检查 //// 用户类型检查
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower()) //if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ //{
//对不起,您的账户没有操作权限 // //对不起,您的账户没有操作权限
return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission"))); // return Results.Json(ResponseOutput.NotOk(I18n.T("TrialResource_NoAccessPermission")));
} //}
#endregion #endregion
@@ -79,11 +79,12 @@ public class SystemEmailSendConfig
public bool IsEnv_US { get; set; } public bool IsEnv_US { get; set; }
public bool IsOpenErrorNoticeEmail { get; set; }
public string EmailRegexStr { get; set; } public string EmailRegexStr { get; set; }
public List<string> ErrorNoticeEmailList { get; set; } = new List<string>(); //public bool IsOpenErrorNoticeEmail { get; set; }
//public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
} }
public class SystemEmailSendConfigView public class SystemEmailSendConfigView
@@ -145,6 +146,31 @@ public class RequestDuplicationOptions
public static class IRCSystemInfo public static class IRCSystemInfo
{ {
public static List<RequestInfo> RequestRecordList { get; set; } = new List<RequestInfo>(); public static List<RequestInfo> RequestRecordList { get; set; } = new List<RequestInfo>();
private static readonly object requestRecordLock = new object();
public static bool TryAddRequestRecord(RequestInfo requestInfo, int cacheTimeSeconds, int duplicationWindowMs)
{
lock (requestRecordLock)
{
var now = DateTime.Now;
RequestRecordList = RequestRecordList
.Where(x => x.RequestTime >= now.AddSeconds(-cacheTimeSeconds))
.ToList();
var isDuplicate = RequestRecordList.Any(x =>
x.RequestTime >= requestInfo.RequestTime.AddMilliseconds(-duplicationWindowMs) &&
x.RequestKey == requestInfo.RequestKey);
if (isDuplicate)
{
return false;
}
RequestRecordList.Add(requestInfo);
return true;
}
}
} }
public class RequestInfo public class RequestInfo
@@ -8,6 +8,8 @@ public static class CacheKeys
//项目缓存 //项目缓存
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}"; public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
public static string TrialVisitTaskMaxCode(Guid trialId) => $"TrialVisitTaskMaxCode:{trialId}";
//检查编号递增锁 //检查编号递增锁
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}"; public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
@@ -1,15 +1,8 @@
using DocumentFormat.OpenXml.Office.CustomUI; using FellowOakDicom;
using FellowOakDicom;
using FellowOakDicom.Media; using FellowOakDicom.Media;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper
{ {
@@ -160,6 +153,91 @@ namespace IRaCIS.Core.Application.Helper
} }
public static async Task GenerateStudyDIR(List<StudyDIRInfo> list, Dictionary<string, string> dic, string? dirSavePath = null, Stream? outputStream = null)
{
var mappings = new List<string>();
int index = 1;
var trialId = Guid.Empty;
var studyUid = list.FirstOrDefault()?.StudyInstanceUid;
var dicomDir = new DicomDirectory();
foreach (var item in list.OrderBy(t => t.SeriesNumber).ThenBy(t => t.InstanceNumber))
{
var dicomUid = DicomUID.Enumerate().FirstOrDefault(uid => uid.UID == item.TransferSytaxUID);
if (dicomUid != null)
{
var ts = DicomTransferSyntax.Query(dicomUid);
var dataset = new DicomDataset(ts)
{
{ DicomTag.PatientID, item.PatientId ?? string.Empty },
{ DicomTag.PatientName, item.PatientName ?? string.Empty },
{ DicomTag.PatientBirthDate, item.PatientBirthDate ?? string.Empty },
{ DicomTag.PatientSex, item.PatientSex ?? string.Empty },
{ DicomTag.StudyInstanceUID, item.StudyInstanceUid ?? string.Empty },
{ DicomTag.StudyID, item.StudyId ?? string.Empty },
{ DicomTag.StudyDate, item.DicomStudyDate ?? string.Empty },
{ DicomTag.StudyTime, item.DicomStudyTime ?? string.Empty },
{ DicomTag.AccessionNumber, item.AccessionNumber ?? string.Empty },
{ DicomTag.StudyDescription, item.StudyDescription ?? string.Empty },
{ DicomTag.SeriesInstanceUID, item.SeriesInstanceUid ?? string.Empty },
{ DicomTag.Modality, item.Modality ?? string.Empty },
{ DicomTag.SeriesDate, item.DicomSeriesDate ?? string.Empty },
{ DicomTag.SeriesTime, item.DicomSeriesTime ?? string.Empty },
{ DicomTag.SeriesNumber, item.SeriesNumber.ToString() ?? string.Empty },
{ DicomTag.SeriesDescription, item.SeriesDescription ?? string.Empty },
{ DicomTag.SOPInstanceUID, item.SopInstanceUid ?? string.Empty },
{ DicomTag.SOPClassUID, item.SOPClassUID ?? string.Empty },
{ DicomTag.InstanceNumber, item.InstanceNumber.ToString() ?? string.Empty },
{ DicomTag.MediaStorageSOPClassUID, item.MediaStorageSOPClassUID ?? string.Empty },
{ DicomTag.MediaStorageSOPInstanceUID, item.MediaStorageSOPInstanceUID ?? string.Empty },
{ DicomTag.TransferSyntaxUID, item.TransferSytaxUID ?? string.Empty },
};
var dicomFile = new DicomFile(dataset);
// 文件名递增格式:IM_00001, IM_00002, ...
string filename = $@"IMAGE\IM_{index:D5}"; // :D5 表示补足5位
mappings.Add($"{filename} => {item.InstanceId}");
dic.Add(item.InstanceId.ToString(), filename.TrimEnd('/', '\\').Split('/', '\\').Last());
dicomDir.AddFile(dicomFile, filename);
index++;
}
}
//有实际的文件
if (mappings.Count > 0)
{
// 保存 DICOMDIR 到临时文件 不能直接写入到流种
if (dirSavePath.IsNotNullOrEmpty())
{
await dicomDir.SaveAsync(dirSavePath);
}
else
{
await dicomDir.SaveAsync(outputStream);
}
}
}
public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile) public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile)
{ {
@@ -62,8 +62,15 @@ public static class SendEmailHelper
} }
/// <summary>
public static async Task<string> SendEmailAsync(MimeMessage messageToSend, Trial trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null) /// 发送项目邮件
/// </summary>
/// <param name="messageToSend"></param>
/// <param name="trial"></param>
/// <param name="messageSentSuccess"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static async Task<string> SendTrialEmailAsync(MimeMessage messageToSend, Trial trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
{ {
// 项目的需要重设 发件地址与邮件地址 // 项目的需要重设 发件地址与邮件地址
@@ -78,12 +85,39 @@ public static class SendEmailHelper
string result = string.Empty; string result = string.Empty;
result = messageToSend.MessageId; result = messageToSend.MessageId;
//没有收件人 那么不发送 //没有收件人 那么不发送
if (messageToSend.To.Count == 0) if (messageToSend.To.Count == 0)
{ {
return string.Empty; return string.Empty;
} }
// 替换邮件标题
if (!string.IsNullOrEmpty(messageToSend.Subject))
{
foreach (var item in trial.TrialObjectNameList)
{
// 把标题里的占位符替换成真实名称
messageToSend.Subject = messageToSend.Subject.Replace(item.Name, item.TrialName);
}
}
// 构建替换字典
var replacements = new Dictionary<string, string>();
foreach (var item in trial.TrialObjectNameList)
{
replacements[item.Name] = item.TrialName;
}
// 安全替换 HTML
ReplaceHtmlContent(messageToSend.Body, replacements);
try try
{ {
using (var smtp = new MailKit.Net.Smtp.SmtpClient()) using (var smtp = new MailKit.Net.Smtp.SmtpClient())
@@ -128,6 +162,27 @@ public static class SendEmailHelper
return result; return result;
} }
// 遍历邮件体,找到 HTML 部分并替换
public static void ReplaceHtmlContent(MimeEntity entity, Dictionary<string, string> replacements)
{
if (entity is Multipart multipart)
{
foreach (var part in multipart)
{
ReplaceHtmlContent(part, replacements);
}
}
else if (entity is TextPart textPart && textPart.IsHtml)
{
// 只有这里才是真正的 HTML
foreach (var kv in replacements)
{
textPart.Text = textPart.Text.Replace(kv.Key, kv.Value);
}
}
}
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig) public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
{ {
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5))) using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
@@ -147,7 +202,7 @@ public static class SendEmailHelper
return true; return true;
} }
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig,Trial? trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null) public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig, Trial? trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
{ {
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
@@ -161,8 +216,9 @@ public static class SendEmailHelper
if (sMTPEmailConfig.ToMailAddressList.Count == 0) if (sMTPEmailConfig.ToMailAddressList.Count == 0)
{ {
return;
//---没有收件人 //---没有收件人
throw new ArgumentException(I18n.T("SendEmail_NoRecipient")); //throw new ArgumentException(I18n.T("SendEmail_NoRecipient"));
} }
else else
{ {
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,4 @@
using IRaCIS.Core.Domain.Share; using System.Globalization;
using NPOI.XWPF.UserModel;
using System.Globalization;
using Xceed.Document.NET; using Xceed.Document.NET;
using Xceed.Words.NET; using Xceed.Words.NET;
@@ -54,42 +52,42 @@ public static class WordTempleteHelper
} }
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream) //public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
{ //{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; // var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) // using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{ // {
XWPFDocument doc = new XWPFDocument(fs); // XWPFDocument doc = new XWPFDocument(fs);
// 查找包含指定书签的段落及其索引 // // 查找包含指定书签的段落及其索引
var bookmarkParagraph = doc.Paragraphs // var bookmarkParagraph = doc.Paragraphs
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark)); // .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
if (bookmarkParagraph != null) // if (bookmarkParagraph != null)
{ // {
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph); // int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
if (isEn_US) // if (isEn_US)
{ // {
// 从书签所在段落开始,删除之前的所有段落 // // 从书签所在段落开始,删除之前的所有段落
for (int i = bookmarkIndex - 1; i >= 0; i--) // for (int i = bookmarkIndex - 1; i >= 0; i--)
{ // {
doc.RemoveBodyElement(i); // doc.RemoveBodyElement(i);
} // }
} // }
else // else
{ // {
// 删除书签之后的所有段落 // // 删除书签之后的所有段落
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--) // for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
{ // {
doc.RemoveBodyElement(i); // doc.RemoveBodyElement(i);
} // }
} // }
} // }
doc.Write(memoryStream); // doc.Write(memoryStream);
} // }
} //}
} }
+34 -14
View File
@@ -220,7 +220,7 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
public object result { get; private set; } public object result { get; private set; }
private static readonly object _tokenLock = new();
/// <summary> /// <summary>
/// 将指定前缀下的所有现有文件立即转为目标存储类型 /// 将指定前缀下的所有现有文件立即转为目标存储类型
@@ -934,32 +934,52 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
//后端批量上传 或者下载,不每个文件获取临时token //后端批量上传 或者下载,不每个文件获取临时token
private void BackBatchGetToken() private void BackBatchGetToken()
{ {
// 过期时间 ≤ 当前时间 + 15分钟 时需要续期
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{ {
if (AliyunOSSTempToken == null) if (AliyunOSSTempToken != null && AliyunOSSTempToken.Expiration > DateTime.Now.AddMinutes(15))
{ {
GetObjectStoreTempToken(); return; // 还有15分钟以上,不需要续期
}
//token 过期了
if (AliyunOSSTempToken?.Expiration.AddSeconds(10) <= DateTime.Now)
{
GetObjectStoreTempToken();
} }
lock (_tokenLock)
{
if (AliyunOSSTempToken == null ||
AliyunOSSTempToken.Expiration <= DateTime.Now.AddMinutes(15))
{
GetObjectStoreTempToken();
Log.Logger.Warning("后端获取阿里云临时 Token");
}
}
} }
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{ {
if (AWSTempToken == null)
{
GetObjectStoreTempToken(); if (AWSTempToken != null && AWSTempToken.Expiration > DateTime.Now.AddMinutes(15))
} {
//token 过期了 return;
if (AWSTempToken.Expiration?.AddSeconds(10) <= DateTime.Now) }
lock (_tokenLock)
{
if (AWSTempToken == null ||
AWSTempToken.Expiration <= DateTime.Now.AddMinutes(15))
{ {
GetObjectStoreTempToken(); GetObjectStoreTempToken();
Log.Logger.Warning("后端获取s3 临时 Token");
} }
} }
}
} }
@@ -3,8 +3,11 @@ using FellowOakDicom.Imaging;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.PixelFormats;
using IRaCIS.Core.Application.Helper;
using SixLabors.ImageSharp.Drawing.Processing;
namespace IRaCIS.Core.Application.Helper;
public static class ImageHelper public static class ImageHelper
{ {
@@ -60,6 +63,36 @@ public static class ImageHelper
} }
public static class ImageMaskHelper
{
public static async Task MaskAsync(Stream input, Stream output, IEnumerable<MaskRegion> regions)
{
// 确保输入流从起始位置读取
if (input.CanSeek && input.Position != 0)
{
input.Position = 0;
}
using var image = await Image.LoadAsync(input);
// 保存原始图片的编码格式
var originalFormat = image.Metadata.DecodedImageFormat;
image.Mutate(ctx =>
{
foreach (var r in regions)
{
ctx.Fill(Color.Black, new Rectangle(r.X, r.Y, r.Width, r.Height));
}
});
// 使用原始格式保存,保持格式不变
await image.SaveAsync(output, originalFormat);
}
}
} }
@@ -1,15 +1,5 @@
using System; using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using RestSharp; using RestSharp;
using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure.Extention;
using NPOI.SS.Formula.Functions;
namespace IRaCIS.Core.Application.Helper.OtherTool namespace IRaCIS.Core.Application.Helper.OtherTool
{ {
@@ -1,9 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
@@ -12,6 +10,7 @@
<OutputPath>..\bin\</OutputPath> <OutputPath>..\bin\</OutputPath>
<DocumentationFile>.\IRaCIS.Core.Application.xml</DocumentationFile> <DocumentationFile>.\IRaCIS.Core.Application.xml</DocumentationFile>
<NoWarn>1701;1702;1591</NoWarn> <NoWarn>1701;1702;1591</NoWarn>
<NoWarn>$(NoWarn);NU1903</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -32,13 +31,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ClosedXML" Version="0.105.0" />
<PackageReference Include="IdentityModel.OidcClient" Version="6.0.0" /> <PackageReference Include="IdentityModel.OidcClient" Version="6.0.0" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" /> <PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" /> <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="4.0.21" /> <PackageReference Include="AWSSDK.S3" Version="4.0.24" />
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.5.19" /> <PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
<PackageReference Include="DocX" Version="5.0.0" /> <PackageReference Include="DocX" Version="5.0.0" />
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" /> <PackageReference Include="FreeSpire.Doc" Version="14.4.0" />
<PackageReference Include="ExcelDataReader" Version="3.8.0" /> <PackageReference Include="ExcelDataReader" Version="3.8.0" />
<PackageReference Include="ExcelDataReader.DataSet" Version="3.8.0" /> <PackageReference Include="ExcelDataReader.DataSet" Version="3.8.0" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.1" /> <PackageReference Include="DistributedLock.Redis" Version="1.1.1" />
@@ -47,23 +47,23 @@
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" /> <PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.7" /> <PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
<PackageReference Include="IP2Region.Net" Version="3.0.2" /> <PackageReference Include="IP2Region.Net" Version="3.0.2" />
<PackageReference Include="MailKit" Version="4.15.1" /> <PackageReference Include="MailKit" Version="4.17.0" />
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.1.0" /> <PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.1.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="5.4.1" /> <PackageReference Include="MaxMind.GeoIP2" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
<PackageReference Include="MimeKit" Version="4.15.1" /> <PackageReference Include="MimeKit" Version="4.17.0" />
<PackageReference Include="MiniExcel" Version="1.41.2" /> <PackageReference Include="MiniExcel" Version="1.44.1" />
<PackageReference Include="Minio" Version="6.0.3" /> <PackageReference Include="Minio" Version="7.0.0" />
<PackageReference Include="MiniWord" Version="0.9.2" /> <PackageReference Include="MiniWord" Version="0.9.2" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0"> <PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="NPOI" Version="2.7.4" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" /> <PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="RestSharp" Version="114.0.0" /> <PackageReference Include="RestSharp" Version="114.0.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="10.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -59,17 +59,17 @@
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.AutoColumnStartIndex"> <member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.AutoColumnStartIndex">
<summary> <summary>
增加动态列开始索引 从0 开始 增加动态列开始索引 npoi从0开始 现在ClosedXML 从1开始
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.AutoColumnTitleRowIndex"> <member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.AutoColumnTitleRowIndex">
<summary> <summary>
动态列开始的行index 从0开始 动态列开始的行index npoi从0开始 现在ClosedXML 从1开始
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.TempalteLastColumnIndex"> <member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.TempalteLastColumnIndex">
<summary> <summary>
模板列最后的索引 模板列最后的索引 npoi从0开始 现在ClosedXML 从1开始
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.ColumnIdNameList"> <member name="P:IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig.ColumnIdNameList">
@@ -102,20 +102,6 @@
Excel Title Name Excel Title Name
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ExcelExportHelper.CDISC_DataExport_Async(System.String,IRaCIS.Application.Contracts.ExcelExportInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument},Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Application.Interfaces.IDictionaryService,System.Type,System.Nullable{IRaCIS.Core.Domain.Share.CriterionType},IRaCIS.Core.Application.Service.ExcelExportHelper.DynamicColumnConfig)">
<summary>
暂时废弃--合并到上面
</summary>
<param name="code"></param>
<param name="data"></param>
<param name="_commonDocumentRepository"></param>
<param name="_hostEnvironment"></param>
<param name="_dictionaryService"></param>
<param name="translateType"></param>
<param name="criterionType"></param>
<param name="dynamicColumnConfig"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ExcelExportHelper.ExportTemplateAsync(IRaCIS.Application.Contracts.ExportTemplateServiceDto)"> <member name="M:IRaCIS.Core.Application.Service.ExcelExportHelper.ExportTemplateAsync(IRaCIS.Application.Contracts.ExportTemplateServiceDto)">
<summary> <summary>
导出文件模板 导出文件模板
@@ -351,6 +337,12 @@
<param name="taskId"></param> <param name="taskId"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.VisitTaskHelpeService.GenerateTaskNo">
<summary>
从 NewId 的后 3 个字节(24 位)生成一个 6 位十六进制字符串
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.VisitTaskHelpeService.GetIsClinicalDataSignTest(System.Guid)"> <member name="M:IRaCIS.Core.Application.Service.VisitTaskHelpeService.GetIsClinicalDataSignTest(System.Guid)">
<summary> <summary>
获取GetIsClinicalDataSignTest 获取GetIsClinicalDataSignTest
@@ -363,7 +355,7 @@
访视读片任务 访视读片任务
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.Allocation.VisitTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskAllocationRule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTaskReReading},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluationVisitFilter},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCanceDoctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMarkBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskInfluence},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialQCQuestionAnswer},Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.Application.Service.Allocation.VisitTaskService},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluationVisitStudyFilter},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)"> <member name="M:IRaCIS.Core.Application.Service.Allocation.VisitTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskAllocationRule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTaskReReading},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluationVisitFilter},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCanceDoctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMarkBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskInfluence},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialQCQuestionAnswer},Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.Application.Service.Allocation.VisitTaskService},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectCriteriaEvaluationVisitStudyFilter},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary> <summary>
访视读片任务 访视读片任务
</summary> </summary>
@@ -559,119 +551,32 @@
系统模板文档配置表 系统模板文档配置表
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.Service.DictionaryService"> <member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.GetSystemBasicConfigInfo(Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption})">
<summary> <summary>
数据字典-基础数据维护 获取系统基础配置信息
</summary> </summary>
</member> <param name="options"></param>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DoctorDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Doctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemCriterionDictionaryCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialCriterionDictionaryCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
数据字典-基础数据维护
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddBoolDic(IRaCIS.Application.Contracts.AddOrEditBasicDic)">
<summary>
添加bool
</summary>
<param name="addOrEditBasic"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetAllDictionaryKey"> <member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.UpdateSystemBasicConfig(IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption)">
<summary> <summary>
获取所有字典的Key 更新系统基础配置
</summary> </summary>
<param name="basicSystemConfigOption"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddBasicDicAndChild(IRaCIS.Application.Contracts.AddBasicDicAndChild)"> <member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.GetEmailConfigInfo(Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary> <summary>
添加字典 的同时 一起添加子项 --New 获取系统邮件配置信息
</summary> </summary>
<param name="addBasicDicAndChild"></param> <param name="options"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDicList(IRaCIS.Application.Contracts.BasicDicQuery)"> <member name="M:IRaCIS.Core.Application.Service.Common.DeployConfigService.UpdateSystemEmailConfig(IRaCIS.Core.Domain.Share.SystemEmailSendConfig)">
<summary> <summary>
New 查询条件 更新系统邮件配置
</summary> </summary>
<param name="inQuery"></param> <param name="emailConfig"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddOrUpdateBasicDic(IRaCIS.Application.Contracts.AddOrEditBasicDic)">
<summary>
添加和编辑
</summary>
<param name="addOrEditBasic"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetChildList(IRaCIS.Application.Contracts.ChildInQuery)">
<summary>
获取子项数组
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.DeleteDictionary(System.Guid)">
<summary> 删除字典数据 </summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataSelect(System.String[])">
<summary>
传递父亲 code 字符串 数组 返回多个下拉框数据
</summary>
<param name="searchArray"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataSelect(System.String)">
<summary>
根据父亲Code 获取单个下拉框数据
</summary>
<param name="searchKey"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicConfigSelect(System.String)">
<summary>
根据父亲字典分组 获取子项
</summary>
<param name="searchKey"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetCriterionDictionaryList(IRaCIS.Application.Contracts.GetCriterionDictionaryListInDto)">
<summary>
获取标准字典
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetTrialCriterionDictionaryList(IRaCIS.Application.Contracts.GetTrialCriterionDictionaryListInDto)">
<summary>
获取标准字典
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetCriterionDictionary(IRaCIS.Application.Contracts.GetCriterionDictionaryInDto)">
<summary>
获取标准指定字典
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataAllSelect(IRaCIS.Application.Contracts.GetBasicDataAllSelectInDto)">
<summary>
获取所有下拉框 枚举 bool 数据
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBoolValueState(System.Boolean)">
<summary>
获取是和否
</summary>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetAuditState``1(System.Guid,``0)">
<summary>
获取审核状态
</summary>
<typeparam name="T"></typeparam>
<param name="trial"></param>
<param name="childCode"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Common.TU_TR_RSBaseModel.ResearchProgramNo"> <member name="P:IRaCIS.Core.Application.Service.Common.TU_TR_RSBaseModel.ResearchProgramNo">
@@ -1441,6 +1346,129 @@
RSTEST 疗效评估全称 RSTEST 疗效评估全称
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.Service.DictionaryService">
<summary>
数据字典-基础数据维护
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DoctorDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Doctor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemCriterionDictionaryCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialCriterionDictionaryCode},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
数据字典-基础数据维护
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddBoolDic(IRaCIS.Application.Contracts.AddOrEditBasicDic)">
<summary>
添加bool
</summary>
<param name="addOrEditBasic"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetAllDictionaryKey">
<summary>
获取所有字典的Key
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddBasicDicAndChild(IRaCIS.Application.Contracts.AddBasicDicAndChild)">
<summary>
添加字典 的同时 一起添加子项 --New
</summary>
<param name="addBasicDicAndChild"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDicList(IRaCIS.Application.Contracts.BasicDicQuery)">
<summary>
New 查询条件
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.AddOrUpdateBasicDic(IRaCIS.Application.Contracts.AddOrEditBasicDic)">
<summary>
添加和编辑
</summary>
<param name="addOrEditBasic"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetChildList(IRaCIS.Application.Contracts.ChildInQuery)">
<summary>
获取子项数组
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.DeleteDictionary(System.Guid)">
<summary> 删除字典数据 </summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataSelect(System.String[])">
<summary>
传递父亲 code 字符串 数组 返回多个下拉框数据
</summary>
<param name="searchArray"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataSelect(System.String)">
<summary>
根据父亲Code 获取单个下拉框数据
</summary>
<param name="searchKey"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicConfigSelect(System.String)">
<summary>
根据父亲字典分组 获取子项
</summary>
<param name="searchKey"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetCriterionDictionaryList(IRaCIS.Application.Contracts.GetCriterionDictionaryListInDto)">
<summary>
获取标准字典
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetTrialCriterionDictionaryList(IRaCIS.Application.Contracts.GetTrialCriterionDictionaryListInDto)">
<summary>
获取标准字典
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetCriterionDictionary(IRaCIS.Application.Contracts.GetCriterionDictionaryInDto)">
<summary>
获取标准指定字典
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBasicDataAllSelect(IRaCIS.Application.Contracts.GetBasicDataAllSelectInDto)">
<summary>
获取所有下拉框 枚举 bool 数据
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.ChangeTrialObjectNameList(System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{IRaCIS.Application.Contracts.BasicDicSelect}},System.Nullable{System.Guid})">
<summary>
替换字典中的项目名称为试验对象名称 --New
</summary>
<param name="data"></param>
<param name="trialId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetBoolValueState(System.Boolean)">
<summary>
获取是和否
</summary>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DictionaryService.GetAuditState``1(System.Guid,``0)">
<summary>
获取审核状态
</summary>
<typeparam name="T"></typeparam>
<param name="trial"></param>
<param name="childCode"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.EmailLogService"> <member name="T:IRaCIS.Core.Application.Service.EmailLogService">
<summary> <summary>
邮件日志 邮件日志
@@ -1556,6 +1584,13 @@
<param name="_attachmentrepository"></param> <param name="_attachmentrepository"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.FileUploadRecordService.AddOrUpdateCommonUploadRecord(IRaCIS.Core.Application.ViewModel.CommonUploadRecordAddOrEdit)">
<summary>
上传通用文件记录
</summary>
<param name="addOrEditCommonUploadRecord"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.FileUploadRecordService.GetSubjectUploadRecordList(IRaCIS.Core.Application.ViewModel.SubjectFileUploadRecordQuery)"> <member name="M:IRaCIS.Core.Application.Service.FileUploadRecordService.GetSubjectUploadRecordList(IRaCIS.Core.Application.ViewModel.SubjectFileUploadRecordQuery)">
<summary> <summary>
按照 subject visit studyCode 三个维度进行分组的查询列表 (subject相关) 按照 subject visit studyCode 三个维度进行分组的查询列表 (subject相关)
@@ -1696,6 +1731,17 @@
<param name="inCommand"></param> <param name="inCommand"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.MailVerificationService.GetEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Share.EmailBusinessScenario,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}},System.Nullable{IRaCIS.Core.Domain.Models.UserWorkLanguage})">
<summary>
获取邮件主题和html 通用封装 以用户语言为主,没有的就用当前的请求语言_userInfo.IsEn_Us
</summary>
<param name="scenario"></param>
<param name="messageToSend"></param>
<param name="emailFunc"></param>
<param name="userWorkLanguage"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Service.MailVerificationService.SendEmailVerification(System.String,System.Int32)"> <member name="M:IRaCIS.Core.Application.Service.MailVerificationService.SendEmailVerification(System.String,System.Int32)">
<summary> <summary>
Reviewer简历录入 发送验证码 Reviewer简历录入 发送验证码
@@ -1721,18 +1767,20 @@
<param name="_trialRepository"></param> <param name="_trialRepository"></param>
<param name="_oSSService"></param> <param name="_oSSService"></param>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Helper.IOSSService,Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})"> <member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Application.Helper.IOSSService,Microsoft.AspNetCore.Hosting.IWebHostEnvironment,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})">
<summary> <summary>
项目影像后台下载,不打包 项目影像后台下载,不打包
</summary> </summary>
<param name="_trialRepository"></param> <param name="_trialRepository"></param>
<param name="_oSSService"></param> <param name="_oSSService"></param>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadTrialImage(System.Guid)"> <member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadTrialImage(System.Guid,System.Int32,System.Int32)">
<summary> <summary>
后端api swagger 下载项目影像 后端api swagger 下载项目影像
</summary> </summary>
<param name="trialId"></param> <param name="trialId"></param>
<param name="startIndex"></param>
<param name="endIndex"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadAndUploadTrialData(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries})"> <member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadAndUploadTrialData(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries})">
@@ -2329,7 +2377,7 @@
<param name="sendFileRelativePath"></param> <param name="sendFileRelativePath"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TrialEmailNoticeConfigService.DealEnrollAnswer(System.Guid,System.Guid,IRaCIS.Core.Domain.Share.CriterionType,System.Guid)"> <member name="M:IRaCIS.Core.Application.Service.TrialEmailNoticeConfigService.DealEnrollAnswer(System.Guid,System.Guid,IRaCIS.Core.Domain.Share.CriterionType,System.Guid,IRaCIS.Core.Domain.Models.UserWorkLanguage)">
<summary> <summary>
获取入组结果 获取入组结果
</summary> </summary>
@@ -2337,9 +2385,10 @@
<param name="subjectVisitId"></param> <param name="subjectVisitId"></param>
<param name="criterionType"></param> <param name="criterionType"></param>
<param name="trialReadingCriterionId"></param> <param name="trialReadingCriterionId"></param>
<param name="userWorkLanguage"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TrialEmailNoticeConfigService.TranslatePdStateAsync(System.Guid,IRaCIS.Core.Domain.Share.ReadingCategory,IRaCIS.Core.Domain.Share.CriterionType,System.Nullable{System.Boolean})"> <member name="M:IRaCIS.Core.Application.Service.TrialEmailNoticeConfigService.TranslatePdStateAsync(System.Guid,IRaCIS.Core.Domain.Share.ReadingCategory,IRaCIS.Core.Domain.Share.CriterionType,IRaCIS.Core.Domain.Models.UserWorkLanguage,System.Nullable{System.Boolean})">
<summary> <summary>
获取PD 结果 获取PD 结果
</summary> </summary>
@@ -2347,6 +2396,7 @@
<param name="readingCategory"> 任务类型</param> <param name="readingCategory"> 任务类型</param>
<param name="criterionType">标准类型</param> <param name="criterionType">标准类型</param>
<param name="IsGlobalGenerate"> 是否是全局产生(区分裁判任务)</param> <param name="IsGlobalGenerate"> 是否是全局产生(区分裁判任务)</param>
<param name="userWorkLanguage"></param>
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
@@ -2890,7 +2940,7 @@
<param name="modality"></param> <param name="modality"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.DownloadImageSuccess(System.Guid)"> <member name="M:IRaCIS.Core.Application.Service.ImageAndDoc.DownloadAndUploadService.DownloadImageSuccess(System.Guid,System.Nullable{System.Guid})">
<summary> <summary>
影像下载成功回调 影像下载成功回调
</summary> </summary>
@@ -3038,7 +3088,7 @@
SystemAnonymizationService SystemAnonymizationService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.SystemAnonymizationService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemAnonymization},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)"> <member name="M:IRaCIS.Core.Application.Service.SystemAnonymizationService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemAnonymization},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)">
<summary> <summary>
SystemAnonymizationService SystemAnonymizationService
</summary> </summary>
@@ -3234,6 +3284,20 @@
批次Id 批次Id
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.getInspectionById(IRaCIS.Core.Application.Service.Inspection.DTO.InspectionDto)">
<summary>
根据Id获取稽查记录
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetJsonDetail(IRaCIS.Core.Application.Service.Inspection.DTO.InspectionDto)">
<summary>
设置稽查记录JsonDetail
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetTrialShowInspection(IRaCIS.Core.Application.Service.Inspection.DTO.SetTrialShowInspection)"> <member name="M:IRaCIS.Core.Application.Service.Inspection.InspectionService.SetTrialShowInspection(IRaCIS.Core.Application.Service.Inspection.DTO.SetTrialShowInspection)">
<summary> <summary>
设置项目稽查配置 设置项目稽查配置
@@ -3670,29 +3734,6 @@
<param name="code"></param> <param name="code"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:IRaCIS.Core.Application.Service.MinimalApiService.FileToPDFService">
<summary>
上传文件转PDF 或者给url 这边下载然后转PDF
</summary>
<param name="_hostEnvironment"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.MinimalApiService.FileToPDFService.#ctor(Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
上传文件转PDF 或者给url 这边下载然后转PDF
</summary>
<param name="_hostEnvironment"></param>
</member>
<!-- Badly formed XML comment ignored for member "T:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService" -->
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService.#ctor(IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Infra.EFCore.TestLength})" -->
<member name="M:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService.TestEfcoreJson">
<summary>
测试efcore json 列支持情况
https://devblogs.microsoft.com/dotnet/array-mapping-in-ef-core-8/
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.HIRActivateService.GetAuthorizationCodeInfo(System.String,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Application.Contracts.SystemHospitalOption})"> <member name="M:IRaCIS.Core.Application.Service.HIRActivateService.GetAuthorizationCodeInfo(System.String,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Application.Contracts.SystemHospitalOption})">
<summary> <summary>
获取授权码明文信息 获取授权码明文信息
@@ -3855,6 +3896,15 @@
The ID token, which can be used to verify the identity of the user. The ID token, which can be used to verify the identity of the user.
</summary> </summary>
</member> </member>
<!-- Badly formed XML comment ignored for member "T:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService" -->
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService.#ctor(IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Infra.EFCore.TestLength})" -->
<member name="M:IRaCIS.Core.Application.Service.MinimalApiService.TestMinimalApiService.TestEfcoreJson">
<summary>
测试efcore json 列支持情况
https://devblogs.microsoft.com/dotnet/array-mapping-in-ef-core-8/
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.QCCommon.VerifyIsCRCSubmmitAsync(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Domain.Share.IUserInfo,System.Nullable{System.Guid})"> <member name="M:IRaCIS.Core.Application.Service.QCCommon.VerifyIsCRCSubmmitAsync(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Domain.Share.IUserInfo,System.Nullable{System.Guid})">
<summary> <summary>
验证CRC 是否已提交 已提交 就不允许进行任何操作,如果是IQC 那么还验证是否是当前任务领取人 验证CRC 是否已提交 已提交 就不允许进行任何操作,如果是IQC 那么还验证是否是当前任务领取人
@@ -6009,7 +6059,7 @@
<param name="inDto"></param> <param name="inDto"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRIPDFFAdvanceCalculateService.CalculateAvg(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)"> <member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRIPDFFAdvanceCalculateService.GetReportVerify(IRaCIS.Core.Application.Service.Reading.Dto.GetReportVerifyInDto)">
<summary> <summary>
计算平均值 计算平均值
</summary> </summary>
@@ -8977,6 +9027,11 @@
外弹力膜面积- 管腔面积 外弹力膜面积- 管腔面积
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.IVUSMeasuredValue.PlaqueRupture">
<summary>
斑块破裂
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.FrameNumber"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.FrameNumber">
<summary> <summary>
帧数 帧数
@@ -9027,6 +9082,16 @@
脂质角度 脂质角度
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.PlaqueRupture">
<summary>
斑块破裂
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTFCTUploadData.PlaqueHealing">
<summary>
斑块愈合
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTInfo.PlaqueNum"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.OCTInfo.PlaqueNum">
<summary> <summary>
斑块编号 斑块编号
@@ -9707,6 +9772,16 @@
融合的病灶 融合的病灶
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetMarkListInDto.VisitTaskId">
<summary>
任务Id
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.NoneDicomMarkInfo.MarkId">
<summary>
标记的唯一标识符
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTagInDto.VisitTaskId"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTagInDto.VisitTaskId">
<summary> <summary>
任务Id 任务Id
@@ -9717,6 +9792,36 @@
单位 单位
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartDataOutDto.ValueType">
<summary>
数值类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartDataOutDto.CustomUnit">
<summary>
自定义单位
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetReportsChartDataOutDto.Type">
<summary>
类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ChartItem.ValueType">
<summary>
数值类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ChartItem.CustomUnit">
<summary>
自定义单位
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ChartItem.Type">
<summary>
类型
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Service.Reading.Dto.SaveTableQuestionMarkInDto"> <member name="T:IRaCIS.Core.Application.Service.Reading.Dto.SaveTableQuestionMarkInDto">
<summary> <summary>
保存表格问题标记 保存表格问题标记
@@ -10127,6 +10232,11 @@
问题分类 问题分类
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetFilterTableQuestionInDto.QuestionClassify">
<summary>
问题分类
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SetOncologyQuestion.EvaluationResult"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.SetOncologyQuestion.EvaluationResult">
<summary> <summary>
评估结果 评估结果
@@ -12308,6 +12418,11 @@
影像工具 影像工具
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingQuestionTrialView.AddDeleteTypeEnum">
<summary>
新增修改类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingQuestionTrialView.ImageToolAttribute"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingQuestionTrialView.ImageToolAttribute">
<summary> <summary>
影像工具属性 影像工具属性
@@ -13253,6 +13368,11 @@
影像工具 影像工具
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionTrialInDto.AddDeleteTypeEnum">
<summary>
新增修改类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionTrialInDto.ImageToolAttribute"> <member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionTrialInDto.ImageToolAttribute">
<summary> <summary>
影像工具属性 影像工具属性
@@ -14663,7 +14783,7 @@
<param name="inDto"></param> <param name="inDto"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMarkBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserFeedBack},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganTrialInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoWithoutPETCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CriterionKeyFileRead},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialCriterionKeyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMarkBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserFeedBack},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganTrialInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoWithoutPETCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CriterionKeyFileRead},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialCriterionKeyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},Microsoft.Extensions.Configuration.IConfiguration,IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)">
<summary> <summary>
IR影像阅片 IR影像阅片
</summary> </summary>
@@ -14755,6 +14875,20 @@
<param name="inQuery"></param> <param name="inQuery"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetMarkList(IRaCIS.Core.Application.Service.Reading.Dto.GetMarkListInDto)">
<summary>
获取标记信息
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetNoneDicomMarkList(IRaCIS.Core.Application.Service.Reading.Dto.GetMarkListInDto)">
<summary>
获取非DICOM标记信息
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetManualList(IRaCIS.Core.Application.Service.Reading.Dto.GetManualListInDto)"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetManualList(IRaCIS.Core.Application.Service.Reading.Dto.GetManualListInDto)">
<summary> <summary>
获取手册 获取手册
@@ -14886,6 +15020,13 @@
<param name="inDto"></param> <param name="inDto"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetFilterTableQuestion(IRaCIS.Core.Application.Service.Reading.Dto.GetFilterTableQuestionInDto)">
<summary>
获取单个表格问题及答案 过滤问题
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetCustomTableQuestionAnswer(IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTableQuestionAnswerInDto)"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetCustomTableQuestionAnswer(IRaCIS.Core.Application.Service.Reading.Dto.GetCustomTableQuestionAnswerInDto)">
<summary> <summary>
获取自定义问题以及答案 获取自定义问题以及答案
@@ -15105,7 +15246,21 @@
<param name="visitTaskId"></param> <param name="visitTaskId"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.ComputeJudgeResult(System.Collections.Generic.List{IRaCIS.Core.Application.Service.Reading.Dto.GroupTaskAnswerDto})"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.SendWeComNotifier(System.Guid,System.String)">
<summary>
发送微信通知
</summary>
<param name="visiTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.SendAbnormalEmail(System.Guid,IRaCIS.Core.Domain.Share.EmailBusinessScenario)">
<summary>
发送邮件通知
</summary>
<param name="visiTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.ComputeJudgeResult(System.Collections.Generic.List{IRaCIS.Core.Application.Service.Reading.Dto.GroupTaskAnswerDto},System.Guid)">
<summary> <summary>
计算返回的结果 为True表示不相等 计算返回的结果 为True表示不相等
</summary> </summary>
@@ -15913,7 +16068,7 @@
<param name="inQuery"></param> <param name="inQuery"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance})"> <member name="M:IRaCIS.Core.Application.Service.PatientService.SubmitVisitStudyBinding(IRaCIS.Application.Contracts.SubmitVisitStudyBindingCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.FileUploadRecord})">
<summary> <summary>
提交 患者检查和访视的绑定 提交 患者检查和访视的绑定
</summary> </summary>
@@ -15990,6 +16145,12 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.DoctorWorkloadService.GetDoctorUserTrialReadingStat(IRaCIS.Application.Contracts.TrialReadingStatQuery)">
<summary>
获取项目阅片统计
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.DoctorWorkloadService.GetTrialEnrollmentWorkloadStats(IRaCIS.Application.Contracts.WorkLoadDoctorQueryDTO)"> <member name="M:IRaCIS.Core.Application.Service.DoctorWorkloadService.GetTrialEnrollmentWorkloadStats(IRaCIS.Application.Contracts.WorkLoadDoctorQueryDTO)">
<summary> <summary>
获取某个项目入组的医生工作量统计列表 获取某个项目入组的医生工作量统计列表
@@ -16071,6 +16232,18 @@
<param name="outEnrollTime"></param> <param name="outEnrollTime"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.TestService.SiteSuveryEquipment">
<summary>
维护中心调研设备默认配置
</summary>
<param name="modelVerify"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.TestService.SubjectVisitExcel">
<summary>
访视数据模型
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.MaskImage"> <member name="M:IRaCIS.Core.Application.Service.TestService.MaskImage">
<summary> <summary>
遮挡影像 遮挡影像
@@ -16163,7 +16336,7 @@
<param name="logger">logger</param> <param name="logger">logger</param>
<param name="accessor">loggerHelper</param> <param name="accessor">loggerHelper</param>
</member> </member>
<member name="M:IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api.RequestDuplicationFilter.#ctor(Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api.RequestDuplicationFilter},Microsoft.AspNetCore.Http.IHttpContextAccessor,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.RequestDuplicationOptions})"> <member name="M:IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api.RequestDuplicationFilter.#ctor(Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api.RequestDuplicationFilter},Microsoft.AspNetCore.Http.IHttpContextAccessor,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.RequestDuplicationOptions},Microsoft.Extensions.Configuration.IConfiguration)">
<summary> <summary>
请求拦截 请求前后的操作 请求拦截 请求前后的操作
</summary> </summary>
@@ -16236,6 +16409,16 @@
<param name="email"></param> <param name="email"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Helper.SendEmailHelper.SendTrialEmailAsync(MimeKit.MimeMessage,IRaCIS.Core.Domain.Models.Trial,System.EventHandler{MailKit.MessageSentEventArgs})">
<summary>
发送项目邮件
</summary>
<param name="messageToSend"></param>
<param name="trial"></param>
<param name="messageSentSuccess"></param>
<returns></returns>
<exception cref="T:System.Exception"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Helper.FileConvertHelper.ConvertWordToPdf(System.String,System.String)"> <member name="M:IRaCIS.Core.Application.Helper.FileConvertHelper.ConvertWordToPdf(System.String,System.String)">
<summary> <summary>
镜像里面打入libreoffice 的方案 镜像里面打入libreoffice 的方案
@@ -16425,23 +16608,25 @@
全量一致性核查 全量一致性核查
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.EmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}})"> <member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.EmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}},System.Nullable{IRaCIS.Core.Domain.Models.UserWorkLanguage})">
<summary> <summary>
系统默认邮件 + 项目默认邮件 (不用添加到项目邮件配置中,才发送) 系统默认邮件 + 项目默认邮件 (不用添加到项目邮件配置中,才发送)
</summary> </summary>
<param name="configInfo"></param> <param name="configInfo"></param>
<param name="messageToSend"></param> <param name="messageToSend"></param>
<param name="emailFunc"></param> <param name="emailFunc"></param>
<param name="userWorkLanguage"></param>
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}})"> <member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}},System.Nullable{IRaCIS.Core.Domain.Models.UserWorkLanguage})">
<summary> <summary>
项目手动邮件 (需要添加到项目邮件配置中,才发送) 项目手动邮件 (需要添加到项目邮件配置中,才发送)
</summary> </summary>
<param name="configInfo"></param> <param name="configInfo"></param>
<param name="messageToSend"></param> <param name="messageToSend"></param>
<param name="emailFunc"></param> <param name="emailFunc"></param>
<param name="userWorkLanguage"></param>
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
@@ -16812,12 +16997,12 @@
定时过期提醒 定时过期提醒
</summary> </summary>
</member> </member>
<member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer"> <member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer.SystemDocumentPublishEventConsumer">
<summary> <summary>
生效通知 生效通知
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})"> <member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer.SystemDocumentPublishEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary> <summary>
生效通知 生效通知
</summary> </summary>
@@ -18212,6 +18397,16 @@
文件大小,单位字节 文件大小,单位字节
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.ViewModel.SegmentationAddOrEdit.SEGUpdateTime">
<summary>
SEGUpdateTime 更新时间
</summary>
</member>
<member name="P:IRaCIS.Core.Application.ViewModel.SegmentationVersionView.StartTime">
<summary>
版本开始时间
</summary>
</member>
<member name="P:IRaCIS.Core.Application.ViewModel.SegmentBindingView.IsLock"> <member name="P:IRaCIS.Core.Application.ViewModel.SegmentBindingView.IsLock">
<summary> <summary>
是否锁定 是否锁定
@@ -18670,11 +18865,24 @@
NoneDicomStudyService NoneDicomStudyService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},Medallion.Threading.IDistributedLockProvider,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Application.Service.QCCommon,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)"> <member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},Medallion.Threading.IDistributedLockProvider,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Application.Service.QCCommon,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary> <summary>
NoneDicomStudyService NoneDicomStudyService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.NoneDicomStudyMaskImage(IRaCIS.Core.Application.Contracts.NoneDicomStudyMaskImageCommand)">
<summary>
标注遮盖影像 路径后面加了.MaskNoneDicom_ 就是遮盖的新路径
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.NoneDicomStudyUndoMaskImage(IRaCIS.Core.Application.Contracts.NoneDicomStudyUndoMaskImageCommand)">
<summary>
撤销遮盖的影像,可以单张,也可以整个检查
</summary>
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.GetNoneDicomStudyFileList(System.Guid)"> <member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.GetNoneDicomStudyFileList(System.Guid)">
<summary> <summary>
非Dicom检查 文件列表 非Dicom检查 文件列表
@@ -18843,6 +19051,11 @@
受试者ID 受试者ID
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Contracts.DTO.TrialVisitQADTO.IsSupportQCDownloadImage">
<summary>
QC质控下载
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.DTO.QAStudyInfoDTO.PatientSex"> <member name="P:IRaCIS.Core.Application.Contracts.DTO.QAStudyInfoDTO.PatientSex">
<summary> <summary>
性别 性别
@@ -19303,7 +19516,17 @@
检查名称列表 检查名称列表
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Contracts.TrialProcessConfig.IsImageQualityControl"> <member name="P:IRaCIS.Core.Application.Contracts.BasicTrialConfig.IsSupportQCDownloadImage">
<summary>
QC质控下载
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.BasicTrialConfig.IsOpenLostVistRead">
<summary>
打开失访可读
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.BasicTrialConfig.IsImageQualityControl">
<summary> <summary>
影像质控风险控制 影像质控风险控制
</summary> </summary>
@@ -19935,7 +20158,7 @@
TrialDocumentService TrialDocumentService
</summary> </summary>
</member> </member>
<member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecord},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocumentAttachment},IRaCIS.Core.Application.Contracts.ISystemDocumentService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)"> <member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},MassTransit.Mediator.IScopedMediator,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecord},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocumentAttachment},IRaCIS.Core.Application.Contracts.ISystemDocumentService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary> <summary>
TrialDocumentService TrialDocumentService
</summary> </summary>
@@ -20123,11 +20346,12 @@
<param name="editTrialSiteCommand"></param> <param name="editTrialSiteCommand"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Services.TrialMaintenanceService.GetTrialSiteSelect(System.Guid)"> <member name="M:IRaCIS.Core.Application.Services.TrialMaintenanceService.GetTrialSiteSelect(System.Guid,System.Nullable{System.Boolean})">
<summary> <summary>
获取项目下的 site 下拉框数据 CRC只看到他负责的 获取项目下的 site 下拉框数据 CRC只看到他负责的
</summary> </summary>
<param name="trialId"></param> <param name="trialId"></param>
<param name="ignoreDisable"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Services.TrialMaintenanceService.DeleteTrialSite(System.Guid)"> <member name="M:IRaCIS.Core.Application.Services.TrialMaintenanceService.DeleteTrialSite(System.Guid)">
@@ -20735,6 +20959,12 @@
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.ReplaceSubject">
<summary>
替换受试者
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.TrialReadingInfoSignVerify(IRaCIS.Core.Application.Contracts.TrialReadingInfoSignInDto)"> <member name="M:IRaCIS.Core.Application.TrialConfigService.TrialReadingInfoSignVerify(IRaCIS.Core.Application.Contracts.TrialReadingInfoSignInDto)">
<summary> <summary>
阅片信息签名验证接口 阅片信息签名验证接口
@@ -20743,6 +20973,33 @@
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.SetTrialLinkExpirationTime(IRaCIS.Core.Application.Contracts.TrialLinkExpirationTimeDto)">
<summary>
设置项目链接过期时间
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.GetTrialLinkExpirationTime(IRaCIS.Core.Application.Contracts.SetTrialLinkExpirationTimeDto)">
<summary>
获取项目链接过期时间
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.GetLinkLinkExpirationTime(IRaCIS.Core.Application.Contracts.VerifyLinkExpirationTimeDto)">
<summary>
获取时间是否过期 过期返回true 没有过期返回false
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.GetLinkVerificationCodeIsEffective(IRaCIS.Core.Application.Contracts.GetLinkVerificationCodeIsEffectiveDto)">
<summary>
获取是否Code是否有效 有效返回true 无效返回false
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.GetTrialConfirmCriterionList(IRaCIS.Core.Application.Contracts.GetTrialConfirmCriterionListInDto)"> <member name="M:IRaCIS.Core.Application.TrialConfigService.GetTrialConfirmCriterionList(IRaCIS.Core.Application.Contracts.GetTrialConfirmCriterionListInDto)">
<summary> <summary>
获取项目已经确认的标准 获取项目已经确认的标准
@@ -21709,11 +21966,6 @@
读片数量分类统计 读片数量分类统计
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Application.Contracts.TrialExtraConfig.IsOpenLostVistRead">
<summary>
打开失访可读
</summary>
</member>
<member name="P:IRaCIS.Application.Contracts.TrialConfigInfo.IsImageQualityControl"> <member name="P:IRaCIS.Application.Contracts.TrialConfigInfo.IsImageQualityControl">
<summary> <summary>
影像质控风险控制 影像质控风险控制
@@ -21968,5 +22220,49 @@
<member name="M:IRaCIS.Application.Interfaces.ITrialEnrollmentService.ConfirmReviewer(System.Guid,System.Guid[],System.Int32)"> <member name="M:IRaCIS.Application.Interfaces.ITrialEnrollmentService.ConfirmReviewer(System.Guid,System.Guid[],System.Int32)">
<summary>入组流程-向CRO提交医生[Submit]</summary> <summary>入组流程-向CRO提交医生[Submit]</summary>
</member> </member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type)">
<summary>
Generates a documentation comment ID for a type.
Example: T:Namespace.Outer+Inner`1 becomes T:Namespace.Outer.Inner`1
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.PropertyInfo)">
<summary>
Generates a documentation comment ID for a property.
Example: P:Namespace.ContainingType.PropertyName or for an indexer P:Namespace.ContainingType.Item(System.Int32)
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type,System.String)">
<summary>
Generates a documentation comment ID for a property given its container type and property name.
Example: P:Namespace.ContainingType.PropertyName
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.MethodInfo)">
<summary>
Generates a documentation comment ID for a method (or constructor).
For example:
M:Namespace.ContainingType.MethodName(ParamType1,ParamType2)~ReturnType
M:Namespace.ContainingType.#ctor(ParamType)
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.GetTypeDocId(System.Type,System.Boolean,System.Boolean)">
<summary>
Generates a documentation ID string for a type.
This method handles nested types (replacing '+' with '.'),
generic types, arrays, pointers, by-ref types, and generic parameters.
The <paramref name="includeGenericArguments"/> flag controls whether
constructed generic type arguments are emitted, while <paramref name="omitGenericArity"/>
controls whether the generic arity marker (e.g. "`1") is appended.
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.NormalizeDocId(System.String)">
<summary>
Normalizes a documentation comment ID to match the compiler-style format.
Strips the return type suffix for ordinary methods but retains it for conversion operators.
</summary>
<param name="docId">The documentation comment ID to normalize.</param>
<returns>The normalized documentation comment ID.</returns>
</member>
</members> </members>
</doc> </doc>
@@ -34,6 +34,8 @@ namespace IRaCIS.Core.Application.MassTransit.Command
public Guid SubjectVisitId { get; set; } public Guid SubjectVisitId { get; set; }
public Guid StudyId { get; set; } public Guid StudyId { get; set; }
public string SiteCounty { get; set; }
} }
public class FullCheckResult: CheckViewModel public class FullCheckResult: CheckViewModel
@@ -62,7 +64,7 @@ namespace IRaCIS.Core.Application.MassTransit.Command
//[Required(ErrorMessage = "受试者筛选号不能为空")] //[Required(ErrorMessage = "受试者筛选号不能为空")]
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)] //[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
[ExcelColumnName("Subject ID")] [ExcelColumnName("Participant ID")]
public string SubjectCode { get; set; } = string.Empty; public string SubjectCode { get; set; } = string.Empty;
//[Required(ErrorMessage = "访视名称不能为空")] //[Required(ErrorMessage = "访视名称不能为空")]
@@ -21,12 +21,14 @@ public static class CommonEmailHelper
/// <param name="configInfo"></param> /// <param name="configInfo"></param>
/// <param name="messageToSend"></param> /// <param name="messageToSend"></param>
/// <param name="emailFunc"></param> /// <param name="emailFunc"></param>
/// <param name="userWorkLanguage"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailNoticeConfig configInfo, MimeMessage messageToSend, public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailNoticeConfig configInfo, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc) Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
{ {
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
bool isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN); var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
@@ -60,13 +62,14 @@ Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr
/// <param name="configInfo"></param> /// <param name="configInfo"></param>
/// <param name="messageToSend"></param> /// <param name="messageToSend"></param>
/// <param name="emailFunc"></param> /// <param name="emailFunc"></param>
/// <param name="userWorkLanguage"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
public static async Task<TrialEmailNoticeConfig> GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(TrialEmailNoticeConfig configInfo, MimeMessage messageToSend, public static async Task<TrialEmailNoticeConfig> GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(TrialEmailNoticeConfig configInfo, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc) Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
{ {
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
bool isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN); var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
@@ -94,12 +97,20 @@ Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr
return configInfo; return configInfo;
} }
public static string ReplacePlatformName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt, UserWorkLanguage? userWorkLanguage = null)
public static string ReplaceCompanyName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt)
{ {
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var platformName = isEn_US ? _systemEmailConfig.PlatformName : _systemEmailConfig.PlatformNameCN;
var str = needDealtxt.Replace("{platformName}", platformName);
return str;
}
public static string ReplaceCompanyName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt, UserWorkLanguage? userWorkLanguage = null)
{
var isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var str = needDealtxt.Replace("{company}", isEn_US ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN) var str = needDealtxt.Replace("{company}", isEn_US ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
.Replace("{company abbreviation}", isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN); .Replace("{company abbreviation}", isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
@@ -10,12 +10,14 @@ using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using MaxMind.GeoIP2.Model;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
@@ -79,6 +81,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
Modality = study.ModalityForEdit, Modality = study.ModalityForEdit,
SubjectCode = subject.Code, SubjectCode = subject.Code,
VisitName = sv.VisitName, VisitName = sv.VisitName,
SiteCounty = sv.TrialSite.Country,
}; };
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda) var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
@@ -93,6 +97,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
Modality = noneDicomStudy.Modality, Modality = noneDicomStudy.Modality,
SubjectCode = subject.Code, SubjectCode = subject.Code,
VisitName = sv.VisitName, VisitName = sv.VisitName,
SiteCounty = sv.TrialSite.Country,
}; };
var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList(); var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();
@@ -120,6 +126,21 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList(); var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
//设置当前中心语言
var isEn_us = dbVisitStudyList.First().SiteCounty == StaticData.SiteCountry.US;
var cultureInfoName = StaticData.CultureInfo.en_US;
if (isEn_us == false)
{
cultureInfoName = StaticData.CultureInfo.zh_CN;
}
CultureInfo.CurrentCulture = new CultureInfo(cultureInfoName);
CultureInfo.CurrentUICulture = new CultureInfo(cultureInfoName);
//找到etc 当前visit site 和subject 一致的检查列表 //找到etc 当前visit site 和subject 一致的检查列表
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList(); var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
@@ -27,5 +27,16 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer.Dto
}
public class SendEmailUserDto
{
public UserTypeEnum UserTypeEnum { get; set; }
public string FullName { get; set; }
public UserWorkLanguage UserWorkLanguage { get; set; }
public string EMail { get; set; }
} }
} }
@@ -273,15 +273,30 @@ public class ImageConsumer(
}; };
// 根据不同场景获取不同角色的用户 先排除CRC和CRA // 根据不同场景获取不同角色的用户 先排除CRC和CRA
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted && !filterUserTypeList.Contains(x.UserRole.UserTypeEnum) ).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted && !filterUserTypeList.Contains(x.UserRole.UserTypeEnum) ).Include(x => x.UserRole).Select(x => x.UserRole)
.Select(x => new SendEmailUserDto()
{
UserTypeEnum = x.UserTypeEnum,
FullName = x.FullName,
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
EMail=x.EMail,
})
.ToListAsync();
// CRC和CRA单独取 // CRC和CRA单独取
var crcAndcraUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole)).ToListAsync(); var crcAndcraUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole))
.Select(x => new SendEmailUserDto()
{
UserTypeEnum = x.UserTypeEnum,
FullName = x.FullName,
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
EMail = x.EMail,
}).ToListAsync();
trialUserList.AddRange(crcAndcraUserList); trialUserList.AddRange(crcAndcraUserList);
// 根据场景确定收件人 // 根据场景确定收件人
List<UserRole> toUserList = new List<UserRole>(); List<SendEmailUserDto> toUserList = new List<SendEmailUserDto>();
List<UserRole> ccUserList = new List<UserRole>(); List<SendEmailUserDto> ccUserList = new List<SendEmailUserDto>();
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync(); var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync();
var userTypeEnumList = emailNoticeUserList.Select(x => x.UserType).ToList(); var userTypeEnumList = emailNoticeUserList.Select(x => x.UserType).ToList();
@@ -334,26 +349,39 @@ public class ImageConsumer(
DictionaryList = dictionaryDtos DictionaryList = dictionaryDtos
}); });
foreach (var userinfo in toUserList)
var userWorkLanguageList = toUserList.Select(x => x.UserWorkLanguage).Distinct().ToList();
foreach (var workLanguage in userWorkLanguageList)
{ {
var userinfoList = toUserList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
// 发件地址 // 发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
foreach (var userinfo in userinfoList)
{
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
// 添加抄送 // 添加抄送
foreach (var ccUser in ccUserList) foreach (var ccUser in ccUserList)
{ {
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail)); messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
} }
var userNames = userinfoList.Select(x => x.FullName).ToList();
// 格式化邮件内容 // 格式化邮件内容
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var subjectCode = inDto.SubjectVisit.Subject.Code; var subjectCode = inDto.SubjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} string.Join(',', userNames), // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
inDto.SubjectVisit.VisitName, // 访视 {3} inDto.SubjectVisit.VisitName, // 访视 {3}
@@ -367,9 +395,9 @@ public class ImageConsumer(
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
@@ -446,11 +474,19 @@ public class ImageConsumer(
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
// 根据不同场景获取不同角色的用户 // 根据不同场景获取不同角色的用户
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole)
.Select(x => new SendEmailUserDto()
{
UserTypeEnum = x.UserTypeEnum,
FullName = x.FullName,
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
EMail = x.EMail,
})
.ToListAsync();
// 根据场景确定收件人 // 根据场景确定收件人
List<UserRole> toUserList = new List<UserRole>(); List<SendEmailUserDto> toUserList = new List<SendEmailUserDto>();
List<UserRole> ccUserList = new List<UserRole>(); List<SendEmailUserDto> ccUserList = new List<SendEmailUserDto>();
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync(); var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync();
@@ -469,12 +505,19 @@ public class ImageConsumer(
return; return;
} }
foreach (var userinfo in toUserList) var userWorkLanguageList = toUserList.Select(x => x.UserWorkLanguage).Distinct().ToList();
foreach (var workLanguage in userWorkLanguageList)
{ {
var userinfoList = toUserList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
// 发件地址 // 发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
foreach (var userinfo in userinfoList)
{
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
// 添加抄送 // 添加抄送
foreach (var ccUser in ccUserList) foreach (var ccUser in ccUserList)
@@ -482,13 +525,15 @@ public class ImageConsumer(
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail)); messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
} }
var userNames = userinfoList.Select(x => x.FullName).ToList();
// 格式化邮件内容 // 格式化邮件内容
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} string.Join(',', userNames), // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
"", // 受试者 {2} - 阅片人筛选不涉及受试者 "", // 受试者 {2} - 阅片人筛选不涉及受试者
"", // 访视 {3} - 阅片人筛选不涉及访视 "", // 访视 {3} - 阅片人筛选不涉及访视
@@ -500,9 +545,9 @@ public class ImageConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
@@ -1,5 +1,6 @@
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Command; using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MassTransit.Consumer.Dto;
using IRaCIS.Core.Domain; using IRaCIS.Core.Domain;
using IRaCIS.Core.Domain.BaseModel; using IRaCIS.Core.Domain.BaseModel;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
@@ -68,7 +69,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId); var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync(); var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync(); var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
@@ -78,7 +79,8 @@ public class UrgentMedicalReviewAddedEventConsumer(
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync(); var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
@@ -86,14 +88,14 @@ public class UrgentMedicalReviewAddedEventConsumer(
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
DictionaryRepository = _dictionaryRepository, DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US, IsEn_US = userIsEn_US,
DictionaryList = new List<DictionaryDto>() DictionaryList = new List<DictionaryDto>()
@@ -110,7 +112,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
var subjectName = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode; var subjectName = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectName, taskInfo.TaskBlindName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectName, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
criterion.CriterionName, // 阅片标准 {2} criterion.CriterionName, // 阅片标准 {2}
@@ -126,9 +128,9 @@ public class UrgentMedicalReviewAddedEventConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
@@ -177,7 +179,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId); var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync(); var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync(); var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
@@ -187,6 +189,8 @@ public class UrgentIRRepliedMedicalReviewConsumer(
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync(); var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
@@ -195,14 +199,14 @@ public class UrgentIRRepliedMedicalReviewConsumer(
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
DictionaryRepository = _dictionaryRepository, DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US, IsEn_US = userIsEn_US,
DictionaryList = new List<DictionaryDto>() DictionaryList = new List<DictionaryDto>()
@@ -219,7 +223,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode; var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
criterion.CriterionName, // 阅片标准 {2} criterion.CriterionName, // 阅片标准 {2}
@@ -234,9 +238,9 @@ public class UrgentIRRepliedMedicalReviewConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
@@ -293,7 +297,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId); var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync(); var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync(); var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
@@ -303,6 +307,9 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync(); var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
@@ -311,14 +318,14 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
DictionaryRepository = _dictionaryRepository, DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US, IsEn_US = userIsEn_US,
DictionaryList = new List<DictionaryDto>() DictionaryList = new List<DictionaryDto>()
@@ -335,7 +342,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode; var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
@@ -352,8 +359,8 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
@@ -399,7 +406,15 @@ public class UrgentIRApplyedReReadingConsumer(
var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync(); var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId && x.TrialUser.IsDeleted==false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId && x.TrialUser.IsDeleted==false).Include(x => x.UserRole).Select(x => x.UserRole)
.Select(x => new SendEmailUserDto()
{
UserTypeEnum = x.UserTypeEnum,
FullName = x.FullName,
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
EMail = x.EMail,
})
.ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList(); var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList();
if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed) if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
@@ -412,23 +427,21 @@ public class UrgentIRApplyedReReadingConsumer(
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync(); var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var userWorkLanguageList = userinfoList.Select(x => x.UserWorkLanguage).Distinct().ToList();
foreach (var workLanguage in userWorkLanguageList)
{
var langUserinfoList = userinfoList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
if (!langUserinfoList.Any()) continue;
var userIsEn_US = workLanguage == UserWorkLanguage.US;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
DictionaryRepository = _dictionaryRepository, DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US, IsEn_US = userIsEn_US,
DictionaryList = new List<DictionaryDto>() DictionaryList = new List<DictionaryDto>()
{ {
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), }, //任务类型 new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), }, //任务类型
@@ -436,13 +449,26 @@ public class UrgentIRApplyedReReadingConsumer(
} }
}); });
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
foreach (var userinfo in langUserinfoList)
{
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var userNames = langUserinfoList.Select(x => x.FullName).ToList();
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode; var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} string.Join(',', userNames), // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
taskInfo.TaskBlindName, // 访视 {3} taskInfo.TaskBlindName, // 访视 {3}
@@ -451,18 +477,14 @@ public class UrgentIRApplyedReReadingConsumer(
criterion.CriterionName, // 阅片标准 {6} criterion.CriterionName, // 阅片标准 {6}
dictionValue[1], // 审批结果 {7} dictionValue[1], // 审批结果 {7}
_systemEmailConfig.SiteUrl // 链接 {8} _systemEmailConfig.SiteUrl // 链接 {8}
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
@@ -1,27 +1,9 @@
using DocumentFormat.OpenXml.Office2013.Excel; using IRaCIS.Core.Application.Helper;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Vml;
using DocumentFormat.OpenXml.Wordprocessing;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Domain; using IRaCIS.Core.Domain;
using IRaCIS.Core.Domain.BaseModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MimeKit; using MimeKit;
using NPOI.SS.Formula.Functions;
using NPOI.Util;
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Consumer; namespace IRaCIS.Core.Application.MassTransit.Consumer;
@@ -57,14 +39,23 @@ public class UserSiteSurveySubmitedEventConsumer(
if (emailConfig != null) if (emailConfig != null)
{ {
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId && t.TrialUser.IsDeleted == false) var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM) .Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum }).ToListAsync(); .Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList(); var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList(); var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
var toUserName = string.Empty; var toUserName = string.Empty;
@@ -72,12 +63,14 @@ public class UserSiteSurveySubmitedEventConsumer(
//有SPM 并且参与 //有SPM 并且参与
if (trialInfo.IsSPMJoinSiteSurvey && sPMOrCPMList.Count > 0) if (trialInfo.IsSPMJoinSiteSurvey && sPMOrCPMList.Count > 0)
{ {
foreach (var user in sPMOrCPMList) var lan_SPMOrCPMList = sPMOrCPMList.Where(t => t.UserWorkLanguage == workLanguage);
foreach (var user in lan_SPMOrCPMList)
{ {
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail)); messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
} }
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName)); toUserName = string.Join('、', lan_SPMOrCPMList.Select(t => t.FullName));
foreach (var user in pmAndAPMList) foreach (var user in pmAndAPMList)
{ {
@@ -87,26 +80,26 @@ public class UserSiteSurveySubmitedEventConsumer(
} }
else else
{ {
foreach (var user in pmAndAPMList) var lan_pmAndAPMList = pmAndAPMList.Where(t => t.UserWorkLanguage == workLanguage);
foreach (var user in lan_pmAndAPMList)
{ {
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail)); messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
} }
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName)); toUserName = string.Join('、', lan_pmAndAPMList.Select(t => t.FullName));
} }
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
toUserName, toUserName,
siteInfo.TrialSiteCode, siteInfo.TrialSiteCode,
siteInfo.TrialSiteAliasName, siteInfo.TrialSiteAliasName,
@@ -121,9 +114,10 @@ public class UserSiteSurveySubmitedEventConsumer(
}; };
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
}
} }
} }
@@ -152,45 +146,54 @@ public class SiteSurveySPMSubmitedEventConsumer(
var trialId = siteSurveyInfo.TrialId; var trialId = siteSurveyInfo.TrialId;
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToList();
var scenario = EmailBusinessScenario.Approval_SubmitSiteSurvey; var scenario = EmailBusinessScenario.Approval_SubmitSiteSurvey;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null) if (emailConfig != null)
{ {
var messageToSend = new MimeMessage();
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false) // 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM) foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList(); {
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList(); var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList(); var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
var messageToSend = new MimeMessage();
var toUserName = string.Empty; var toUserName = string.Empty;
foreach (var item in pmAndAPMList) var lan_pmAndAPMList = pmAndAPMList.Where(t => t.UserWorkLanguage == workLanguage);
foreach (var item in lan_pmAndAPMList)
{ {
messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail)); messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail));
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName)); toUserName = string.Join('、', lan_pmAndAPMList.Select(t => t.FullName));
} }
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
toUserName, toUserName,
siteInfo.TrialSiteCode, //中心编号 siteInfo.TrialSiteCode, //中心编号
siteInfo.TrialSiteAliasName,//中心名称 siteInfo.TrialSiteAliasName,//中心名称
@@ -204,9 +207,13 @@ public class SiteSurveySPMSubmitedEventConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
}
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
} }
@@ -235,16 +242,25 @@ public class SiteSurverRejectedEventConsumer(
var trialSiteSurveyId = context.Message.TrialSiteSurveyId; var trialSiteSurveyId = context.Message.TrialSiteSurveyId;
var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId ,ignoreQueryFilters:true).FirstOrDefault().IfNullThrowException(); var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId, ignoreQueryFilters: true).FirstOrDefault().IfNullThrowException();
var trialId = siteSurveyInfo.TrialId; var trialId = siteSurveyInfo.TrialId;
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var scenario = EmailBusinessScenario.SiteSurveyReject; var scenario = EmailBusinessScenario.SiteSurveyReject;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null) if (emailConfig != null)
{ {
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
@@ -256,27 +272,31 @@ public class SiteSurverRejectedEventConsumer(
//PM 驳回到SPM //PM 驳回到SPM
if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted) if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted)
{ {
//var user = await _userRoleRepository.FirstOrDefaultAsync(t => t.Id == siteSurveyInfo.PreliminaryUserId);
//name = user.FullName;
var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false) var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM) .Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList(); .Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToList();
var lan_SPMOrCPMList = sPMOrCPMList.Where(t => t.UserWorkLanguage == workLanguage);
foreach (var user in sPMOrCPMList) foreach (var user in lan_SPMOrCPMList)
{ {
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail)); messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
} }
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName)); toUserName = string.Join('、', lan_SPMOrCPMList.Select(t => t.FullName));
} }
//SPM 驳回到CRC //SPM 驳回到CRC
else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit) else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
{
//使用中心国家语言 一致才发送
if ((siteInfo.Country == StaticData.SiteCountry.US && isEn_US) || (siteInfo.Country == StaticData.SiteCountry.CN && isEn_US == false))
{ {
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email)); messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
}
} }
} }
@@ -284,25 +304,24 @@ public class SiteSurverRejectedEventConsumer(
{ {
//没有SPM PM驳回到CRC //没有SPM PM驳回到CRC
messageToSend.To.Add(new MailboxAddress(siteSurveyInfo.UserName, siteSurveyInfo.Email)); //使用中心国家语言 一致才发送
if ((siteInfo.Country == StaticData.SiteCountry.US && isEn_US) || (siteInfo.Country == StaticData.SiteCountry.CN && isEn_US == false))
{
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
}
} }
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName,trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
toUserName, toUserName,
trialInfo.TrialCode, trialInfo.TrialCode,
trialInfo.ResearchProgramNo, trialInfo.ResearchProgramNo,
@@ -320,7 +339,11 @@ public class SiteSurverRejectedEventConsumer(
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
}
} }
@@ -36,7 +36,7 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<CRCSubmitedAndQCToAuditEvent> context) public async Task Consume(ConsumeContext<CRCSubmitedAndQCToAuditEvent> context)
{ {
Console.WriteLine("发送(005,006) 【加急项目所有IQC待领取质控任务】邮件!!!"); Log.Logger.Warning("发送(005,006) 【加急项目所有IQC待领取质控任务】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId; var subjectVisitId = context.Message.SubjectVisitId;
@@ -49,17 +49,25 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
if (trialEmailConfig != null) if (trialEmailConfig != null)
{ {
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList(); var iqcList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).Where(t => t.UserWorkLanguage == workLanguage).ToList();
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList(); var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var auditStateCode = "AuditStatePE"; var auditStateCode = "AuditStatePE";
@@ -68,8 +76,6 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
auditStateCode = "AuditStateRC"; auditStateCode = "AuditStateRC";
} }
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
@@ -87,12 +93,12 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
foreach (var userinfo in userinfoList) foreach (var userinfo in iqcList)
{ {
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
} }
var userNames = userinfoList.Select(x => x.FullName).ToList(); var userNames = iqcList.Select(x => x.FullName).ToList();
foreach (var pm in pmandAPm) foreach (var pm in pmandAPm)
{ {
@@ -108,7 +114,7 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
string.Join(',', userNames), // 用户名 {0} string.Join(',', userNames), // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
@@ -120,9 +126,14 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
}
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
} }
} }
@@ -147,7 +158,7 @@ public class CRCRepliedQCChallengeEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<CRCRepliedQCChallengeEvent> context) public async Task Consume(ConsumeContext<CRCRepliedQCChallengeEvent> context)
{ {
Console.WriteLine("发送(Code012013) 【CRC 回复质控质疑 通知QC】邮件!!!"); Log.Logger.Warning("发送(Code012013) 【CRC 回复质控质疑 通知QC】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId; var subjectVisitId = context.Message.SubjectVisitId;
@@ -158,26 +169,29 @@ public class CRCRepliedQCChallengeEventConsumer(
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending; var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (trialEmailConfig != null) if (trialEmailConfig != null)
{ {
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync(); var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList(); var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList(); var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var userinfo = subjectVisit.CurrentActionUser; var userinfo = subjectVisit.CurrentActionUser;
//重新设置当前发送邮件的语言
var workLanguage = _userRoleRepository.Where(t => t.Id == userinfo.Id).Select(t => t.IdentityUser.UserWorkLanguage).First();
isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -207,7 +221,7 @@ public class CRCRepliedQCChallengeEventConsumer(
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
@@ -219,9 +233,9 @@ public class CRCRepliedQCChallengeEventConsumer(
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
@@ -244,7 +258,7 @@ public class QCRepliedQCChallengeEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<QCRepliedQCChallengeEvent> context) public async Task Consume(ConsumeContext<QCRepliedQCChallengeEvent> context)
{ {
Console.WriteLine("发送(014015) 【 QC回复 质控质疑,通知CRC】邮件!!!"); Log.Logger.Warning("发送(014015) 【 QC回复 质控质疑,通知CRC】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId; var subjectVisitId = context.Message.SubjectVisitId;
@@ -277,18 +291,23 @@ public class QCRepliedQCChallengeEventConsumer(
} }
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); .Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Where(t => t.UserWorkLanguage == workLanguage).ToList();
var craInfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).ToList();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
@@ -302,29 +321,31 @@ public class QCRepliedQCChallengeEventConsumer(
}); });
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
if (craInfo != null) var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
foreach (var userinfo in userinfoList)
{ {
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
foreach (var user in craInfoList)
{
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
} }
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} toUserName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3} subjectVisit.VisitName, // 访视 {3}
@@ -337,10 +358,13 @@ public class QCRepliedQCChallengeEventConsumer(
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
} }
} }
} }
} }
@@ -364,7 +388,7 @@ public class CRCRepliedCheckChallengeEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<CRCRepliedCheckChallengeEvent> context) public async Task Consume(ConsumeContext<CRCRepliedCheckChallengeEvent> context)
{ {
Console.WriteLine("发送(019,020) 【 CRC 回复一致性核查质疑 通知PM】邮件!!!"); Log.Logger.Warning("发送(019,020) 【 CRC 回复一致性核查质疑 通知PM】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
@@ -383,13 +407,18 @@ public class CRCRepliedCheckChallengeEventConsumer(
{ {
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
@@ -405,27 +434,31 @@ public class CRCRepliedCheckChallengeEventConsumer(
} }
}); });
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager)
.Where(t => t.UserWorkLanguage == workLanguage).ToList();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
foreach (var userinfo in userinfoList)
{
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} toUserName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3} subjectVisit.VisitName, // 访视 {3}
@@ -437,10 +470,17 @@ public class CRCRepliedCheckChallengeEventConsumer(
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
} }
} }
} }
} }
@@ -466,12 +506,12 @@ public class PMRepliedCheckChallengeEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<PMRepliedCheckChallengeEvent> context) public async Task Consume(ConsumeContext<PMRepliedCheckChallengeEvent> context)
{ {
Console.WriteLine("发送(016017) 【 PM 一致性核查 通知CRC】邮件!!!"); Log.Logger.Warning("发送(016017) 【 PM 一致性核查 通知CRC】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId; var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.NoneDicomStudyList).Include(x => x.StudyList).Include(x => x.Subject).FirstNotNullAsync(); var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.NoneDicomStudyList).Include(x => x.StudyList).Include(x => x.Subject).Include(t => t.TrialSite).FirstNotNullAsync();
var trialId = subjectVisit.TrialId; var trialId = subjectVisit.TrialId;
@@ -486,11 +526,11 @@ public class PMRepliedCheckChallengeEventConsumer(
var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync(); var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault(); var craInfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
@@ -499,6 +539,20 @@ public class PMRepliedCheckChallengeEventConsumer(
modalities = subjectVisit.NoneDicomStudyList.Select(t => t.Modality) modalities = subjectVisit.NoneDicomStudyList.Select(t => t.Modality)
.Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList(); .Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList();
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
//foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = subjectVisit.TrialSite.Country == StaticData.SiteCountry.US;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Where(t => t.UserWorkLanguage == workLanguage).ToList();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
@@ -511,16 +565,20 @@ public class PMRepliedCheckChallengeEventConsumer(
} }
}); });
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
if (craInfo != null) var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
foreach (var userinfo in userinfoList)
{ {
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
foreach (var user in craInfoList)
{
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
} }
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
@@ -531,8 +589,8 @@ public class PMRepliedCheckChallengeEventConsumer(
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} toUserName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
@@ -547,10 +605,11 @@ public class PMRepliedCheckChallengeEventConsumer(
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
} }
@@ -592,15 +651,22 @@ public class CheckStateChangedToAuditEventConsumer(
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
{
//重新设置当前发送邮件的语言
isEn_US = workLanguage == UserWorkLanguage.US;
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager)
.Where(t => t.UserWorkLanguage == workLanguage).ToList();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{ {
@@ -615,26 +681,27 @@ public class CheckStateChangedToAuditEventConsumer(
}); });
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
foreach (var userinfo in userinfoList)
{
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 姓名 {0} toUserName, // 姓名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2} subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3} subjectVisit.VisitName, // 访视 {3}
@@ -646,10 +713,11 @@ public class CheckStateChangedToAuditEventConsumer(
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
} }
@@ -671,7 +739,7 @@ public class QCClaimTaskEventConsumer(
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<QCClaimTaskEvent> context) public async Task Consume(ConsumeContext<QCClaimTaskEvent> context)
{ {
Console.WriteLine("发送(Code007008) 【QC 领取了质控任务】邮件!!!"); Log.Logger.Warning("发送(Code007008) 【QC 领取了质控任务】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
@@ -708,6 +776,10 @@ public class QCClaimTaskEventConsumer(
return; return;
} }
//重新设置当前发送邮件的语言
var workLanguage = _userRoleRepository.Where(t => t.Id == userinfo.Id).Select(t => t.IdentityUser.UserWorkLanguage).First();
isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -745,7 +817,7 @@ public class QCClaimTaskEventConsumer(
var subjectCode = subjectVisit.Subject.Code; var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.FullName, // 用户名 {0} userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1} trialInfo.ExperimentName, // 项目 {1}
string.Join(',', subjectcodes), // 受试者 {2} string.Join(',', subjectcodes), // 受试者 {2}
@@ -759,9 +831,9 @@ public class QCClaimTaskEventConsumer(
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
} }
@@ -1,10 +1,6 @@
using System.Globalization; using IRaCIS.Core.Domain.BaseModel;
using System.Threading;
using System.Threading.Tasks;
using IRaCIS.Core.Domain.BaseModel;
using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using NPOI.SS.Formula.Functions; using System.Globalization;
public class CultureInfoFilter<T> (IRepository<EventStoreRecord> _eventStoreRecordRepository) : IFilter<ConsumeContext<T>> where T : DomainEvent public class CultureInfoFilter<T> (IRepository<EventStoreRecord> _eventStoreRecordRepository) : IFilter<ConsumeContext<T>> where T : DomainEvent
{ {
@@ -74,13 +74,17 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
t.UserRole.IdentityUser.EMail, t.UserRole.IdentityUser.EMail,
t.UserRole.IdentityUser.UserName, t.UserRole.IdentityUser.UserName,
t.Trial.TrialCode, t.Trial.TrialCode,
t.Trial.ResearchProgramNo t.Trial.ResearchProgramNo,
t.UserRole.IdentityUser.UserWorkLanguage
//TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList() //TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList()
}); });
foreach (var trialUser in trialUserList) foreach (var trialUser in trialUserList)
{ {
//重新设置当前发送邮件的语言
var workLanguage = trialUser.UserWorkLanguage;
isEn_US = workLanguage == UserWorkLanguage.US;
var userId = trialUser.UserId; var userId = trialUser.UserId;
@@ -153,7 +157,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent, workLanguage),
trialUser.FullName, trialUser.FullName,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
@@ -167,9 +171,9 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc); await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
//处理标记已通知的任务 //处理标记已通知的任务
@@ -44,12 +44,17 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync(); var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
//找到 该项目的CRC 用户Id //找到 该项目的CRC 用户Id
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync(); var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件 //判断是否任务可以领取 ,可以的话 发送邮件
foreach (var user in userList) foreach (var user in userList)
{ {
//重新设置当前发送邮件的语言
var workLanguage = user.UserWorkLanguage;
isEn_us = workLanguage == UserWorkLanguage.US;
var userId = user.UserId; var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id //过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
var query = _trialRepository.Where(t => t.Id == trialId) var query = _trialRepository.Where(t => t.Id == trialId)
@@ -72,7 +77,7 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
{ {
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN; var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl); user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, isEn_us, userId); return (topicStr, htmlBodyStr, isEn_us, userId);
@@ -116,12 +121,17 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync(); var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync();
//找到 该项目的IQC 用户Id //找到 该项目的IQC 用户Id
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync(); var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件 //判断是否任务可以领取 ,可以的话 发送邮件
foreach (var user in userList) foreach (var user in userList)
{ {
//重新设置当前发送邮件的语言
var workLanguage = user.UserWorkLanguage;
isEn_us = workLanguage == UserWorkLanguage.US;
var userId = user.UserId; var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id //过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
@@ -147,7 +157,7 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
{ {
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN; var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl); user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
@@ -181,7 +191,7 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context) public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context)
{ {
var trialId=context.Message.TrialId; var trialId = context.Message.TrialId;
var isEn_us = context.Message.CultureInfoName == StaticData.CultureInfo.en_US; var isEn_us = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
@@ -192,13 +202,17 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync(); var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
//找到 该项目的IQC 用户Id //找到 该项目的IQC 用户Id
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync(); var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件 //判断是否任务可以领取 ,可以的话 发送邮件
var userIdList = userList.Select(t => t.UserId).ToList(); var userIdList = userList.Select(t => t.UserId).ToList();
foreach (var user in userList) foreach (var user in userList)
{ {
//重新设置当前发送邮件的语言
var workLanguage = user.UserWorkLanguage;
isEn_us = workLanguage == UserWorkLanguage.US;
var userId = user.UserId; var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id //过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
@@ -226,7 +240,7 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN; var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl); user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, false, userId); return (topicStr, htmlBodyStr, false, userId);
@@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer; using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MimeKit; using MimeKit;
@@ -50,11 +51,13 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
var systemDocQuery = var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false) from sysDoc in _systemDocumentRepository.AsQueryable(false)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId))) from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.Status == UserStateEnum.Enable).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
join confirmc in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirmc.ConfirmUserId, confirmc.SystemDocumentId } into cc join confirmc in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirmc.ConfirmUserId, confirmc.SystemDocumentId } into cc
from confirm in cc.DefaultIfEmpty() from confirm in cc.DefaultIfEmpty()
select new UnionDocumentWithConfirmInfoView() select new TriaAndSystemlSignDocView()
{ {
DocLanguageType=sysDoc.DocLanguageType,
UserWorkLanguage=identityUser.UserWorkLanguage,
IsSystemDoc = true, IsSystemDoc = true,
Id = sysDoc.Id, Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime, CreateTime = sysDoc.CreateTime,
@@ -78,64 +81,66 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
}; };
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null) var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null)
.ToListAsync(); .ToListAsync();
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date) datalist = datalist
.Where(x=>x.DocLanguageType == DocLanguageType.CN_US || (int)x.DocLanguageType == (int)x.UserWorkLanguage)
.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
.Where(x => x.IsNeedSendEmial).ToList(); .Where(x => x.IsNeedSendEmial).ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList(); var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync(); var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
Console.WriteLine("发送定时过期提醒:人员数量" + userinfoList.Count); Console.WriteLine("发送定时过期提醒:人员数量" + userinfoList.Count);
int index = 1;
foreach (var userinfo in userinfoList) var scenario = EmailBusinessScenario.GeneralTraining_ExpirationNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig == null)
{
return;
}
var userWorkLanguageList = userinfoList.Select(x => x.UserWorkLanguage).Distinct().ToList();
foreach (var workLanguage in userWorkLanguageList)
{
var langUserInfoList = userinfoList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
if (!langUserInfoList.Any())
{
continue;
}
var userIsEn_US = workLanguage == UserWorkLanguage.US;
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
foreach (var userinfo in langUserInfoList)
{ {
try try
{ {
Console.WriteLine($"{index}发送定时过期提醒,邮箱:{userinfo.EMail},姓名{userinfo.UserName}");
index++;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.UserName, // 用户名 {0} userinfo.FullName,
_systemEmailConfig.SiteUrl _systemEmailConfig.SiteUrl
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
var scenario = EmailBusinessScenario.GeneralTraining_ExpirationNotification; await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
} }
}
catch (Exception) catch (Exception)
{ {
}
}
} }
} }
}
}
/// <summary> /// <summary>
/// 生效通知 /// 生效通知
/// </summary> /// </summary>
@@ -167,7 +172,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
Console.WriteLine($"只发送给新增的角色,角色数量: {context.Message.NewUserTypeIds.Count}"); Console.WriteLine($"只发送给新增的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
} }
// 构建查询 // 构建查询
IQueryable<UnionDocumentWithConfirmInfoView> systemDocQuery; IQueryable<TriaAndSystemlSignDocView> systemDocQuery;
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any()) if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
{ {
@@ -179,8 +184,10 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false) t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
.Any(t => context.Message.NewUserTypeIds.Contains(t.UserTypeId) && .Any(t => context.Message.NewUserTypeIds.Contains(t.UserTypeId) &&
sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId))) sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
select new UnionDocumentWithConfirmInfoView() select new TriaAndSystemlSignDocView()
{ {
DocLanguageType = sysDoc.DocLanguageType,
UserWorkLanguage = identityUser.UserWorkLanguage,
IsSystemDoc = true, IsSystemDoc = true,
Id = sysDoc.Id, Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime, CreateTime = sysDoc.CreateTime,
@@ -206,8 +213,10 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
.Where(t => t.Status == UserStateEnum.Enable && .Where(t => t.Status == UserStateEnum.Enable &&
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false) t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
.Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId))) .Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
select new UnionDocumentWithConfirmInfoView() select new TriaAndSystemlSignDocView()
{ {
DocLanguageType = sysDoc.DocLanguageType,
UserWorkLanguage = identityUser.UserWorkLanguage,
IsSystemDoc = true, IsSystemDoc = true,
Id = sysDoc.Id, Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime, CreateTime = sysDoc.CreateTime,
@@ -225,50 +234,45 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
}; };
} }
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(x => x.IsNeedSendEmial).ToListAsync(); var datalist = await systemDocQuery.IgnoreQueryFilters().Where(x => x.IsNeedSendEmial).ToListAsync();
datalist = datalist.Where(x => x.DocLanguageType == DocLanguageType.CN_US || (int)x.DocLanguageType == (int)x.UserWorkLanguage).ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList(); var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync(); var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
int index = 1;
var scenario = EmailBusinessScenario.GeneralTraining_EffectiveNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig == null)
{
return;
}
foreach (var userinfo in userinfoList) foreach (var userinfo in userinfoList)
{ {
string msg = $"{index}生效通知,邮箱:{userinfo.EMail},姓名{userinfo.UserName},"; string msg = $"{userinfo.UserName}生效通知,";
index++;
try try
{ {
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var workLanguage = userinfo.UserWorkLanguage;
var userIsEn_US = workLanguage == UserWorkLanguage.US;
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.UserName, // 用户名 {0} userinfo.FullName,
_systemEmailConfig.SiteUrl _systemEmailConfig.SiteUrl
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
var scenario = EmailBusinessScenario.GeneralTraining_EffectiveNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
msg += "发送成功"; msg += "发送成功";
}
} }
catch (Exception) catch (Exception)
@@ -283,4 +287,5 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
} }
} }
}
} }
@@ -1,24 +1,16 @@
using DocumentFormat.OpenXml; using DocumentFormat.OpenXml;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer; using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MimeKit; using MimeKit;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using System.Reactive.Joins;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Recurring namespace IRaCIS.Core.Application.MassTransit.Recurring
{ {
@@ -60,7 +52,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
var trialDocQuery = var trialDocQuery =
from trialDoc in _trialDocumentRepository.AsQueryable(true) from trialDoc in _trialDocumentRepository.AsQueryable(true)
join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable) join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
@@ -72,15 +64,18 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
from confirm in cc.DefaultIfEmpty() from confirm in cc.DefaultIfEmpty()
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId)) where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
select new TrialSignDocView() select new TriaAndSystemlSignDocView()
{ {
TrialCode = trialDoc.Trial.TrialCode, TrialCode = trialDoc.Trial.TrialCode,
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo, ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
ExperimentName = trialDoc.Trial.ExperimentName, ExperimentName = trialDoc.Trial.ExperimentName,
CurrentStaffTrainDays = trialDoc.CurrentStaffTrainDays, CurrentStaffTrainDays = trialDoc.CurrentStaffTrainDays,
NewStaffTrainDays = trialDoc.NewStaffTrainDays, NewStaffTrainDays = trialDoc.NewStaffTrainDays,
Id = trialDoc.Id, Id = trialDoc.Id,
TrialId= trialDoc.TrialId, TrialType= trial.TrialType,
IsTestUser= identityUser.IsTestUser,
TrialId = trialDoc.TrialId,
IsSystemDoc = false, IsSystemDoc = false,
CreateTime = trialDoc.CreateTime, CreateTime = trialDoc.CreateTime,
FullFilePath = trialDoc.Path, FullFilePath = trialDoc.Path,
@@ -102,58 +97,80 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
}; };
var datalist = await trialDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null&&t.ConfirmTime==null) var datalist = await trialDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null&&t.ConfirmTime==null)
.ToListAsync(); .ToListAsync();
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
datalist = datalist
.Where(x=>((x.TrialType== TrialType.OfficialTrial|| x.TrialType== TrialType.Training) && !x.IsTestUser) || (x.TrialType==TrialType.NoneOfficial &&x.IsTestUser))
.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
.ToList(); .ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList(); var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync(); var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
Console.WriteLine("发送定时项目过期提醒:人员数量" + userinfoList.Count); Console.WriteLine("发送定时项目过期提醒:人员数量" + userinfoList.Count);
int index = 1;
foreach (var userinfo in userinfoList) var scenario = EmailBusinessScenario.TrialTraining_ExpirationNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig == null)
{
return;
}
var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
var userWithTrialList = (from ut in userTrialIdList
join u in userinfoList on ut.ConfirmUserId equals u.Id
select new { ut.TrialId, User = u }).ToList();
var groupedList = userWithTrialList.GroupBy(x => new { x.TrialId, x.User.UserWorkLanguage }).ToList();
foreach (var groupItem in groupedList)
{
var langUserInfoList = groupItem.Select(x => x.User).Distinct().ToList();
if (!langUserInfoList.Any())
{
continue;
}
Console.WriteLine($"发送定时过期提醒,数量:{langUserInfoList.Count}");
var trialInfo = await _trialRepository.Where(x => x.Id == groupItem.Key.TrialId).FirstOrDefaultAsync();
if (trialInfo == null)
{
continue;
}
var workLanguage = groupItem.Key.UserWorkLanguage;
var userIsEn_US = workLanguage == UserWorkLanguage.US;
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
foreach (var userinfo in langUserInfoList)
{ {
try try
{ {
Console.WriteLine($"{index}发送定时过期提醒,邮箱:{userinfo.EMail},姓名{userinfo.UserName}");
index++;
var trialInfo = _trialRepository.Where(x => x.Id == userinfo.TrialId).FirstOrDefault();
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.UserName, // 用户名 {0} userinfo.FullName,
_systemEmailConfig.SiteUrl _systemEmailConfig.SiteUrl
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
var scenario = EmailBusinessScenario.TrialTraining_ExpirationNotification; await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
}
} }
catch (Exception) catch (Exception)
{ {
} }
}
} }
@@ -193,20 +210,21 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
Console.WriteLine($"只发送给新增项目的角色,角色数量: {context.Message.NewUserTypeIds.Count}"); Console.WriteLine($"只发送给新增项目的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
} }
// 构建查询 // 构建查询
IQueryable<UnionDocumentWithConfirmInfoView> systemDocQuery; IQueryable<TriaAndSystemlSignDocView> trialDocQuery;
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any()) if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
{ {
// 只查询新增角色的用户 // 只查询新增角色的用户
systemDocQuery = trialDocQuery =
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id)) from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
join trialIdentityUser in _trialIdentityUserRepository.Where(x=>x.IsDeleted==false) on trialDoc.TrialId equals trialIdentityUser.TrialId join trialIdentityUser in _trialIdentityUserRepository.Where(x=>x.IsDeleted==false) on trialDoc.TrialId equals trialIdentityUser.TrialId
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable) join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
on trialIdentityUser.IdentityUserId equals identityUser.Id on trialIdentityUser.IdentityUserId equals identityUser.Id
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && context.Message.NewUserTypeIds.Contains(ur.UserRole.UserTypeId) && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId)) where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && context.Message.NewUserTypeIds.Contains(ur.UserRole.UserTypeId) && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
select new UnionDocumentWithConfirmInfoView() select new TriaAndSystemlSignDocView()
{ {
IsSystemDoc = true, IsSystemDoc = true,
Id = trialDoc.Id, Id = trialDoc.Id,
@@ -214,6 +232,8 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
CreateTime = trialDoc.CreateTime, CreateTime = trialDoc.CreateTime,
IsDeleted = trialDoc.IsDeleted, IsDeleted = trialDoc.IsDeleted,
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes, SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
TrialType = trial.TrialType,
IsTestUser = identityUser.IsTestUser,
Name = trialDoc.Name, Name = trialDoc.Name,
Path = trialDoc.Path, Path = trialDoc.Path,
FileTypeId = trialDoc.FileTypeId, FileTypeId = trialDoc.FileTypeId,
@@ -228,8 +248,9 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
else else
{ {
// 查询所有相关角色的用户 // 查询所有相关角色的用户
systemDocQuery = trialDocQuery =
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id)) from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
@@ -239,7 +260,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId)) where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
select new UnionDocumentWithConfirmInfoView() select new TriaAndSystemlSignDocView()
{ {
IsSystemDoc = false, IsSystemDoc = false,
Id = trialDoc.Id, Id = trialDoc.Id,
@@ -248,6 +269,8 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
CreateTime = trialDoc.CreateTime, CreateTime = trialDoc.CreateTime,
IsDeleted = trialDoc.IsDeleted, IsDeleted = trialDoc.IsDeleted,
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes, SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
TrialType = trial.TrialType,
IsTestUser = identityUser.IsTestUser,
Name = trialDoc.Name, Name = trialDoc.Name,
Path = trialDoc.Path, Path = trialDoc.Path,
FileTypeId = trialDoc.FileTypeId, FileTypeId = trialDoc.FileTypeId,
@@ -260,56 +283,60 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
}; };
} }
var datalist = await systemDocQuery.IgnoreQueryFilters().ToListAsync(); var datalist = await trialDocQuery.IgnoreQueryFilters().ToListAsync();
datalist = datalist.Where(x => ((x.TrialType == TrialType.OfficialTrial || x.TrialType == TrialType.Training) && !x.IsTestUser) || (x.TrialType == TrialType.NoneOfficial && x.IsTestUser)).ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList(); var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync(); var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
int index = 1;
foreach (var userinfo in userinfoList) var scenario = EmailBusinessScenario.TrialTraining_EffectiveNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable).FirstOrDefault();
if (emailConfig == null)
{ {
string msg = $"{index}项目生效通知,邮箱:{userinfo.EMail},姓名{userinfo.UserName},"; return;
index++; }
var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
var userWithTrialList = (from ut in userTrialIdList
join u in userinfoList on ut.ConfirmUserId equals u.Id
select new { ut.TrialId, User = u }).ToList();
foreach (var userWithTrial in userWithTrialList)
{
var userinfo = userWithTrial.User;
string msg = $"{userinfo.UserName}项目生效通知,";
try try
{ {
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail)); messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
var workLanguage = userinfo.UserWorkLanguage;
var userIsEn_US = workLanguage == UserWorkLanguage.US;
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format( var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userinfo.UserName, // 用户名 {0} userinfo.FullName,
_systemEmailConfig.SiteUrl _systemEmailConfig.SiteUrl
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
var scenario = EmailBusinessScenario.TrialTraining_EffectiveNotification; var trialInfo = await _trialRepository.Where(x => x.Id == userWithTrial.TrialId).FirstOrDefaultAsync();
if (trialInfo == null)
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{ {
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc); continue;
var trial = datalist.Where(x => x.ConfirmUserId == userinfo.Id).FirstOrDefault();
var trialInfo = await _trialRepository.Where(x=>x.Id==trial.TrialId).FirstNotNullAsync();
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
msg += "发送成功";
} }
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
msg += "发送成功";
} }
catch (Exception) catch (Exception)
@@ -439,6 +439,8 @@ namespace IRaCIS.Core.Application.ViewModel
public string TaskName { get; set; } = String.Empty; public string TaskName { get; set; } = String.Empty;
public string TaskBlindName { get; set; } = String.Empty;
public Guid? DoctorUserId { get; set; } public Guid? DoctorUserId { get; set; }
public ReadingCategory? ReadingCategory { get; set; } public ReadingCategory? ReadingCategory { get; set; }
@@ -124,6 +124,45 @@ namespace IRaCIS.Core.Application.Service
} }
#region
/// <summary>
/// 从 NewId 的后 3 个字节(24 位)生成一个 6 位十六进制字符串
/// </summary>
/// <returns></returns>
public static string GenerateTaskNo()
{
var bytes = NewId.Next().ToByteArray();
uint value =
BitConverter.ToUInt32(bytes, 0)
^ BitConverter.ToUInt32(bytes, 4)
^ BitConverter.ToUInt32(bytes, 8)
^ BitConverter.ToUInt32(bytes, 12);
return (value & 0xFFFFFF).ToString("X6");
}
private async Task<string> GetRandomTaskName(Guid trialId, List<string> existList)
{
var taskName = GenerateTaskNo();
while (existList.Any(t => t == taskName))
{
taskName = GenerateTaskNo();
}
while (await _visitTaskRepository.AnyAsync(t => t.TaskBlindName == taskName && t.TrialId == trialId))
{
taskName = GenerateTaskNo();
}
existList.Add(taskName);
return taskName;
}
#endregion
//基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务) //基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务)
public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List<Guid>? subjectVisitIdList = null) public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List<Guid>? subjectVisitIdList = null)
@@ -151,11 +190,11 @@ namespace IRaCIS.Core.Application.Service
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialStudyMaxCode(trialId)); var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialVisitTaskMaxCode(trialId));
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode; int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
var randomTaskBlindNameList = new List<string>();
foreach (var subjectGroup in needGenerateVisit.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() })) foreach (var subjectGroup in needGenerateVisit.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() }))
{ {
@@ -173,6 +212,8 @@ namespace IRaCIS.Core.Application.Service
var blindTaskName = string.Empty; var blindTaskName = string.Empty;
var isRandom = false;
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder) if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{ {
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0) if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0)
@@ -185,6 +226,12 @@ namespace IRaCIS.Core.Application.Service
} }
} }
else if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.Random)
{
blindTaskName = await GetRandomTaskName(trialId, randomTaskBlindNameList);
isRandom = true;
}
else else
{ {
blindTaskName = "Timepoint"; blindTaskName = "Timepoint";
@@ -258,12 +305,14 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
var blindTaskName2 = isRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : blindTaskName;
task2 = await _visitTaskRepository.AddAsync(new VisitTask() task2 = await _visitTaskRepository.AddAsync(new VisitTask()
{ {
TrialId = trialId, TrialId = trialId,
SubjectId = subjectVisit.SubjectId, SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent, IsUrgent = subjectVisit.IsUrgent,
TaskBlindName = blindTaskName, TaskBlindName = blindTaskName2,
TaskName = subjectVisit.VisitName, TaskName = subjectVisit.VisitName,
TaskUrgentType = taskUrgentType, TaskUrgentType = taskUrgentType,
IsCanEditUrgentState = isCanEditUrgentState, IsCanEditUrgentState = isCanEditUrgentState,
@@ -283,7 +332,7 @@ namespace IRaCIS.Core.Application.Service
} }
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
@@ -344,7 +393,7 @@ namespace IRaCIS.Core.Application.Service
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
@@ -590,11 +639,11 @@ namespace IRaCIS.Core.Application.Service
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialStudyMaxCode(trialId)); var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialVisitTaskMaxCode(trialId));
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode; int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
var randomTaskBlindNameList = new List<string>();
switch (generateTaskCommand.ReadingCategory) switch (generateTaskCommand.ReadingCategory)
@@ -654,7 +703,9 @@ namespace IRaCIS.Core.Application.Service
var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false); var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false);
var blindTaskName = string.Empty; var blindTaskName = string.Empty;
var isFullRandom = false;
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder) if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{ {
@@ -668,6 +719,12 @@ namespace IRaCIS.Core.Application.Service
} }
} }
else if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.Random)
{
blindTaskName = await GetRandomTaskName(trialId, randomTaskBlindNameList);
isFullRandom = true;
}
//受试者随机
else else
{ {
blindTaskName = "Timepoint"; blindTaskName = "Timepoint";
@@ -721,11 +778,15 @@ namespace IRaCIS.Core.Application.Service
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2)) if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
{ {
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
var blindTaskName2 = isFullRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : blindTaskName;
task2 = await _visitTaskRepository.AddAsync(new VisitTask() task2 = await _visitTaskRepository.AddAsync(new VisitTask()
{ {
TrialId = trialId, TrialId = trialId,
SubjectId = subjectVisit.SubjectId, SubjectId = subjectVisit.SubjectId,
TaskBlindName = blindTaskName, TaskBlindName = blindTaskName2,
TaskName = subjectVisit.VisitName, TaskName = subjectVisit.VisitName,
IsUrgent = subjectVisit.IsUrgent, IsUrgent = subjectVisit.IsUrgent,
@@ -747,7 +808,7 @@ namespace IRaCIS.Core.Application.Service
} }
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
#region #region
@@ -873,7 +934,7 @@ namespace IRaCIS.Core.Application.Service
{ {
arm1.TaskAllocationState = TaskAllocationState.Allocated; arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now; arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId; arm1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
} }
@@ -913,14 +974,14 @@ namespace IRaCIS.Core.Application.Service
{ {
taskOne.TaskAllocationState = TaskAllocationState.Allocated; taskOne.TaskAllocationState = TaskAllocationState.Allocated;
taskOne.AllocateTime = DateTime.Now; taskOne.AllocateTime = DateTime.Now;
taskOne.DoctorUserId = task1!.DoctorUserId; taskOne.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
taskOne.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); taskOne.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
} }
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
} }
@@ -944,7 +1005,7 @@ namespace IRaCIS.Core.Application.Service
{ {
arm2.TaskAllocationState = TaskAllocationState.Allocated; arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now; arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId; arm2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
} }
@@ -986,13 +1047,13 @@ namespace IRaCIS.Core.Application.Service
{ {
taskTwo.TaskAllocationState = TaskAllocationState.Allocated; taskTwo.TaskAllocationState = TaskAllocationState.Allocated;
taskTwo.AllocateTime = DateTime.Now; taskTwo.AllocateTime = DateTime.Now;
taskTwo.DoctorUserId = task2!.DoctorUserId; taskTwo.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
} }
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
} }
@@ -1069,7 +1130,7 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
#region #region
@@ -1197,7 +1258,7 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
} }
@@ -1277,6 +1338,7 @@ namespace IRaCIS.Core.Application.Service
var reReadingVisitTask = generateTaskCommand.ReReadingTask; var reReadingVisitTask = generateTaskCommand.ReReadingTask;
Guid? subjectVisitId = Guid.Empty; Guid? subjectVisitId = Guid.Empty;
if (reReadingVisitTask.SourceSubjectVisitId == null) if (reReadingVisitTask.SourceSubjectVisitId == null)
@@ -1317,6 +1379,10 @@ namespace IRaCIS.Core.Application.Service
//&& t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId && t.TaskState == TaskState.Effect //&& t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId && t.TaskState == TaskState.Effect
// && t.SourceSubjectVisitId == reReadingVisitTask.SourceSubjectVisitId && t.ArmEnum == reReadingVisitTask.ArmEnum && t.DoctorUserId == reReadingVisitTask.DoctorUserId).FirstOrDefault(); // && t.SourceSubjectVisitId == reReadingVisitTask.SourceSubjectVisitId && t.ArmEnum == reReadingVisitTask.ArmEnum && t.DoctorUserId == reReadingVisitTask.DoctorUserId).FirstOrDefault();
var isRandomReading = trialReadingCriterionConfigList.FirstOrDefault(t => t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId)?.IsReadingTaskViewInOrder == ReadingOrder.Random;
var taskBlindName = isRandomReading ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : reReadingVisitTask.TaskBlindName;
var newTask = await _visitTaskRepository.AddAsync(new VisitTask() var newTask = await _visitTaskRepository.AddAsync(new VisitTask()
{ {
@@ -1325,7 +1391,7 @@ namespace IRaCIS.Core.Application.Service
SubjectId = reReadingVisitTask.SubjectId, SubjectId = reReadingVisitTask.SubjectId,
ArmEnum = reReadingVisitTask.ArmEnum, ArmEnum = reReadingVisitTask.ArmEnum,
TaskName = reReadingVisitTask.TaskName, TaskName = reReadingVisitTask.TaskName,
TaskBlindName = reReadingVisitTask.TaskBlindName, TaskBlindName = taskBlindName,
IsUrgent = reReadingVisitTask.IsAnalysisCreate ? false : subjectVisitUrgentInfo.IsUrgent, IsUrgent = reReadingVisitTask.IsAnalysisCreate ? false : subjectVisitUrgentInfo.IsUrgent,
TaskUrgentType = reReadingVisitTask.IsAnalysisCreate ? null : taskUrgent, TaskUrgentType = reReadingVisitTask.IsAnalysisCreate ? null : taskUrgent,
@@ -1386,7 +1452,7 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
//} //}
@@ -1491,7 +1557,7 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
break; break;
@@ -1538,7 +1604,7 @@ namespace IRaCIS.Core.Application.Service
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
break; break;
@@ -1548,6 +1614,11 @@ namespace IRaCIS.Core.Application.Service
var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm && x.IsConfirmed && x.TrialReadingCriterionId == firstTask.TrialReadingCriterionId).FirstOrDefaultAsync(); var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm && x.IsConfirmed && x.TrialReadingCriterionId == firstTask.TrialReadingCriterionId).FirstOrDefaultAsync();
var isRandom = trialReadingCriterionConfigList.FirstOrDefault(t => t.TrialReadingCriterionId == firstTask.TrialReadingCriterionId)?.IsReadingTaskViewInOrder == ReadingOrder.Random;
var blindName = isRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : firstTask.TaskBlindName;
VisitTask visitTask = new VisitTask() VisitTask visitTask = new VisitTask()
{ {
ArmEnum = Arm.JudgeArm, ArmEnum = Arm.JudgeArm,
@@ -1564,7 +1635,7 @@ namespace IRaCIS.Core.Application.Service
SouceReadModuleId = firstTask.SouceReadModuleId, SouceReadModuleId = firstTask.SouceReadModuleId,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
TaskState = TaskState.Effect, TaskState = TaskState.Effect,
TaskBlindName = firstTask.TaskBlindName, TaskBlindName = blindName,
DoctorUserId = subjectUser == null ? null : subjectUser.DoctorUserId, DoctorUserId = subjectUser == null ? null : subjectUser.DoctorUserId,
TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated, TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated,
AllocateTime = subjectUser == null ? null : DateTime.Now, AllocateTime = subjectUser == null ? null : DateTime.Now,
@@ -1576,7 +1647,7 @@ namespace IRaCIS.Core.Application.Service
await _visitTaskRepository.AddAsync(visitTask); await _visitTaskRepository.AddAsync(visitTask);
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id), x => new VisitTask() await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id), x => new VisitTask()
{ {
@@ -1637,7 +1708,7 @@ namespace IRaCIS.Core.Application.Service
}); });
currentMaxCodeInt = currentMaxCodeInt + 1; currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
} }
@@ -1707,7 +1778,7 @@ namespace IRaCIS.Core.Application.Service
TrialId = originalTaskInfo.TrialId TrialId = originalTaskInfo.TrialId
}); });
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30)); _fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
} }
break; break;
} }
@@ -54,6 +54,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository, IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository,
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository, IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
//IRepository<ReadingCustomTag> _readingCustomTagRepository, //IRepository<ReadingCustomTag> _readingCustomTagRepository,
IRepository<TaskStudy> _taskStudyRepository,
IRepository<TaskSeries> _taskSeriesRepository,
IRepository<TaskInstance> _taskInstanceRepository,
IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
IRepository<TaskInfluence> _taskInfluenceRepository, IRepository<TaskInfluence> _taskInfluenceRepository,
IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository, IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
ILogger<VisitTaskService> _logger, ILogger<VisitTaskService> _logger,
@@ -91,6 +95,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
{ {
TrialReadingCriterionId = t.Id, TrialReadingCriterionId = t.Id,
IsAutoCreate = t.IsAutoCreate, IsAutoCreate = t.IsAutoCreate,
ReadingTool = t.ReadingTool,
IsAdditionalAssessment = t.IsAdditionalAssessment, IsAdditionalAssessment = t.IsAdditionalAssessment,
TrialReadingCriterionName = t.CriterionName, TrialReadingCriterionName = t.CriterionName,
CriterionType = t.CriterionType, CriterionType = t.CriterionType,
@@ -849,7 +854,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
/// <param name="inQuery"></param> /// <param name="inQuery"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public async Task<PageOutput<ReReadingTaskView>> GetIRReReadingTaskList(VisitTaskQuery inQuery) public async Task<IResponseOutput<PageOutput<ReReadingTaskView>>> GetIRReReadingTaskList(VisitTaskQuery inQuery)
{ {
var visitTaskQueryable = _visitTaskReReadingRepository var visitTaskQueryable = _visitTaskReReadingRepository
@@ -873,6 +878,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false)) .WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskName)) .WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskBlindName), t => t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskBlindName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate)) .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate) .WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1)) .WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
@@ -884,7 +890,11 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray); var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
return pageList; var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
return ResponseOutput.Ok(pageList, criterionInfo);
} }
@@ -1016,9 +1026,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder) if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{ {
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr }).FirstOrDefault(); var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.IsOpenLostVistRead }).FirstOrDefault();
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig(); //var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect && x.Subject.IsSubjectQuit == false) var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect && x.Subject.IsSubjectQuit == false)
@@ -1027,7 +1037,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum)) .WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum))
// 前序 不存在 未一致性核查未通过的 // 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralConfig.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum)) .Where(t => !t.Subject.SubjectVisitList.Where(t => extralObj.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ? //.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true) //t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true) //.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
@@ -1050,14 +1060,14 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(), UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
//未读 里可读任务量 //未读 里可读任务量
UnReadCanReadTaskCount = x.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true) UnReadCanReadTaskCount = x.Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
//不能对包含聚合或子查询的表达式执行聚合函数 //不能对包含聚合或子查询的表达式执行聚合函数
//&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum ) //&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum )
).Count(), ).Count(),
UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned) UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false) .Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
.Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)) .Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.OrderBy(x => x.VisitTaskNum) .OrderBy(x => x.VisitTaskNum)
.Select(u => new IRUnreadTaskView() .Select(u => new IRUnreadTaskView()
@@ -1237,7 +1247,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
/// <param name="inQuery"></param> /// <param name="inQuery"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public async Task<PageOutput<IRHaveReadView>> GetIRHaveReadTaskList(VisitTaskQuery inQuery) public async Task<IResponseOutput<PageOutput<IRHaveReadView>>> GetIRHaveReadTaskList(VisitTaskQuery inQuery)
{ {
@@ -1256,6 +1266,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState) .WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false)) .WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName)) .WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskBlindName), t => t.TaskBlindName.Contains(inQuery.TaskBlindName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate)) .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate) .WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1)) .WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
@@ -1265,7 +1276,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray); var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
return pageList; var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
return ResponseOutput.Ok(pageList, criterionInfo);
} }
@@ -2074,29 +2088,27 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//申请表 设置新任务Id //申请表 设置新任务Id
visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id; visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id;
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{
CopyImages(newTask, influenceTask);
//拷贝原始表单 //拷贝原始表单
if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id) if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id)
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{ {
CopyForms(newTask, origenalTask); CopyForms(newTask, origenalTask);
} }
}
//拷贝后续表单 //拷贝后续表单
if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum) if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{ {
newTask.IsCopyLesionAnswer = true; newTask.IsCopyLesionAnswer = true;
//CopyForms(newTask, origenalTask);
} }
} }
} }
} }
@@ -2185,6 +2197,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//申请表 设置新任务Id //申请表 设置新任务Id
visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id; visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id;
if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id) if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id)
{ {
if (origenalTask.ReadingCategory == ReadingCategory.Visit) if (origenalTask.ReadingCategory == ReadingCategory.Visit)
@@ -2194,16 +2207,16 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
} }
//拷贝后续表单 ////拷贝后续表单
if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum) //if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
{ //{
if (origenalTask.ReadingCategory == ReadingCategory.Visit) // if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{ // {
newTask.IsCopyLesionAnswer = true; // newTask.IsCopyLesionAnswer = true;
//CopyForms(newTask, origenalTask); // //CopyForms(newTask, origenalTask);
} // }
} //}
} }
} }
}); });
@@ -2223,7 +2236,84 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
} }
} }
private async Task CopyForms(VisitTask newTask, VisitTask origenalTask)
private void CopyImages(VisitTask newTask, VisitTask origenalTask)
{
//拷贝后处理绑定的的Dicom影像
var newTaskId = newTask.Id;
var taskStudyList = _taskStudyRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
var taskSeriesList = _taskSeriesRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
var taskInstanceList = _taskInstanceRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var taskStudy in taskStudyList)
{
var newStudyId = IdentifierHelper.CreateGuid(taskStudy.StudyInstanceUid, taskStudy.TrialId.ToString(), newTaskId.ToString());
var newStudy = taskStudy.Clone();
newStudy.Id = newStudyId;
newStudy.SeqId = NewId.NextSequentialGuid();
newStudy.VisitTaskId = newTaskId;
_ = _taskStudyRepository.AddAsync(newStudy).Result;
var studySeriesList = taskSeriesList.Where(t => t.StudyId == taskStudy.Id).ToList();
foreach (var series in studySeriesList)
{
var newSeriesId = IdentifierHelper.CreateGuid(series.StudyInstanceUid, series.SeriesInstanceUid, series.TrialId.ToString(), newTaskId.ToString());
var newSeries = series.Clone();
newSeries.Id = newSeriesId;
newSeries.SeqId = NewId.NextSequentialGuid();
newSeries.StudyId = newStudyId;
newSeries.VisitTaskId = newTaskId;
_ = _taskSeriesRepository.AddAsync(newSeries).Result;
var studyInstanceList = taskInstanceList.Where(t => t.StudyId == taskStudy.Id && t.SeriesId == series.Id).ToList();
foreach (var instance in studyInstanceList)
{
var newInstanceId = IdentifierHelper.CreateGuid(newStudy.StudyInstanceUid, newSeries.SeriesInstanceUid, instance.SopInstanceUid, newStudy.TrialId.ToString(), newTaskId.ToString());
var newInstance = instance.Clone();
newInstance.Id = newInstanceId;
newInstance.SeqId = NewId.NextSequentialGuid();
newInstance.StudyId = newStudyId;
newInstance.SeriesId = newSeriesId;
newInstance.VisitTaskId = newTaskId;
Console.WriteLine($"StudyInstanceUid:{newStudy.StudyInstanceUid} SeriesInstanceUid:{newSeries.SeriesInstanceUid} SopInstanceUid: {instance.SopInstanceUid},newInstanceId:{newInstanceId} ");
_ = _taskInstanceRepository.AddAsync(newInstance).Result;
}
}
}
//拷贝后处理的NoneDicom
var fileList = _noneDicomStudyFileRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var file in fileList)
{
var newFile = file.Clone();
newFile.Id = NewId.NextSequentialGuid();
newFile.VisitTaskId = newTaskId;
_ = _noneDicomStudyFileRepository.AddAsync(newFile).Result;
}
}
private void CopyForms(VisitTask newTask, VisitTask origenalTask)
{ {
newTask.IsCopyLesionAnswer = true; newTask.IsCopyLesionAnswer = true;
//自定义 //自定义
@@ -2242,6 +2332,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList(); var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in readingTaskQuestionAnswerList) foreach (var item in readingTaskQuestionAnswerList)
@@ -2718,7 +2810,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
// 处理阅片期的临床数据 // 处理阅片期的临床数据
var readModuleIdList =await _readModuleRepository.Where(x => x.SubjectVisitId == sv.Id).Select(x => x.Id).ToListAsync(); var readModuleIdList = await _readModuleRepository.Where(x => x.SubjectVisitId == sv.Id).Select(x => x.Id).ToListAsync();
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => readModuleIdList.Contains(t.ReadingId), c => new ReadingClinicalData() await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => readModuleIdList.Contains(t.ReadingId), c => new ReadingClinicalData()
@@ -96,6 +96,8 @@ namespace IRaCIS.Application.Contracts
public Guid? TrialReadingCriterionId { get; set; } public Guid? TrialReadingCriterionId { get; set; }
public Guid? SystemReadingCriterionId { get; set; } public Guid? SystemReadingCriterionId { get; set; }
public Guid? TrialId { get; set; }
} }
@@ -4,7 +4,6 @@
// 生成时间 2026-03-10 06:15:31Z // 生成时间 2026-03-10 06:15:31Z
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using System.Collections.Generic; using System.Collections.Generic;
namespace IRaCIS.Core.Application.ViewModel; namespace IRaCIS.Core.Application.ViewModel;
@@ -96,7 +95,22 @@ public class FileUploadRecordAddOrEdit
public bool? IsSync { get; set; } public bool? IsSync { get; set; }
} }
public class CommonUploadRecordDto: CommonUploadRecordAddOrEdit
{
}
public class CommonUploadRecordAddOrEdit
{
public Guid? Id { get; set; }
public string FileType { get; set; }
public string FileName { get; set; }
public long FileSize { get; set; }
public string Path { get; set; }
}
public class SubjectFileUploadRecordQuery : PageInput public class SubjectFileUploadRecordQuery : PageInput
{ {
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
@@ -0,0 +1,174 @@
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using Medallion.Threading;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Service.Common;
[ApiExplorerSettings(GroupName = "Common")]
public class DeployConfigService(IMapper _mapper, IConfiguration _configuration, IDistributedLockProvider _distributedLockProvider, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService
{
/// <summary>
/// 获取系统基础配置信息
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public async Task<ServiceVerifyConfigOption> GetSystemBasicConfigInfo([FromServices] IOptionsMonitor<ServiceVerifyConfigOption> options)
{
//var config = _configuration.GetSection("BasicSystemConfig").Get<ServiceVerifyConfigOption>();
//return config;
var path = Path.Combine( _hostEnvironment.ContentRootPath,$"appsettings.{_hostEnvironment.EnvironmentName}.json");
var json = File.ReadAllText(path);
var obj = JObject.Parse(json);
return obj["BasicSystemConfig"]!.ToObject<ServiceVerifyConfigOption>()!;
}
/// <summary>
/// 更新系统基础配置
/// </summary>
/// <param name="basicSystemConfigOption"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateSystemBasicConfig(ServiceVerifyConfigOption basicSystemConfigOption)
{
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
using (await @lock.AcquireAsync())
{
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// QCRiskControl 相关配置
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.QCRiskControl)] = basicSystemConfigOption.QCRiskControl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenUserComplexPassword)] = basicSystemConfigOption.OpenUserComplexPassword;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenSignDocumentBeforeWork)] = basicSystemConfigOption.OpenSignDocumentBeforeWork;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenTrialRelationDelete)] = basicSystemConfigOption.OpenTrialRelationDelete;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginLimit)] = basicSystemConfigOption.OpenLoginLimit;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginMaxFailCount)] = basicSystemConfigOption.LoginMaxFailCount;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginFailLockMinutes)] = basicSystemConfigOption.LoginFailLockMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.AutoLoginOutMinutes)] = basicSystemConfigOption.AutoLoginOutMinutes;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginMFA)] = basicSystemConfigOption.OpenLoginMFA;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ContinuousReadingTimeMin)] = basicSystemConfigOption.ContinuousReadingTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ReadingRestTimeMin)] = basicSystemConfigOption.ReadingRestTimeMin;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.IsNeedChangePassWord)] = basicSystemConfigOption.IsNeedChangePassWord;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ChangePassWordDays)] = basicSystemConfigOption.ChangePassWordDays;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.TemplateType)] = ((int)basicSystemConfigOption.TemplateType); // 枚举需要转换为字符串
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ThirdPdfUrl)] = basicSystemConfigOption.ThirdPdfUrl;
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.UserMFAVerifyMinutes)] = basicSystemConfigOption.UserMFAVerifyMinutes;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
}
return ResponseOutput.Ok();
}
/// <summary>
/// 获取系统邮件配置信息
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public async Task<SystemEmailSendConfig> GetEmailConfigInfo([FromServices] IOptionsMonitor<SystemEmailSendConfig> options)
{
//两种方式都有问题
//var config = _configuration.GetSection("BasicSystemConfig").Get<SystemEmailSendConfig>();
//return config;
//return options.CurrentValue;
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
var json = File.ReadAllText(path);
var obj = JObject.Parse(json);
return obj["SystemEmailSendConfig"]!.ToObject<SystemEmailSendConfig>()!;
}
/// <summary>
/// 更新系统邮件配置
/// </summary>
/// <param name="emailConfig"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateSystemEmailConfig(SystemEmailSendConfig emailConfig)
{
var path = Path.Combine(_hostEnvironment.ContentRootPath,$"appsettings.{_hostEnvironment.EnvironmentName}.json");
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
using (await @lock.AcquireAsync())
{
string text = System.IO.File.ReadAllText(path);
// 修改
JObject obj = JObject.Parse(text);
// SystemEmailSendConfig 相关配置
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Port)] = emailConfig.Port;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Host)] = emailConfig.Host;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Imap)] = emailConfig.Imap;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.ImapPort)] = emailConfig.ImapPort;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromEmail)] = emailConfig.FromEmail;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromName)] = emailConfig.FromName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.AuthorizationCode)] = emailConfig.AuthorizationCode;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SiteUrl)] = emailConfig.SiteUrl;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformName)] = emailConfig.PlatformName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformNameCN)] = emailConfig.PlatformNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SystemShortName)] = emailConfig.SystemShortName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationName)] = emailConfig.OrganizationName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationNameCN)] = emailConfig.OrganizationNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyName)] = emailConfig.CompanyName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyNameCN)] = emailConfig.CompanyNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortName)] = emailConfig.CompanyShortName;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortNameCN)] = emailConfig.CompanyShortNameCN;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.IsEnv_US)] = emailConfig.IsEnv_US;
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.EmailRegexStr)] = emailConfig.EmailRegexStr;
// 重新写入appsettings.json
string result = obj.ToString();
System.IO.File.WriteAllText(path, result);
}
return ResponseOutput.Ok();
}
}
@@ -452,14 +452,14 @@ namespace IRaCIS.Core.Application.Service
if (inDto.TrialReadingCriterionId == null && inDto.SystemReadingCriterionId == null) if (inDto.TrialReadingCriterionId == null && inDto.SystemReadingCriterionId == null)
{ {
return result; return await ChangeTrialObjectNameList(result,inDto.TrialId);
} }
else if (inDto.TrialReadingCriterionId != null) else if (inDto.TrialReadingCriterionId != null)
{ {
var trialCriterionType = await _readingQuestionCriterionTrial.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync(); var trialCriterionType = await _readingQuestionCriterionTrial.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
if (trialCriterionType == CriterionType.SelfDefine) if (trialCriterionType == CriterionType.SelfDefine)
{ {
return result; return await ChangeTrialObjectNameList(result, inDto.TrialId);
} }
@@ -505,7 +505,7 @@ namespace IRaCIS.Core.Application.Service
result[item.Key] = item.Value; result[item.Key] = item.Value;
} }
return result; return await ChangeTrialObjectNameList(result, inDto.TrialId);
} }
else else
{ {
@@ -548,12 +548,76 @@ namespace IRaCIS.Core.Application.Service
result[item.Key] = item.Value; result[item.Key] = item.Value;
} }
return result; return await ChangeTrialObjectNameList(result, inDto.TrialId);
} }
} }
/// <summary>
/// 替换字典中的项目名称为试验对象名称 --New
/// </summary>
/// <param name="data"></param>
/// <param name="trialId"></param>
/// <returns></returns>
private async Task<Dictionary<string, List<BasicDicSelect>>> ChangeTrialObjectNameList(Dictionary<string, List<BasicDicSelect>> data,Guid? trialId)
{
if (!trialId.HasValue)
{
return data;
}
// 查询映射集合
var trialObjectNameList = await _trialRepository
.Where(x => x.Id == trialId)
.Select(x => x.TrialObjectNameList)
.FirstOrDefaultAsync();
// 无映射数据直接返回
if (trialObjectNameList == null || !trialObjectNameList.Any())
{
return data;
}
// 构建映射字典,过滤空名称,避免无效替换
var replaceDict = trialObjectNameList
.Where(m => !string.IsNullOrEmpty(m.Name))
.ToDictionary(m => m.Name, m => m.TrialName);
// 遍历替换
foreach (var (_, selectList) in data)
{
foreach (var selectItem in selectList)
{
// 替换Value,判null保护
if (selectItem.Value != null)
{
string tempVal = selectItem.Value;
foreach (var (oldStr, newStr) in replaceDict)
{
tempVal = tempVal.Replace(oldStr, newStr);
}
selectItem.Value = tempVal;
}
// 替换中文名称ValueCN
if (selectItem.ValueCN != null)
{
string tempCn = selectItem.ValueCN;
foreach (var (oldStr, newStr) in replaceDict)
{
tempCn = tempCn.Replace(oldStr, newStr);
}
selectItem.ValueCN = tempCn;
}
}
}
return data;
}
#region #region
/// <summary> /// <summary>
@@ -4,19 +4,13 @@
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using MailKit; using MailKit;
using MailKit.Net.Imap; using MailKit.Net.Imap;
using MailKit.Search; using MailKit.Search;
using MailKit.Security; using MailKit.Security;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace IRaCIS.Core.Application.Contracts namespace IRaCIS.Core.Application.Contracts
@@ -1,27 +1,15 @@
using DocumentFormat.OpenXml.Spreadsheet; using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson; using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infra.EFCore.Migrations;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using NPOI.HPSF;
using NPOI.POIFS.Properties;
using NPOI.SS.Formula.Functions;
using NPOI.XSSF.UserModel;
using System.ComponentModel.Design;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using static IRaCIS.Core.Application.Service.ExcelExportHelper; using static IRaCIS.Core.Application.Service.ExcelExportHelper;
@@ -153,9 +141,9 @@ namespace IRaCIS.Core.Application.Service.Common
var dynamicColumnConfig = new DynamicColumnConfig() var dynamicColumnConfig = new DynamicColumnConfig()
{ {
AutoColumnTitleRowIndex = 2, AutoColumnTitleRowIndex = 3, //2
AutoColumnStartIndex = 7, AutoColumnStartIndex = 8, //7
TempalteLastColumnIndex = 6, TempalteLastColumnIndex = 7, //6
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "Answer", DynamicItemValueName = "Answer",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -167,7 +155,7 @@ namespace IRaCIS.Core.Application.Service.Common
}; };
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(StaticData.Export.TrialQCResult_Export, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(QCQuestionResult_Export), dynamicColumnConfig: dynamicColumnConfig); var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(StaticData.Export.TrialQCResult_Export, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(QCQuestionResult_Export), dynamicColumnConfig: dynamicColumnConfig);
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{ {
@@ -1209,7 +1197,7 @@ namespace IRaCIS.Core.Application.Service.Common
t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.TaskAllocationState == TaskAllocationState.Allocated && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ? t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.TaskAllocationState == TaskAllocationState.Allocated && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ?
ReadingStatusEnum.ReadCompleted : t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? ReadingStatusEnum.ImageReading : ReadingStatusEnum.ReadCompleted : t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? ReadingStatusEnum.ImageReading :
t.ReadingStatus t.ReadingStatus
}).ToList(), }).OrderBy(t=>t.VisitTaskNum).ToList(),
ModuleList = subject.ReadModuleList.Where(t => t.TrialReadingCriterionId == dto.TrialReadingCriterionId).Select(t => new SubjectProgressDto.MouduleProgress() ModuleList = subject.ReadModuleList.Where(t => t.TrialReadingCriterionId == dto.TrialReadingCriterionId).Select(t => new SubjectProgressDto.MouduleProgress()
{ {
@@ -1239,55 +1227,60 @@ namespace IRaCIS.Core.Application.Service.Common
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId); exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(StaticData.Export.TrialSubjectProgressList_Export, exportInfo, /*"", */_commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SubjectProgressDto)); var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(StaticData.Export.TrialSubjectProgressList_Export, exportInfo, /*"", */_commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SubjectProgressDto));
// 使用NPOI 进行二次处理 // 使用 ClosedXML 进行二次处理
using var workbook = new XLWorkbook(memoryStream);
var wb = new XSSFWorkbook(memoryStream); var worksheet = workbook.Worksheet(1); // 获取第一个工作表,索引从1开始
var sheet = wb.GetSheetAt(0);
foreach (var subject in list) foreach (var subject in list)
{ {
var index = list.IndexOf(subject); var index = list.IndexOf(subject);
var row = sheet.GetRow(index + 4);
// ClosedXML 行索引从1开始,原来 NPOI 从0开始,所以 +1
var row = worksheet.Row(index + 4 + 1); // NPOI: index + 4, ClosedXML: +1 = index + 5
foreach (var item in subject.TotalList) foreach (var item in subject.TotalList)
{ {
//从第五列开始动态写 // 从第五列开始动态写ClosedXML 列索引从1开始)
var visitIndex = subject.TotalList.IndexOf(item) + 4; var visitIndex = subject.TotalList.IndexOf(item) + 4 + 1; // NPOI: +4, ClosedXML: +1 = +5
var cell = row.CreateCell(visitIndex); var cell = row.Cell(visitIndex);
if (item.IsLostVisit == true) if (item.IsLostVisit == true)
{ {
cell.CellStyle = sheet.GetRow(1).GetCell(7).CellStyle; //cell.CellStyle = sheet.GetRow(1).GetCell(7).CellStyle;
// 复制样式 - ClosedXML 需要先获取源样式,然后应用到目标单元格
var sourceCell = worksheet.Row(2).Cell(8); // 原 NPOI: GetRow(1).GetCell(7) -> +1 转换
cell.Style = sourceCell.Style;
} }
else else
{ {
switch (item.ReadingStatus) switch (item.ReadingStatus)
{ {
case ReadingStatusEnum.ImageNotSubmit: case ReadingStatusEnum.ImageNotSubmit:
cell.Style = worksheet.Row(2).Cell(2).Style; // NPOI: (1,1) -> ClosedXML: (2,2)
cell.CellStyle = sheet.GetRow(1).GetCell(1).CellStyle;
break; break;
case ReadingStatusEnum.ImageQuality: case ReadingStatusEnum.ImageQuality:
cell.CellStyle = sheet.GetRow(1).GetCell(2).CellStyle; cell.Style = worksheet.Row(2).Cell(3).Style; // (1,2) -> (2,3)
break; break;
case ReadingStatusEnum.ConsistencyCheck: case ReadingStatusEnum.ConsistencyCheck:
cell.CellStyle = sheet.GetRow(1).GetCell(3).CellStyle; cell.Style = worksheet.Row(2).Cell(4).Style; // (1,3) -> (2,4)
break; break;
case ReadingStatusEnum.TaskAllocate: case ReadingStatusEnum.TaskAllocate:
cell.CellStyle = sheet.GetRow(1).GetCell(4).CellStyle; cell.Style = worksheet.Row(2).Cell(5).Style;// (1,4) -> (2,5)
break; break;
case ReadingStatusEnum.ImageReading: case ReadingStatusEnum.ImageReading:
cell.CellStyle = sheet.GetRow(1).GetCell(5).CellStyle; cell.Style = worksheet.Row(2).Cell(6).Style;// (1,5) -> (2,6)
break; break;
case ReadingStatusEnum.ReadCompleted: case ReadingStatusEnum.ReadCompleted:
cell.CellStyle = sheet.GetRow(1).GetCell(6).CellStyle; cell.Style = worksheet.Row(2).Cell(7).Style; // (1,6) -> (2,7)
break; break;
default: default:
@@ -1297,12 +1290,13 @@ namespace IRaCIS.Core.Application.Service.Common
cell.SetCellValue(item.TaskName); cell.SetValue(item.TaskName);
} }
} }
// 保存到 MemoryStream
var memoryStream2 = new MemoryStream(); var memoryStream2 = new MemoryStream();
wb.Write(memoryStream2, true); workbook.SaveAs(memoryStream2);
memoryStream2.Seek(0, SeekOrigin.Begin); memoryStream2.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@@ -2709,9 +2703,10 @@ namespace IRaCIS.Core.Application.Service.Common
var dynamicColumnConfig = new DynamicColumnConfig() var dynamicColumnConfig = new DynamicColumnConfig()
{ {
//可读的列表名行索引,不是{{}} 模板行索引 //可读的列表名行索引,不是{{}} 模板行索引
AutoColumnTitleRowIndex = 2, AutoColumnTitleRowIndex = 3, //2
AutoColumnStartIndex = 5, AutoColumnStartIndex = 6, //5
TempalteLastColumnIndex = 4, TempalteLastColumnIndex = 5, //4
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "QuestionValue", DynamicItemValueName = "QuestionValue",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -2722,7 +2717,7 @@ namespace IRaCIS.Core.Application.Service.Common
}; };
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig); var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig);
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{ {
@@ -2867,7 +2862,8 @@ namespace IRaCIS.Core.Application.Service.Common
if (!criterion.IsArbitrationReading) if (!criterion.IsArbitrationReading)
{ {
//仲裁阅片 才有裁判阅片明细表 同时要把模板里面的三列给去掉 //仲裁阅片 才有裁判阅片明细表 同时要把模板里面的三列给去掉
removeColumnIndexList = new List<int>() { 6, 7, 8 }; //removeColumnIndexList = new List<int>() { 6, 7, 8 };
removeColumnIndexList = new List<int>() { 7, 8 ,9};
} }
//阅片结果表 和阅片结果明细表 没有肿瘤学的时候需要移除肿瘤学三个字段 //阅片结果表 和阅片结果明细表 没有肿瘤学的时候需要移除肿瘤学三个字段
@@ -2876,7 +2872,8 @@ namespace IRaCIS.Core.Application.Service.Common
{ {
if (inQuery.ReadingExportType == ExportResult.TableOfAssessmentResults || inQuery.ReadingExportType == ExportResult.DetailedTableOfAssessmentResults) if (inQuery.ReadingExportType == ExportResult.TableOfAssessmentResults || inQuery.ReadingExportType == ExportResult.DetailedTableOfAssessmentResults)
{ {
removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 9, 10, 11 }).ToList(); //removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 9, 10, 11 }).ToList();
removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 10, 11, 12 }).ToList();
} }
} }
} }
@@ -2933,7 +2930,7 @@ namespace IRaCIS.Core.Application.Service.Common
arbitrationRule = criterion.ArbitrationRule, arbitrationRule = criterion.ArbitrationRule,
trialReadingCriterionId = inQuery.TrialReadingCriterionId, trialReadingCriterionId = inQuery.TrialReadingCriterionId,
isEn_Us = _userInfo.IsEn_Us isEn_Us = _userInfo.IsEn_Us
}).ToListAsync(); }).AsSplitQuery().ToListAsync();
} }
//肿瘤标准 病灶明细表 按照病灶级别 (OCT 暂时不删除,先看是否能覆盖) //肿瘤标准 病灶明细表 按照病灶级别 (OCT 暂时不删除,先看是否能覆盖)
@@ -2952,7 +2949,7 @@ namespace IRaCIS.Core.Application.Service.Common
arbitrationRule = criterion.ArbitrationRule, arbitrationRule = criterion.ArbitrationRule,
trialReadingCriterionId = inQuery.TrialReadingCriterionId, trialReadingCriterionId = inQuery.TrialReadingCriterionId,
isEn_Us = _userInfo.IsEn_Us isEn_Us = _userInfo.IsEn_Us
}).ToListAsync(); }).AsSplitQuery().ToListAsync();
} }
// 非肿瘤标准 包括自定义,以及系统非肿瘤 会配置到表格层级 问题名称是 表格名称_表格子问题名 // 非肿瘤标准 包括自定义,以及系统非肿瘤 会配置到表格层级 问题名称是 表格名称_表格子问题名
@@ -2970,7 +2967,7 @@ namespace IRaCIS.Core.Application.Service.Common
arbitrationRule = criterion.ArbitrationRule, arbitrationRule = criterion.ArbitrationRule,
trialReadingCriterionId = inQuery.TrialReadingCriterionId, trialReadingCriterionId = inQuery.TrialReadingCriterionId,
isEn_Us = _userInfo.IsEn_Us isEn_Us = _userInfo.IsEn_Us
}).ToListAsync(); }).AsSplitQuery().ToListAsync();
} }
// CDISC 导出 只管到 外层问题层级 和阅片结果表是保持一致 // CDISC 导出 只管到 外层问题层级 和阅片结果表是保持一致
@@ -2988,7 +2985,7 @@ namespace IRaCIS.Core.Application.Service.Common
arbitrationRule = criterion.ArbitrationRule, arbitrationRule = criterion.ArbitrationRule,
trialReadingCriterionId = inQuery.TrialReadingCriterionId, trialReadingCriterionId = inQuery.TrialReadingCriterionId,
isEn_Us = _userInfo.IsEn_Us isEn_Us = _userInfo.IsEn_Us
}).ToListAsync(); }).AsSplitQuery().ToListAsync();
} }
else else
{ {
@@ -3000,7 +2997,7 @@ namespace IRaCIS.Core.Application.Service.Common
arbitrationRule = criterion.ArbitrationRule, arbitrationRule = criterion.ArbitrationRule,
trialReadingCriterionId = inQuery.TrialReadingCriterionId, trialReadingCriterionId = inQuery.TrialReadingCriterionId,
isEn_Us = _userInfo.IsEn_Us isEn_Us = _userInfo.IsEn_Us
}).ToListAsync(); }).AsSplitQuery().ToListAsync();
} }
} }
@@ -3170,7 +3167,7 @@ namespace IRaCIS.Core.Application.Service.Common
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion Type" : "病灶类型", QuestionValue = lession.LessionType, TranslateDicName = "LesionType" }); addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion Type" : "病灶类型", QuestionValue = lession.LessionType, TranslateDicName = "LesionType" });
} }
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, OptionTypeEnum = t.OptionTypeEnum, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName ,Unit=t.Unit}); var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, OptionTypeEnum = t.OptionTypeEnum, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, Unit = t.Unit });
//有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题 //有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题
var dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList(); var dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList();
@@ -3358,9 +3355,10 @@ namespace IRaCIS.Core.Application.Service.Common
dynamicColumnConfig = new DynamicColumnConfig() dynamicColumnConfig = new DynamicColumnConfig()
{ {
AutoColumnTitleRowIndex = 2,
AutoColumnStartIndex = 6, AutoColumnTitleRowIndex = 3, //2
TempalteLastColumnIndex = 11, AutoColumnStartIndex = 7, //6
TempalteLastColumnIndex = 12,//11
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "QuestionValue", DynamicItemValueName = "QuestionValue",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -3372,7 +3370,7 @@ namespace IRaCIS.Core.Application.Service.Common
TranslateDicNameList = translateDicNameList TranslateDicNameList = translateDicNameList
}; };
if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export || export_Template== StaticData.Export.OCT_ReadingLession_Export) if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export || export_Template == StaticData.Export.OCT_ReadingLession_Export)
{ {
dynamicColumnConfig.TempalteLastColumnIndex = 8; dynamicColumnConfig.TempalteLastColumnIndex = 8;
} }
@@ -3435,7 +3433,7 @@ namespace IRaCIS.Core.Application.Service.Common
var dynamicLessionInfoList = new List<CommonQuesionInfo>(); var dynamicLessionInfoList = new List<CommonQuesionInfo>();
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId,OptionTypeEnum=t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit }); var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, OptionTypeEnum = t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
//两部分组成 外层问题+ 动态的表格问题 //两部分组成 外层问题+ 动态的表格问题
dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList(); dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList();
@@ -3458,9 +3456,9 @@ namespace IRaCIS.Core.Application.Service.Common
dynamicColumnConfig = new DynamicColumnConfig() dynamicColumnConfig = new DynamicColumnConfig()
{ {
AutoColumnTitleRowIndex = 1, AutoColumnTitleRowIndex = 2, //1
AutoColumnStartIndex = 6, AutoColumnStartIndex = 7, //6
TempalteLastColumnIndex = 10, TempalteLastColumnIndex = 11, //10
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "QuestionValue", DynamicItemValueName = "QuestionValue",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -3543,9 +3541,9 @@ namespace IRaCIS.Core.Application.Service.Common
dynamicColumnConfig = new DynamicColumnConfig() dynamicColumnConfig = new DynamicColumnConfig()
{ {
AutoColumnTitleRowIndex = 1, AutoColumnTitleRowIndex = 2, //1
AutoColumnStartIndex = 6, AutoColumnStartIndex = 7, //6
TempalteLastColumnIndex = 15, TempalteLastColumnIndex = 16, //15
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "QuestionValue", DynamicItemValueName = "QuestionValue",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -3578,9 +3576,9 @@ namespace IRaCIS.Core.Application.Service.Common
dynamicColumnConfig = new DynamicColumnConfig() dynamicColumnConfig = new DynamicColumnConfig()
{ {
AutoColumnTitleRowIndex = 1, AutoColumnTitleRowIndex = 2, //1
AutoColumnStartIndex = 6, AutoColumnStartIndex = 7, //6
TempalteLastColumnIndex = 10, TempalteLastColumnIndex = 11, //10
DynamicItemDicName = "TranslateDicName", DynamicItemDicName = "TranslateDicName",
DynamicItemValueName = "QuestionValue", DynamicItemValueName = "QuestionValue",
DynamicItemTitleName = "QuestionName", DynamicItemTitleName = "QuestionName",
@@ -3650,12 +3648,12 @@ namespace IRaCIS.Core.Application.Service.Common
if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC) if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC)
{ {
(memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig); (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
} }
else else
{ {
(memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig); (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
} }
@@ -1,26 +1,15 @@
using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Application.Contracts;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs; using MiniExcelLibs;
using MiniExcelLibs.OpenXml; using MiniExcelLibs.OpenXml;
using Newtonsoft.Json; using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1.X509;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Service.Common; namespace IRaCIS.Core.Application.Service.Common;
@@ -1,32 +1,9 @@
using Amazon.Runtime.Internal.Transform; using IRaCIS.Application.Contracts;
using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Office2010.CustomUI;
using DocumentFormat.OpenXml.Office2021.DocumentTasks;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using MailKit;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using NetTopologySuite.Triangulate.Tri;
using NPOI.OpenXmlFormats.Spreadsheet;
using NPOI.SS.Formula.Functions;
using NPOI.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static IRaCIS.Core.Application.Service.ExcelExportHelper;
namespace IRaCIS.Core.Application.Service.Common; namespace IRaCIS.Core.Application.Service.Common;
@@ -24,11 +24,26 @@ namespace IRaCIS.Core.Application.Service;
[ApiExplorerSettings(GroupName = "Common")] [ApiExplorerSettings(GroupName = "Common")]
public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRecordRepository, IRepository<UploadFileSyncRecord> _uploadFileSyncRecordRepository, public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRecordRepository, IRepository<UploadFileSyncRecord> _uploadFileSyncRecordRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<ObjectStoreServiceOptions> options, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<ObjectStoreServiceOptions> options,
IRepository<CommonUploadRecord> _commonUploadRecordRepository,
IFusionCache _fusionCache, IRepository<Trial> _trialRepository, FileSyncQueue _fileSyncQueue) : BaseService, IFileUploadRecordService IFusionCache _fusionCache, IRepository<Trial> _trialRepository, FileSyncQueue _fileSyncQueue) : BaseService, IFileUploadRecordService
{ {
ObjectStoreServiceOptions ObjectStoreServiceConfig = options.CurrentValue; ObjectStoreServiceOptions ObjectStoreServiceConfig = options.CurrentValue;
/// <summary>
/// 上传通用文件记录
/// </summary>
/// <param name="addOrEditCommonUploadRecord"></param>
/// <returns></returns>
public async Task<IResponseOutput> AddOrUpdateCommonUploadRecord(CommonUploadRecordAddOrEdit addOrEditCommonUploadRecord)
{
var entity = await _commonUploadRecordRepository.InsertOrUpdateAsync(addOrEditCommonUploadRecord, true);
return ResponseOutput.Ok(entity.Id.ToString());
}
/// <summary> /// <summary>
@@ -222,7 +237,7 @@ public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRe
{ {
addOrEditFileUploadRecord.IsNeedSync = true; addOrEditFileUploadRecord.IsNeedSync = true;
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority?? 0; addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
addOrEditFileUploadRecord.IsSync = false; addOrEditFileUploadRecord.IsSync = false;
} }
@@ -1,6 +1,8 @@
using IRaCIS.Application.Contracts; using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
@@ -66,7 +68,7 @@ namespace IRaCIS.Core.Application.Service
Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl); Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl);
Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456", string baseUrl=""); Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456", string baseUrl = "");
Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string userTypes, string baseUrl, string rootUrl); Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string userTypes, string baseUrl, string rootUrl);
@@ -105,9 +107,17 @@ namespace IRaCIS.Core.Application.Service
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
/// <summary>
/// 获取邮件主题和html 通用封装 以用户语言为主,没有的就用当前的请求语言_userInfo.IsEn_Us
/// </summary>
/// <param name="scenario"></param>
/// <param name="messageToSend"></param>
/// <param name="emailFunc"></param>
/// <param name="userWorkLanguage"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend, private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc) Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
{ {
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync(); var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();
@@ -119,7 +129,9 @@ namespace IRaCIS.Core.Application.Service
} }
var (topicStr, htmlBodyStr) = _userInfo.IsEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN); bool isEn_Us = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : _userInfo.IsEn_Us;
var (topicStr, htmlBodyStr) = isEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
try try
{ {
@@ -182,24 +194,16 @@ namespace IRaCIS.Core.Application.Service
return sucessHandle; return sucessHandle;
} }
private string ReplaceCompanyName(string needDealtxt)
{
var str = needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
.Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
return str;
}
private string ReplacePlatformName(string needDealtxt)
{
var platformName = _userInfo.IsEn_Us ? _systemEmailConfig.PlatformName : _systemEmailConfig.PlatformNameCN;
var str = needDealtxt.Replace("{platformName}", platformName);
return str;
}
//MFA //MFA
public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login) public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login)
{ {
//设置工作语言
var workLanguage = _identityUserRepository.Where(t => t.Id == userId).Select(t => t.UserWorkLanguage).First();
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -207,13 +211,13 @@ namespace IRaCIS.Core.Application.Service
messageToSend.To.Add(new MailboxAddress(userName, emailAddress)); messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
//主题---[来自{0}] 关于MFA邮箱验证的提醒 //主题---[来自{0}] 关于MFA邮箱验证的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userName, userName,
verificationCode verificationCode
); );
@@ -222,7 +226,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc, workLanguage);
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress); var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
@@ -245,6 +249,11 @@ namespace IRaCIS.Core.Application.Service
public async Task SendEmailVerification(string emailAddress, int verificationCode) public async Task SendEmailVerification(string emailAddress, int verificationCode)
{ {
//设置工作语言
var isEn_US = _userInfo.IsEn_Us;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -253,13 +262,13 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC]的提醒 //---[来自展影IRC]的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
"Sir/Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目 //---您正在参与展影医疗IRC项目
@@ -271,7 +280,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc, workLanguage);
//此时不知道用户 //此时不知道用户
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
@@ -286,8 +295,10 @@ namespace IRaCIS.Core.Application.Service
//中心调研 登陆 发送验证码 //中心调研 登陆 发送验证码
public async Task AnolymousSendEmail(Guid trialId, string emailAddress, int verificationCode) public async Task AnolymousSendEmail(Guid trialId, string emailAddress, int verificationCode)
{ {
//throw new BusinessValidationFailedException("模拟邮件取数据或者发送异常!!!");
//设置工作语言
var isEn_US = _userInfo.IsEn_Us;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
@@ -299,13 +310,13 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒"; //$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
"Sir/Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目中心调研工作 //---您正在参与展影医疗IRC项目中心调研工作
@@ -317,13 +328,13 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc, workLanguage);
//此时不知道用户 //此时不知道用户
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, sucessHandle); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo, sucessHandle);
} }
@@ -335,6 +346,9 @@ namespace IRaCIS.Core.Application.Service
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
@@ -349,20 +363,19 @@ namespace IRaCIS.Core.Application.Service
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new IdentityUser() { EmailToken = token }); await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new IdentityUser() { EmailToken = token });
routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName, sysUserInfo.FullName,
sysUserInfo.EMail, sysUserInfo.EMail,
@@ -374,7 +387,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc, sysUserInfo.UserWorkLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
@@ -385,6 +398,11 @@ namespace IRaCIS.Core.Application.Service
{ {
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -393,13 +411,13 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC] 关于重置账户密码的提醒 //---[来自展影IRC] 关于重置账户密码的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName, sysUserInfo.FullName,
sysUserInfo.UserName, sysUserInfo.UserName,
@@ -413,7 +431,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc, sysUserInfo.UserWorkLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
} }
@@ -421,6 +439,10 @@ namespace IRaCIS.Core.Application.Service
//用户重置邮箱 //用户重置邮箱
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode) public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
{ {
//设置工作语言
var workLanguage = _identityUserRepository.Where(t => t.Id == userId).Select(t => t.UserWorkLanguage).First();
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
@@ -430,13 +452,13 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC] 关于重置邮箱的提醒 //---[来自展影IRC] 关于重置邮箱的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userName, userName,
//---您正在进行邮箱重置操作 //---您正在进行邮箱重置操作
@@ -447,7 +469,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc, workLanguage);
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress); var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
@@ -460,6 +482,11 @@ namespace IRaCIS.Core.Application.Service
//不登录 通过邮箱重置密码 //不登录 通过邮箱重置密码
public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode) public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode)
{ {
//设置工作语言
var isEn_US = _userInfo.IsEn_Us;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -467,13 +494,13 @@ namespace IRaCIS.Core.Application.Service
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress)); messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
"Sir/Madam", "Sir/Madam",
//---您正在进行邮箱重置密码操作 //---您正在进行邮箱重置密码操作
@@ -484,7 +511,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc, workLanguage);
////此时不知道用户 ////此时不知道用户
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
@@ -500,6 +527,11 @@ namespace IRaCIS.Core.Application.Service
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException(); var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -518,18 +550,18 @@ namespace IRaCIS.Core.Application.Service
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName, sysUserInfo.FullName,
trialInfo.ExperimentName, trialInfo.ExperimentName,
@@ -544,9 +576,9 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
@@ -555,10 +587,12 @@ namespace IRaCIS.Core.Application.Service
{ {
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException(); var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -575,20 +609,20 @@ namespace IRaCIS.Core.Application.Service
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token }); await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
} }
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName, sysUserInfo.FullName,
trialInfo.ExperimentName, trialInfo.ExperimentName,
@@ -603,9 +637,9 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
@@ -644,6 +678,12 @@ namespace IRaCIS.Core.Application.Service
saveItem.IsTestUser = true; saveItem.IsTestUser = true;
} }
//通过医生信息,设置工作语言
var nation = _doctorTypeRepository.Where(t => t.Id == doctorId).Select(t => t.Nation).FirstOrDefault();
saveItem.UserWorkLanguage = nation == DoctorNation.CN ? UserWorkLanguage.CN : UserWorkLanguage.US;
saveItem.UserCeateSource = UserCeateSource.ReviewerSelect; saveItem.UserCeateSource = UserCeateSource.ReviewerSelect;
saveItem.TrialId = trialId; saveItem.TrialId = trialId;
@@ -686,6 +726,11 @@ namespace IRaCIS.Core.Application.Service
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -701,7 +746,7 @@ namespace IRaCIS.Core.Application.Service
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token }); await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
} }
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
@@ -711,13 +756,13 @@ namespace IRaCIS.Core.Application.Service
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信"; // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName, sysUserInfo.FullName,
trialInfo.ExperimentName, trialInfo.ExperimentName,
@@ -732,9 +777,9 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc,workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo, null);
//创建账号 和创建角色 一条,更新的时候才记录更新角色 //创建账号 和创建角色 一条,更新的时候才记录更新角色
if (isNeedCreateNewUser == false) if (isNeedCreateNewUser == false)
@@ -754,6 +799,10 @@ namespace IRaCIS.Core.Application.Service
{ {
var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUserRole.UserTypeRole).Include(t => t.CreateUserRole.IdentityUser).FirstNotNullAsync(); var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUserRole.UserTypeRole).Include(t => t.CreateUserRole.IdentityUser).FirstNotNullAsync();
//设置工作语言
var workLanguage = _identityUserRepository.Where(t => t.Id == _userInfo.IdentityUserId).Select(t => t.UserWorkLanguage).First();
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -762,7 +811,7 @@ namespace IRaCIS.Core.Application.Service
var trialinfo = await _trialRepository.Where(x => x.Id == feedBack.TrialId).FirstOrDefaultAsync(); var trialinfo = await _trialRepository.Where(x => x.Id == feedBack.TrialId).FirstOrDefaultAsync();
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack)); var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack));
@@ -785,7 +834,7 @@ namespace IRaCIS.Core.Application.Service
if (feedBack.VisitTaskId != null) if (feedBack.VisitTaskId != null)
{ {
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "FeedBackTypeToIR" && t.ParentId != null && t.Code == ((int)feedBack.QuestionType).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "FeedBackTypeToIR" && t.ParentId != null && t.Code == ((int)feedBack.QuestionType).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync(); var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync();
@@ -794,7 +843,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName); var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userNames, userNames,
info.TrialCode, info.TrialCode,
info.SubejctCode, info.SubejctCode,
@@ -810,12 +859,12 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc, workLanguage);
} }
else if (feedBack.SubjectVisitId != null) else if (feedBack.SubjectVisitId != null)
{ {
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync(); var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync();
@@ -824,7 +873,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName); var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userNames, userNames,
info.TrialCode, info.TrialCode,
info.SubejctCode, info.SubejctCode,
@@ -840,13 +889,13 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc, workLanguage);
} }
//项目相关的反馈 pm admin //项目相关的反馈 pm admin
else if (feedBack.TrialId != null) else if (feedBack.TrialId != null)
{ {
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync(); var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync();
@@ -855,7 +904,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo); var topicStr = string.Format(input.topicStr, info.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userNames, userNames,
info.TrialCode, info.TrialCode,
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
@@ -869,7 +918,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc, workLanguage);
} }
//项目无关的反馈 admin //项目无关的反馈 admin
@@ -881,7 +930,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var topicStr = string.Format(input.topicStr); var topicStr = string.Format(input.topicStr);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
userNames, userNames,
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
feedBack.CreateUserRole.IdentityUser.FullName, feedBack.CreateUserRole.IdentityUser.FullName,
@@ -893,7 +942,7 @@ namespace IRaCIS.Core.Application.Service
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc, workLanguage);
} }
if (trialinfo == null) if (trialinfo == null)
@@ -902,7 +951,7 @@ namespace IRaCIS.Core.Application.Service
} }
else else
{ {
await SendEmailHelper.SendEmailAsync(messageToSend, trialinfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialinfo);
} }
@@ -915,6 +964,10 @@ namespace IRaCIS.Core.Application.Service
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException(); var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
//设置工作语言
var workLanguage = sysUserInfo.UserWorkLanguage;
var isEn_US = workLanguage == UserWorkLanguage.US;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -923,22 +976,23 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC] 关于重置邮箱的提醒 //---[来自展影IRC] 关于重置邮箱的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName); var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(ReplacePlatformName(ReplaceCompanyName(input.htmlBodyStr)) , var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
sysUserInfo.FullName sysUserInfo.FullName,
_systemEmailConfig.PlatformName
); );
return (topicStr, htmlBodyStr); return (topicStr, htmlBodyStr);
}; };
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IdentityUser_ModifyPassword, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IdentityUser_ModifyPassword, messageToSend, emailConfigFunc, workLanguage);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
} }
@@ -948,6 +1002,10 @@ namespace IRaCIS.Core.Application.Service
{ {
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync(); var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync();
//设置工作语言
var isEn_US = _userInfo.IsEn_Us;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -956,14 +1014,14 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC] 关于重置邮箱的提醒 //---[来自展影IRC] 关于重置邮箱的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
name, name,
trialInfo.TrialCode, trialInfo.TrialCode,
trialInfo.ResearchProgramNo trialInfo.ResearchProgramNo
@@ -974,14 +1032,20 @@ namespace IRaCIS.Core.Application.Service
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_CheckUser, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_CheckUser, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
public async Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url) public async Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url)
{ {
var siteInfo = await _trialSiteRepository.Where(t => t.Id == trialSiteId).Include(x=>x.Trial).FirstOrDefaultAsync(); var siteInfo = await _trialSiteRepository.Where(t => t.Id == trialSiteId).Include(x => x.Trial).FirstOrDefaultAsync();
var trialInfo = siteInfo.Trial; var trialInfo = siteInfo.Trial;
//设置工作语言
var isEn_US = _userInfo.IsEn_Us;
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
var messageToSend = new MimeMessage(); var messageToSend = new MimeMessage();
//发件地址 //发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
@@ -990,14 +1054,14 @@ namespace IRaCIS.Core.Application.Service
//主题 //主题
//---[来自展影IRC] 关于重置邮箱的提醒 //---[来自展影IRC] 关于重置邮箱的提醒
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{ {
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
name, name,
trialInfo.TrialCode, trialInfo.TrialCode,
siteInfo.TrialSiteCode, siteInfo.TrialSiteCode,
@@ -1010,7 +1074,7 @@ namespace IRaCIS.Core.Application.Service
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_UpdateUser, messageToSend, emailConfigFunc); await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_UpdateUser, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo); await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
} }
} }
File diff suppressed because it is too large Load Diff
@@ -131,6 +131,11 @@ namespace IRaCIS.Core.Application.Service
CreateMap<FileUploadRecord, FileUploadRecordAddOrEdit>().ReverseMap(); CreateMap<FileUploadRecord, FileUploadRecordAddOrEdit>().ReverseMap();
CreateMap<CommonUploadRecordAddOrEdit, CommonUploadRecord>().ReverseMap();
CreateMap<CommonUploadRecord, CommonUploadRecordDto>();
CreateMap<UploadFileSyncRecord, UploadFileSyncRecordView>() CreateMap<UploadFileSyncRecord, UploadFileSyncRecordView>()
.ForMember(d => d.FileName, u => u.MapFrom(s => s.FileUploadRecord.FileName)) .ForMember(d => d.FileName, u => u.MapFrom(s => s.FileUploadRecord.FileName))
.ForMember(d => d.FileType, u => u.MapFrom(s => s.FileUploadRecord.FileType)) .ForMember(d => d.FileType, u => u.MapFrom(s => s.FileUploadRecord.FileType))
@@ -149,7 +149,7 @@ namespace IRaCIS.Application.Contracts
public bool? AcceptingNewTrial { get; set; }//是否接受新的项目 public bool? AcceptingNewTrial { get; set; }//是否接受新的项目
public bool? ActivelyReading { get; set; }// 是否接受新的读片任务 public bool? ActivelyReading { get; set; }// 是否接受新的读片任务
public int? Nation { get; set; }// 0-中国医生,2-美国医生,3-全部 public DoctorNation? Nation { get; set; }// 0-中国医生,2-美国医生,3-全部
} }
/// <summary> /// <summary>
@@ -4,26 +4,10 @@
// 生成时间 2025-03-27 06:13:33Z // 生成时间 2025-03-27 06:13:33Z
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infrastructure.Extention;
using System.Threading.Tasks;
using IRaCIS.Core.Infra.EFCore;
using AutoMapper.Execution;
using System.Linq;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using DocumentFormat.OpenXml.Office2010.Excel;
using MassTransit; using MassTransit;
using NPOI.POIFS.Properties;
using Org.BouncyCastle.Crypto;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Application.Contracts;
using Microsoft.EntityFrameworkCore;
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;
using NPOI.SS.Formula.Functions;
using EFCore.BulkExtensions;
namespace IRaCIS.Core.Application.Service; namespace IRaCIS.Core.Application.Service;
@@ -50,6 +50,7 @@ namespace IRaCIS.Core.Application.Contracts
public bool? OffLine { get; set; } public bool? OffLine { get; set; }
public Guid? SystemDocumentId { get; set; } public Guid? SystemDocumentId { get; set; }
} }
@@ -79,14 +80,18 @@ namespace IRaCIS.Core.Application.Contracts
} }
public class TrialSignDocView : UnionDocumentWithConfirmInfoView public class TriaAndSystemlSignDocView : UnionDocumentWithConfirmInfoView
{ {
public string TrialCode { get; set; } public string TrialCode { get; set; }
public string ResearchProgramNo { get; set; } public string ResearchProgramNo { get; set; }
public string ExperimentName { get; set; } public string ExperimentName { get; set; }
public TrialType TrialType { get; set; }
public bool IsTestUser { get; set; }
public UserWorkLanguage UserWorkLanguage { get; set; }
} }
@@ -205,7 +210,7 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime? EndCreateTime { get; set; } public DateTime? EndCreateTime { get; set; }
public DocLanguageType? DocLanguageType { get; set; }
} }
public class GetNextUnSignDocumentInDto public class GetNextUnSignDocumentInDto
@@ -362,6 +367,10 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsPublish { get; set; } = false; public bool IsPublish { get; set; } = false;
public DocLanguageType DocLanguageType { get; set; }
} }
@@ -62,10 +62,18 @@ namespace IRaCIS.Core.Application.Service
}).FirstNotNullAsync(); }).FirstNotNullAsync();
var isEn_us = _userInfo.IsEn_Us; //找到当前收件人语言
var workLanguageList = _trialUserRoleRepository.Where(t => t.TrialId == taskInfo.TrialId && t.UserRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => t.UserRole.IdentityUser.UserWorkLanguage).Distinct().ToList();
foreach (var workLanguage in workLanguageList)
{
//设置工作语言
var isEn_us = workLanguage == UserWorkLanguage.US;
var resultStr = isEn_us ? (result == true ? "Yes" : "No") : (result == true ? "是" : "否"); var resultStr = isEn_us ? (result == true ? "Yes" : "No") : (result == true ? "是" : "否");
if (isEnrollment == true) if (isEnrollment == true)
{ {
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig => Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
@@ -97,6 +105,7 @@ namespace IRaCIS.Core.Application.Service
await SendTrialEmailAsync(taskInfo.TrialId, taskInfo.CriterionType, businessScenarioEnum, topicAndHtmlFunc, taskInfo.TrialSiteId); await SendTrialEmailAsync(taskInfo.TrialId, taskInfo.CriterionType, businessScenarioEnum, topicAndHtmlFunc, taskInfo.TrialSiteId);
} }
}
} }
@@ -133,8 +142,12 @@ namespace IRaCIS.Core.Application.Service
var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig); var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig);
//设置工作语言
var workLanguage = isEn_us ? UserWorkLanguage.US : UserWorkLanguage.CN;
//处理替换公司名 //处理替换公司名
htmlBodyStr = CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlBodyStr); htmlBodyStr = CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlBodyStr, workLanguage);
sendEmailConfig.TopicDescription = topicStr; sendEmailConfig.TopicDescription = topicStr;
@@ -150,10 +163,10 @@ namespace IRaCIS.Core.Application.Service
var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList(); var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList();
var allUserList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.UserRole.UserTypeEnum)).Select(t => new { t.UserId, t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToListAsync(); var allUserList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.UserRole.UserTypeEnum)).Select(t => new { t.UserId, t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
//过滤当前语言
var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum)) var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum)).Where(t=>t.UserWorkLanguage==workLanguage)
.ToList(); .ToList();
//收件人 有CRC CRA , CRC CRA的账户要按照中心发送 //收件人 有CRC CRA , CRC CRA的账户要按照中心发送
@@ -191,11 +204,6 @@ namespace IRaCIS.Core.Application.Service
sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList())); sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList()));
} }
if (toUserList.Count == 0)
{
//---没有收件人,无法发送邮件
throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]);
}
if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail)) if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail))
@@ -235,20 +243,7 @@ namespace IRaCIS.Core.Application.Service
} }
} }
//邮件附件 这里是原格式发送,不是PDF
//if (trialEmailConfig.AttachCNPath != string.Empty && trialEmailConfig.AttachPath != string.Empty)
//{
// var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, isEn_us? trialEmailConfig.AttachName: trialEmailConfig.AttachNameCN);
// //先预先生成了邮件,发送预先生成的邮件
// sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig()
// {
// FileName = $"{attachPrefix}_{Path.GetFileName(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}",
// FileStream = File.OpenRead(phyPath),
// });
//}
return (trialEmailConfig, sendEmailConfig); return (trialEmailConfig, sendEmailConfig);
@@ -42,6 +42,7 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(inQuery.OffLine != null, t => t.OffLine == inQuery.OffLine) .WhereIf(inQuery.OffLine != null, t => t.OffLine == inQuery.OffLine)
.WhereIf(inQuery.FileName != null, t => t.FileName == inQuery.FileName) .WhereIf(inQuery.FileName != null, t => t.FileName == inQuery.FileName)
.WhereIf(inQuery.FileFormat != null, t => t.FileFormat == inQuery.FileFormat) .WhereIf(inQuery.FileFormat != null, t => t.FileFormat == inQuery.FileFormat)
.ProjectTo<SystemDocumentAttachmentView>(_mapper.ConfigurationProvider); .ProjectTo<SystemDocumentAttachmentView>(_mapper.ConfigurationProvider);
var pageList = await systemDocumentAttachmentQueryable.ToPagedListAsync(inQuery); var pageList = await systemDocumentAttachmentQueryable.ToPagedListAsync(inQuery);
@@ -95,6 +96,7 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime) .WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId)) .WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted) .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(inQuery.DocLanguageType != null, t => t.DocLanguageType == inQuery.DocLanguageType)
.ProjectTo<SystemDocumentView>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us, userId = _userInfo.UserRoleId }); .ProjectTo<SystemDocumentView>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us, userId = _userInfo.UserRoleId });
return await systemDocumentQueryable.ToPagedListAsync(inQuery); return await systemDocumentQueryable.ToPagedListAsync(inQuery);
@@ -171,23 +173,16 @@ namespace IRaCIS.Core.Application.Services
if (newUserTypeIds.Any()&& newUserTypeIds.Count()>0) if (newUserTypeIds.Any()&& newUserTypeIds.Count()>0)
{ {
// 发送邮件给新增的角色 // 发送邮件给新增的角色
Console.WriteLine("开始 发送系统文档更新邮件给新增角色"); Log.Logger.Warning("开始 发送系统文档更新邮件给新增角色");
Console.WriteLine(string.Join(",", newUserTypeIds)); Log.Logger.Warning(string.Join(",", newUserTypeIds));
Task.Run(async () =>
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
// 只发送给新增的角色 // 只发送给新增的角色
await mediator.Publish(new SystemDocumentPublishEvent { await _mediatorScoped.Publish(new SystemDocumentPublishEvent
{
Ids = new List<Guid> { document.Id }, Ids = new List<Guid> { document.Id },
NewUserTypeIds = newUserTypeIds NewUserTypeIds = newUserTypeIds
}); });
}
});
} }
} }
@@ -212,23 +207,17 @@ namespace IRaCIS.Core.Application.Services
IsDeleted = false, IsDeleted = false,
}); });
Console.WriteLine("开始 发布系统文档"); Log.Logger.Warning("开始 发布系统文档");
await _mediatorScoped.Publish(new SystemDocumentPublishEvent { Ids = inDto.Ids });
Task.Run(async () =>
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new SystemDocumentPublishEvent { Ids = inDto.Ids });
}
});
return ResponseOutput.Result(true); return ResponseOutput.Result(true);
} }
/// <summary> /// <summary>
/// 下线系统文档 /// 下线系统文档
/// </summary> /// </summary>
@@ -286,8 +275,11 @@ namespace IRaCIS.Core.Application.Services
{ {
var isInternal = _userInfo.IsZhiZhun; var isInternal = _userInfo.IsZhiZhun;
var workLanguage = _userInfo.UserWorkLanguage;
var query = from sysDoc in _systemDocumentRepository.Where(t=>t.IsPublish) var query = from sysDoc in _systemDocumentRepository.Where(t=>t.IsPublish)
.WhereIf(workLanguage == UserWorkLanguage.CN, t => t.DocLanguageType == DocLanguageType.CN || t.DocLanguageType == DocLanguageType.CN_US)
.WhereIf(workLanguage == UserWorkLanguage.US, t => t.DocLanguageType == DocLanguageType.US || t.DocLanguageType == DocLanguageType.CN_US)
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId)) .Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name)) .WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
//外部人员 只签署 外部需要签署的 //外部人员 只签署 外部需要签署的
@@ -5,18 +5,10 @@
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.MassTransit.Consumer; using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MassTransit.Mediator; using MassTransit.Mediator;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NPOI.SS.Formula.Functions;
using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
namespace IRaCIS.Core.Application.Services namespace IRaCIS.Core.Application.Services
@@ -27,6 +19,7 @@ namespace IRaCIS.Core.Application.Services
[ApiExplorerSettings(GroupName = "Trial")] [ApiExplorerSettings(GroupName = "Trial")]
public class TrialDocumentService(IRepository<TrialDocument> _trialDocumentRepository, public class TrialDocumentService(IRepository<TrialDocument> _trialDocumentRepository,
IRepository<Trial> _trialRepository, IRepository<Trial> _trialRepository,
IScopedMediator _mediatorScoped,
IRepository<AuditRecord> _auditRecordRepository, IRepository<AuditRecord> _auditRecordRepository,
IRepository<TrialDocumentAttachment> _trialDocumentAttachmentRepository, IRepository<TrialDocumentAttachment> _trialDocumentAttachmentRepository,
ISystemDocumentService _systemDocumentService, ISystemDocumentService _systemDocumentService,
@@ -105,18 +98,11 @@ namespace IRaCIS.Core.Application.Services
IsDeleted = false, IsDeleted = false,
}, false, true); }, false, true);
await _trialDocumentRepository.SaveChangesAsync(); await _trialDocumentRepository.SaveChangesAsync();
Console.WriteLine("开始 发布项目文档"); Serilog.Log.Logger.Warning("开始 发布项目文档");
await _mediatorScoped.Publish(new TrialDocumentPublishEvent { Ids = inDto.Ids });
Task.Run(async () =>
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new TrialDocumentPublishEvent { Ids = inDto.Ids });
}
});
return ResponseOutput.Result(true); return ResponseOutput.Result(true);
@@ -128,32 +114,20 @@ namespace IRaCIS.Core.Application.Services
/// <returns></returns> /// <returns></returns>
public async Task<IResponseOutput> TestPush() public async Task<IResponseOutput> TestPush()
{ {
Task.Run(async () =>
{
// 创建独立作用域 await _mediatorScoped.Publish(new TrialDocumentErverDayEvent { });
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new TrialDocumentErverDayEvent { });
}
});
return ResponseOutput.Result(true); return ResponseOutput.Result(true);
} }
public async Task<IResponseOutput> TestSendEmail() public async Task<IResponseOutput> TestSendEmail()
{ {
Task.Run(async () =>
{ await _mediatorScoped.Publish(new ImageQCRecurringEvent { TrialId = Guid.Parse("08de2254-5d7d-581a-0242-0a0001000000") });
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new ImageQCRecurringEvent { TrialId = Guid.Parse("08de2254-5d7d-581a-0242-0a0001000000") });
}
});
return ResponseOutput.Result(true); return ResponseOutput.Result(true);
} }
@@ -179,7 +153,7 @@ namespace IRaCIS.Core.Application.Services
} }
[HttpPost] [HttpPost]
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery inQuery) public async Task<PageOutput<TriaAndSystemlSignDocView>> GetTrialSignDocumentList(TrialDocQuery inQuery)
{ {
var trialDocQueryable = from trialDoc in _trialDocumentRepository.Where(t => t.IsPublish) var trialDocQueryable = from trialDoc in _trialDocumentRepository.Where(t => t.IsPublish)
.WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId) .WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId)
@@ -190,7 +164,7 @@ namespace IRaCIS.Core.Application.Services
new { trialUser.IdentityUserId, TrialDocumentId = trialDoc.Id } equals new { IdentityUserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc new { trialUser.IdentityUserId, TrialDocumentId = trialDoc.Id } equals new { IdentityUserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
from confirm in cc.DefaultIfEmpty() from confirm in cc.DefaultIfEmpty()
select new TrialSignDocView() select new TriaAndSystemlSignDocView()
{ {
TrialCode = trialDoc.Trial.TrialCode, TrialCode = trialDoc.Trial.TrialCode,
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo, ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
@@ -351,12 +325,16 @@ namespace IRaCIS.Core.Application.Services
var isInternal = _userInfo.IsZhiZhun; var isInternal = _userInfo.IsZhiZhun;
var workLanguage = _userInfo.UserWorkLanguage;
#region #region
var systemDocQuery = var systemDocQuery =
from sysDoc in _systemDocumentRepository.Where(t => t.IsPublish).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId)) from sysDoc in _systemDocumentRepository.Where(t => t.IsPublish).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
//外部人员 只签署 外部需要签署的 //外部人员 只签署 外部需要签署的
.WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter) .WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter)
.WhereIf(workLanguage == UserWorkLanguage.CN, t => t.DocLanguageType == DocLanguageType.CN || t.DocLanguageType == DocLanguageType.CN_US)
.WhereIf(workLanguage == UserWorkLanguage.US, t => t.DocLanguageType == DocLanguageType.US || t.DocLanguageType == DocLanguageType.CN_US)
from trialUser in _trialIdentityUserRepository.AsQueryable(false) from trialUser in _trialIdentityUserRepository.AsQueryable(false)
.Where(t => t.TrialId == inQuery.TrialId && t.IdentityUserId == _userInfo.IdentityUserId .Where(t => t.TrialId == inQuery.TrialId && t.IdentityUserId == _userInfo.IdentityUserId
&& t.TrialUserRoleList.Any(t => sysDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId))) && t.TrialUserRoleList.Any(t => sysDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId)))
@@ -584,6 +562,7 @@ namespace IRaCIS.Core.Application.Services
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.IsPublish) var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.IsPublish)
.Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped) .Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped)
.Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId))) .Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(t => t.IsDeleted == false && !t.TrialDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId)) .Where(t => t.IsDeleted == false && !t.TrialDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId))
@@ -591,6 +570,8 @@ namespace IRaCIS.Core.Application.Services
var needSignSystemDocCount = await _systemDocumentRepository.AsQueryable(true).Where(t => t.IsPublish) var needSignSystemDocCount = await _systemDocumentRepository.AsQueryable(true).Where(t => t.IsPublish)
.WhereIf(workLanguage == UserWorkLanguage.CN, t => t.DocLanguageType == DocLanguageType.CN || t.DocLanguageType == DocLanguageType.CN_US)
.WhereIf(workLanguage == UserWorkLanguage.US, t => t.DocLanguageType == DocLanguageType.US || t.DocLanguageType == DocLanguageType.CN_US)
.WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter) .WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter)
.Where(t => t.IsDeleted == false && !t.SystemDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId)) .Where(t => t.IsDeleted == false && !t.SystemDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId))
.CountAsync(); .CountAsync();
@@ -969,7 +950,7 @@ namespace IRaCIS.Core.Application.Services
IsSystemDoc = true, IsSystemDoc = true,
SysDocUserSignType = sysDoc.DocUserSignType, SysDocUserSignType = sysDoc.DocUserSignType,
IsConfirmIdentityUserInner = identityUser.IsZhiZhun, IsConfirmIdentityUserInner = identityUser.IsZhiZhun,
IsPublish=sysDoc.IsPublish, IsPublish = sysDoc.IsPublish,
Id = sysDoc.Id, Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime, CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted, IsDeleted = sysDoc.IsDeleted,
@@ -1115,7 +1096,7 @@ namespace IRaCIS.Core.Application.Services
return ResponseOutput.NotOk(_localizer["TrialD_DuplicateFileInProject"]); return ResponseOutput.NotOk(_localizer["TrialD_DuplicateFileInProject"]);
} }
var document = (await _trialDocumentRepository.Where(t => t.Id == addOrEditTrialDocument.Id, true,true).Include(t => t.NeedConfirmedUserTypeList).FirstOrDefaultAsync()).IfNullThrowException(); var document = (await _trialDocumentRepository.Where(t => t.Id == addOrEditTrialDocument.Id, true, true).Include(t => t.NeedConfirmedUserTypeList).FirstOrDefaultAsync()).IfNullThrowException();
bool beforeIsPublish = document.IsPublish; bool beforeIsPublish = document.IsPublish;
bool beforeIsDeleted = document.IsDeleted; bool beforeIsDeleted = document.IsDeleted;
@@ -1163,21 +1144,13 @@ namespace IRaCIS.Core.Application.Services
Console.WriteLine("开始 发送项目文档更新邮件给新增角色"); Console.WriteLine("开始 发送项目文档更新邮件给新增角色");
Console.WriteLine(string.Join(",", newUserTypeIds)); Console.WriteLine(string.Join(",", newUserTypeIds));
Task.Run(async () => await _mediatorScoped.Publish(new TrialDocumentPublishEvent
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
// 只发送给新增的角色
await mediator.Publish(new TrialDocumentPublishEvent
{ {
Ids = new List<Guid> { document.Id }, Ids = new List<Guid> { document.Id },
NewUserTypeIds = newUserTypeIds NewUserTypeIds = newUserTypeIds
}); });
}
});
} }
} }
return ResponseOutput.Ok(document.Id.ToString()); return ResponseOutput.Ok(document.Id.ToString());
@@ -24,6 +24,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Spire.Doc; using Spire.Doc;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using System.Runtime;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
@@ -137,7 +138,7 @@ namespace IRaCIS.Core.Application.Service
var isNeedSend = true; var isNeedSend = true;
//手动发送的时候,也有可能答案是是 此时是 这里不发送,发送已经生成的文件 //手动发送的时候,也有可能答案是是 此时是 这里不发送,发送已经生成的文件
if (answer == "是" && isHandSend == null) if ((answer == "是" || answer == "Yes") && isHandSend == null)
{ {
isNeedSend = true; isNeedSend = true;
@@ -194,7 +195,15 @@ namespace IRaCIS.Core.Application.Service
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
public async Task<string> BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isHandSend, EmailStoreSendMode emailStoreMode, string sendFileRelativePath) public async Task<string> BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isHandSend, EmailStoreSendMode emailStoreMode, string sendFileRelativePath)
{ {
var isEn_us = _userInfo.IsEn_Us;
//简单处理,找到该中心的语言 设置工作语言
var country = _visitTaskRepository.Where(t => t.Id == visitTaskId).Select(t => t.Subject.TrialSite.Country).First();
var isEn_us = country == StaticData.SiteCountry.US;
var workLanguage = isEn_us ? UserWorkLanguage.US : UserWorkLanguage.CN;
EmailBusinessScenario businessScenarioEnum = EmailBusinessScenario.None; EmailBusinessScenario businessScenarioEnum = EmailBusinessScenario.None;
var enrollReplace = ""; var enrollReplace = "";
@@ -330,7 +339,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var findItem = (await _dictionaryService.GetBasicDataSelect("Trial_Enroll_Report")).Where(t => t.Code == ((int)taskInfo.CriterionType).ToString()).FirstOrDefault(); var findItem = (await _dictionaryService.GetBasicDataSelect("Trial_Enroll_Report")).Where(t => t.Code == ((int)taskInfo.CriterionType).ToString()).FirstOrDefault();
enrollReplace = _userInfo.IsEn_Us ? findItem.Value : findItem.ValueCN; enrollReplace = isEn_us ? findItem.Value : findItem.ValueCN;
//如果其他阅片人已经做了,说明发送了入组确认报告,第二个人做完就不发送了 //如果其他阅片人已经做了,说明发送了入组确认报告,第二个人做完就不发送了
@@ -348,7 +357,7 @@ namespace IRaCIS.Core.Application.Service
{ {
bool isEnroll = false; bool isEnroll = false;
(answer, isEnroll) = await DealEnrollAnswer(visitTaskId, (Guid)taskInfo.SourceSubjectVisitId, taskInfo.CriterionType, taskInfo.TrialReadingCriterionId); (answer, isEnroll) = await DealEnrollAnswer(visitTaskId, (Guid)taskInfo.SourceSubjectVisitId, taskInfo.CriterionType, taskInfo.TrialReadingCriterionId, workLanguage);
isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List<Guid>() { visitTaskId }, minUserIdList); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, new List<Guid>() { visitTaskId }, minUserIdList);
} }
@@ -357,7 +366,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var findItem = (await _dictionaryService.GetBasicDataSelect("Trial_PD_Report")).Where(t => t.Code == ((int)taskInfo.CriterionType).ToString()).FirstOrDefault(); var findItem = (await _dictionaryService.GetBasicDataSelect("Trial_PD_Report")).Where(t => t.Code == ((int)taskInfo.CriterionType).ToString()).FirstOrDefault();
PdReplace = _userInfo.IsEn_Us ? findItem.Value : findItem.ValueCN; PdReplace = isEn_us ? findItem.Value : findItem.ValueCN;
//有序 //有序
@@ -384,7 +393,7 @@ namespace IRaCIS.Core.Application.Service
if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2) if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) == 2)
{ {
answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType, workLanguage);
isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList);
@@ -394,7 +403,7 @@ namespace IRaCIS.Core.Application.Service
else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1)
{ {
var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First()!.JudgeResultTaskId!.Value; var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First()!.JudgeResultTaskId!.Value;
answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType); answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Visit, taskInfo.CriterionType, workLanguage);
isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList);
@@ -431,7 +440,7 @@ namespace IRaCIS.Core.Application.Service
if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Global) == 2) if (taskList.Count == 2 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Global) == 2)
{ {
answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType, workLanguage);
isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Select(t => t.Id).ToList(), minUserIdList);
} }
@@ -440,7 +449,7 @@ namespace IRaCIS.Core.Application.Service
{ {
var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId!.Value; var judgeResultId = taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).First().JudgeResultTaskId!.Value;
answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Global, taskInfo.CriterionType); answer = await TranslatePdStateAsync(judgeResultId, ReadingCategory.Global, taskInfo.CriterionType, workLanguage);
isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList); isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isHandSend, answer, taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Select(t => t.Id).ToList(), minUserIdList);
@@ -613,7 +622,7 @@ namespace IRaCIS.Core.Application.Service
//先预先生成了邮件,发送预先生成的邮件 //先预先生成了邮件,发送预先生成的邮件
sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig()
{ {
FileName = $"{attachPrefix}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig!.AttachNameCN)}.pdf", FileName = $"{attachPrefix}_{Path.GetFileNameWithoutExtension(isEn_us ? trialEmailConfig.AttachName : trialEmailConfig!.AttachNameCN)}.pdf",
FileStream = File.OpenRead(phyPath), FileStream = File.OpenRead(phyPath),
}); });
@@ -639,7 +648,7 @@ namespace IRaCIS.Core.Application.Service
}; };
var path = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, _userInfo.IsEn_Us ? trialEmailConfig.AttachPath : trialEmailConfig.AttachCNPath); var path = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, isEn_us ? trialEmailConfig.AttachPath : trialEmailConfig.AttachCNPath);
//获取从word 到 PDF的路径 //获取从word 到 PDF的路径
var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetSubjectEnrollConfirmOrPDEmailPath(_hostEnvironment, Path.GetFileName(path), taskInfo.TrialId, taskInfo.TrialSiteId, taskInfo.SubjectId, true); var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetSubjectEnrollConfirmOrPDEmailPath(_hostEnvironment, Path.GetFileName(path), taskInfo.TrialId, taskInfo.TrialSiteId, taskInfo.SubjectId, true);
@@ -729,7 +738,7 @@ namespace IRaCIS.Core.Application.Service
pdfMemoryStream.Seek(0, SeekOrigin.Begin); pdfMemoryStream.Seek(0, SeekOrigin.Begin);
sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig()
{ {
FileName = $"{taskInfo.SubjectCode}_{Path.GetFileNameWithoutExtension(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}.pdf", FileName = $"{taskInfo.SubjectCode}_{Path.GetFileNameWithoutExtension(isEn_us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}.pdf",
FileStream = pdfMemoryStream FileStream = pdfMemoryStream
}); });
@@ -1067,11 +1076,14 @@ namespace IRaCIS.Core.Application.Service
/// <param name="subjectVisitId"></param> /// <param name="subjectVisitId"></param>
/// <param name="criterionType"></param> /// <param name="criterionType"></param>
/// <param name="trialReadingCriterionId"></param> /// <param name="trialReadingCriterionId"></param>
/// <param name="userWorkLanguage"></param>
/// <returns></returns> /// <returns></returns>
private async Task<(string enrollAnswer, bool isEnroll)> DealEnrollAnswer(Guid visitTaskId, Guid subjectVisitId, CriterionType criterionType, Guid trialReadingCriterionId) private async Task<(string enrollAnswer, bool isEnroll)> DealEnrollAnswer(Guid visitTaskId, Guid subjectVisitId, CriterionType criterionType, Guid trialReadingCriterionId, UserWorkLanguage userWorkLanguage)
{ {
var enrollAnswer = _userInfo.IsEn_Us ? "No" : "否"; var isEn_us = userWorkLanguage == UserWorkLanguage.US;
var enrollAnswer = isEn_us ? "No" : "否";
var isEnroll = false; var isEnroll = false;
switch (criterionType) switch (criterionType)
@@ -1088,7 +1100,7 @@ namespace IRaCIS.Core.Application.Service
if (await _readingTableQuestionAnswerRepository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() && if (await _readingTableQuestionAnswerRepository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() &&
x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion)) x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion))
{ {
enrollAnswer = _userInfo.IsEn_Us ? "Yes" : "是"; enrollAnswer = isEn_us ? "Yes" : "是";
isEnroll = true; isEnroll = true;
} }
@@ -1102,7 +1114,7 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
bool exists = list.Any(s => int.TryParse(s, out var n) && n >= 1); bool exists = list.Any(s => int.TryParse(s, out var n) && n >= 1);
if (exists) if (exists)
{ {
enrollAnswer = _userInfo.IsEn_Us ? "Yes" : "是"; enrollAnswer = isEn_us ? "Yes" : "是";
isEnroll = true; isEnroll = true;
} }
@@ -1168,9 +1180,10 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
/// <param name="readingCategory"> 任务类型</param> /// <param name="readingCategory"> 任务类型</param>
/// <param name="criterionType">标准类型</param> /// <param name="criterionType">标准类型</param>
/// <param name="IsGlobalGenerate"> 是否是全局产生(区分裁判任务)</param> /// <param name="IsGlobalGenerate"> 是否是全局产生(区分裁判任务)</param>
/// <param name="userWorkLanguage"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
private async Task<string> TranslatePdStateAsync(Guid visitTaskId, ReadingCategory readingCategory, CriterionType criterionType, bool? IsGlobalGenerate = null) private async Task<string> TranslatePdStateAsync(Guid visitTaskId, ReadingCategory readingCategory, CriterionType criterionType, UserWorkLanguage userWorkLanguage, bool? IsGlobalGenerate = null)
{ {
var answer = string.Empty; var answer = string.Empty;
@@ -1361,6 +1374,7 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidTaskTypeForEmailSending"]); throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidTaskTypeForEmailSending"]);
} }
var isEn_us = userWorkLanguage == UserWorkLanguage.US;
switch (criterionType) switch (criterionType)
{ {
@@ -1372,11 +1386,11 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
if (answer == OverallAssessment.PD.GetEnumInt()) if (answer == OverallAssessment.PD.GetEnumInt())
{ {
answer = _userInfo.IsEn_Us ? "Yes" : "是"; answer = isEn_us ? "Yes" : "是";
} }
else else
{ {
answer = _userInfo.IsEn_Us ? "No" : "否"; answer = isEn_us ? "No" : "否";
} }
break; break;
@@ -1384,11 +1398,11 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
if (answer == OverallAssessment.iCPD.GetEnumInt()) if (answer == OverallAssessment.iCPD.GetEnumInt())
{ {
answer = _userInfo.IsEn_Us ? "Yes" : "是"; answer = isEn_us ? "Yes" : "是";
} }
else else
{ {
answer = _userInfo.IsEn_Us ? "No" : "否"; answer = isEn_us ? "No" : "否";
} }
break; break;
@@ -1396,11 +1410,11 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
if (answer == CTMRIOverallAssessment.PD.GetEnumInt()) if (answer == CTMRIOverallAssessment.PD.GetEnumInt())
{ {
answer = _userInfo.IsEn_Us ? "Yes" : "是"; answer = isEn_us ? "Yes" : "是";
} }
else else
{ {
answer = _userInfo.IsEn_Us ? "No" : "否"; answer = isEn_us ? "No" : "否";
} }
break; break;
@@ -1408,11 +1422,11 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
if (answer == ImagingOverallAssessment_Lugano.PMDPD.GetEnumInt()) if (answer == ImagingOverallAssessment_Lugano.PMDPD.GetEnumInt())
{ {
answer = _userInfo.IsEn_Us ? "Yes" : "是"; answer = isEn_us ? "Yes" : "是";
} }
else else
{ {
answer = _userInfo.IsEn_Us ? "No" : "否"; answer = isEn_us ? "No" : "否";
} }
break; break;
@@ -1423,11 +1437,11 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
if (answer == VisitTumorEvaluation.PD.GetEnumInt()) if (answer == VisitTumorEvaluation.PD.GetEnumInt())
{ {
answer = _userInfo.IsEn_Us ? "Yes" : "是"; answer = isEn_us ? "Yes" : "是";
} }
else else
{ {
answer = _userInfo.IsEn_Us ? "No" : "否"; answer = isEn_us ? "No" : "否";
} }
break; break;
@@ -1537,14 +1551,23 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
.WhereIf(inQuery.IsReturnRequired != null, t => t.IsReturnRequired == inQuery.IsReturnRequired) .WhereIf(inQuery.IsReturnRequired != null, t => t.IsReturnRequired == inQuery.IsReturnRequired)
.WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable) .WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable)
.WhereIf(inQuery.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == inQuery.IsDistinguishCriteria) .WhereIf(inQuery.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == inQuery.IsDistinguishCriteria)
.WhereIf(inQuery.IsDistinguishCriteria == true && trialConfig.IsEnrollementQualificationConfirm == true && trialConfig.IsPDProgressView == false, t => t.IsDistinguishCriteria == true && t.BusinessScenarioEnum == EmailBusinessScenario.EnrollConfirmed)
.WhereIf(inQuery.IsDistinguishCriteria == true && trialConfig.IsEnrollementQualificationConfirm == false && trialConfig.IsPDProgressView == true, t => t.IsDistinguishCriteria == true && t.BusinessScenarioEnum == EmailBusinessScenario.PDConfirmed)
.WhereIf(inQuery.IsDistinguishCriteria == true && trialConfig.IsEnrollementQualificationConfirm == true && trialConfig.IsPDProgressView == true, t => t.IsDistinguishCriteria == true)
.WhereIf(inQuery.IsDistinguishCriteria == true && trialConfig.IsEnrollementQualificationConfirm == false && trialConfig.IsPDProgressView == false, t => t.IsDistinguishCriteria == true && (t.BusinessScenarioEnum != EmailBusinessScenario.EnrollConfirmed && t.BusinessScenarioEnum != EmailBusinessScenario.PDConfirmed))
.WhereIf(inQuery.BusinessModuleEnum != null, t => t.BusinessModuleEnum == inQuery.BusinessModuleEnum) .WhereIf(inQuery.BusinessModuleEnum != null, t => t.BusinessModuleEnum == inQuery.BusinessModuleEnum)
.WhereIf(inQuery.EmailUrgentEnum != null, t => t.EmailUrgentEnum == inQuery.EmailUrgentEnum) .WhereIf(inQuery.EmailUrgentEnum != null, t => t.EmailUrgentEnum == inQuery.EmailUrgentEnum)
.WhereIf(inQuery.ToUserType != null, t => t.EmailNoticeUserTypeList.Any(t => t.UserType == inQuery.ToUserType && t.EmailUserType == EmailUserType.To)) .WhereIf(inQuery.ToUserType != null, t => t.EmailNoticeUserTypeList.Any(t => t.UserType == inQuery.ToUserType && t.EmailUserType == EmailUserType.To))
.WhereIf(inQuery.CopyUserType != null, t => t.EmailNoticeUserTypeList.Any(t => t.UserType == inQuery.CopyUserType && t.EmailUserType == EmailUserType.Copy)) .WhereIf(inQuery.CopyUserType != null, t => t.EmailNoticeUserTypeList.Any(t => t.UserType == inQuery.CopyUserType && t.EmailUserType == EmailUserType.Copy))
.WhereIf(trialConfig.IsEnrollementQualificationConfirm == false, t => t.BusinessModuleEnum != BusinessModule.EligibilityVerification)
.WhereIf(trialConfig.IsPDProgressView == false, t => t.BusinessModuleEnum != BusinessModule.PDVerification) .WhereIf(trialConfig.IsEnrollementQualificationConfirm == false && trialConfig.IsPDProgressView == true, t => t.BusinessModuleEnum != BusinessModule.EligibilityVerification)
.WhereIf(trialConfig.IsEnrollementQualificationConfirm == true && trialConfig.IsPDProgressView == false, t => t.BusinessModuleEnum != BusinessModule.PDVerification)
.WhereIf(trialConfig.IsPDProgressView == false && trialConfig.IsEnrollementQualificationConfirm == false, t => t.BusinessModuleEnum != BusinessModule.PDVerification .WhereIf(trialConfig.IsPDProgressView == false && trialConfig.IsEnrollementQualificationConfirm == false, t => t.BusinessModuleEnum != BusinessModule.PDVerification
&& t.BusinessModuleEnum != BusinessModule.EligibilityVerification) && t.BusinessModuleEnum != BusinessModule.EligibilityVerification && t.BusinessModuleEnum != BusinessModule.Eligibility_PDVerification)
.ProjectTo<TrialSelectEmailNoticeConfigView>(_mapper.ConfigurationProvider, new { trialId = inQuery.TrialId }); .ProjectTo<TrialSelectEmailNoticeConfigView>(_mapper.ConfigurationProvider, new { trialId = inQuery.TrialId });
return await emailNoticeConfigQueryable.ToPagedListAsync(inQuery); return await emailNoticeConfigQueryable.ToPagedListAsync(inQuery);
@@ -105,7 +105,7 @@
public string Reviewer { get; set; } = String.Empty; public string Reviewer { get; set; } = String.Empty;
public DateTime BeginMonth { get; set; } public DateTime BeginMonth { get; set; }
public DateTime EndMonth { get; set; } public DateTime EndMonth { get; set; }
public int? Nation { get; set; } public DoctorNation? Nation { get; set; }
} }
public class MonthlyPaymentDTO public class MonthlyPaymentDTO
{ {
@@ -59,7 +59,7 @@
{ {
public DateTime StatisticsDate { get; set; } public DateTime StatisticsDate { get; set; }
public string KeyWord { get; set; } = String.Empty; public string KeyWord { get; set; } = String.Empty;
public int? Nation { get; set; } public DoctorNation? Nation { get; set; }
} }
public class MonthlyPaymentDetailQuery public class MonthlyPaymentDetailQuery
@@ -162,7 +162,7 @@
public DateTime BeginDate { get; set; } public DateTime BeginDate { get; set; }
public DateTime EndDate { get; set; } public DateTime EndDate { get; set; }
public int? Nation { get; set; } public DoctorNation? Nation { get; set; }
} }
public class TrialAnalysisQueryDTO public class TrialAnalysisQueryDTO
@@ -749,6 +749,17 @@ namespace IRaCIS.Core.Application.Contracts
public long? FileSize { get; set; } public long? FileSize { get; set; }
} }
public class DownloadFileDto
{
public Guid Id { get; set; }
public string Path { get; set; }
public string FileName { get; set; }
public string FileType { get; set; }
}
public class DownloadNoneDicomStudyDto public class DownloadNoneDicomStudyDto
{ {
public string Modality { get; set; } public string Modality { get; set; }
@@ -776,6 +787,9 @@ namespace IRaCIS.Core.Application.Contracts
public List<Guid> DicomStudyIdList { get; set; } public List<Guid> DicomStudyIdList { get; set; }
public List<Guid> NoneDicomStudyIdList { get; set; } public List<Guid> NoneDicomStudyIdList { get; set; }
// true 导出阅片,null 就是所有影像
public bool? IsExportReading { get; set; }
} }
public class IRReadingDownloadQuery : SortInput public class IRReadingDownloadQuery : SortInput
@@ -846,9 +860,13 @@ namespace IRaCIS.Core.Application.Contracts
public List<TrialKeyPicturePath> QuestionMarkPictureList { get; set; } public List<TrialKeyPicturePath> QuestionMarkPictureList { get; set; }
public List<TrialKeyPicturePath> TableQuestionRowPictureList { get; set; } public List<TrialKeyPicturePath> TableQuestionRowPictureList { get; set; }
public List<TrialKeyPicturePath> SegmentationFileList { get; set; }
} }
public class TrialKeyPicturePath public class TrialKeyPicturePath
{ {
public string SegmentationName { get; set; }
public string PicturePath { get; set; } public string PicturePath { get; set; }
public string OtherPicturePath { get; set; } public string OtherPicturePath { get; set; }
@@ -1157,6 +1175,20 @@ namespace IRaCIS.Core.Application.Contracts
public List<MaskRegion> MaskRegionList { get; set; } public List<MaskRegion> MaskRegionList { get; set; }
}
public class NoneDicomStudyMaskImageCommand
{
public Guid? NodicomStudyId { get; set; }
public List<Guid>? NoneDicomStudyFileIdList { get; set; }
public List<MaskRegion> MaskRegionList { get; set; }
}
public class NoneDicomStudyUndoMaskImageCommand
{
public Guid? NodicomStudyId { get; set; }
public List<Guid>? NoneDicomStudyFileIdList { get; set; }
} }
public class StudyUndoMaskImageCommand public class StudyUndoMaskImageCommand
@@ -1,31 +1,18 @@
using DocumentFormat.OpenXml.EMMA; using FellowOakDicom;
using FellowOakDicom;
using FellowOakDicom.Media;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using MassTransit; using MassTransit;
using MassTransit.Initializers; using MassTransit.Initializers;
using MathNet.Numerics;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NetTopologySuite.Mathematics;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using System.Data; using System.Data;
using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq;
using System.Text; using System.Text;
using System.Web; using System.Web;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application.Service.ImageAndDoc namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
@@ -71,8 +58,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
//subject 随机阅片 或者无序 有上传 才处理任务编号 //subject 随机阅片 或者无序 有上传 才处理任务编号
if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId &&
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom || (t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageDownloadEnum != ReadingImageDownload.None)))) //||(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageDownloadEnum != ReadingImageDownload.None)
)))
{ {
//找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务 //找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
@@ -131,6 +119,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var subjectCode = string.Empty; var subjectCode = string.Empty;
var subjectId = inQuery.SubjectId; var subjectId = inQuery.SubjectId;
bool? isIRImageDownloaded = true;
if(inQuery.VisitTaskId != null)
{
//isIRImageDownloaded= _visitTaskRepository.Where(t => t.Id == inQuery.VisitTaskId).Select(t => t.IsIRImageDownloaded).FirstOrDefault();
}
if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random) if (criterionInfo.IsReadingTaskViewInOrder == ReadingOrder.Random)
{ {
@@ -224,7 +218,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var SVlist = await querySV.ToListAsync(); var SVlist = await querySV.ToListAsync();
return ResponseOutput.Ok(SVlist, new { TrialModality = criterionInfo.Modalitys }); return ResponseOutput.Ok(SVlist, new { TrialModality = criterionInfo.Modalitys, IsReadingTaskViewInOrder = criterionInfo.IsReadingTaskViewInOrder });
} }
else else
@@ -234,7 +228,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed
&& t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect) /* && t.DoctorUserId == _userInfo.UserRoleId*/ && t.TaskState == TaskState.Effect)
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查 //满足 有序,或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.Select(u => new SubjectImageUploadDTO() .Select(u => new SubjectImageUploadDTO()
@@ -337,7 +331,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
} }
return ResponseOutput.Ok(list, new { TrialModality = criterionInfo.Modalitys }); return ResponseOutput.Ok(list, new { TrialModality = criterionInfo.Modalitys, IsReadingTaskViewInOrder = criterionInfo.IsReadingTaskViewInOrder, IsIRImageDownloaded= isIRImageDownloaded });
} }
@@ -397,9 +391,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}; };
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true); //var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
return ResponseOutput.Ok(addEntity.Id); return ResponseOutput.Ok(Guid.NewGuid());
} }
@@ -586,25 +580,25 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var trialId = incommand.TrialId; var trialId = incommand.TrialId;
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId); //var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId);
studyMonitor.UploadFinishedTime = DateTime.Now; //studyMonitor.UploadFinishedTime = DateTime.Now;
studyMonitor.ArchiveFinishedTime = DateTime.Now; //studyMonitor.ArchiveFinishedTime = DateTime.Now;
studyMonitor.FailedFileCount = incommand.FailedFileCount; //studyMonitor.FailedFileCount = incommand.FailedFileCount;
studyMonitor.IsSuccess = incommand.FailedFileCount == 0; //studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
studyMonitor.RecordPath = incommand.RecordPath; //studyMonitor.RecordPath = incommand.RecordPath;
studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize); //studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize);
var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString()); var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString(), visiTaskId.ToString());
var findStudy = await _taskStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); var findStudy = await _taskStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
studyMonitor.StudyId = studyId; //studyMonitor.StudyId = studyId;
studyMonitor.StudyCode = findStudy?.StudyCode ?? ""; //studyMonitor.StudyCode = findStudy?.StudyCode ?? "";
studyMonitor.IsDicomReUpload = findStudy != null; //studyMonitor.IsDicomReUpload = findStudy != null;
//上传 //上传
if (studyMonitor.IsDicomReUpload == false) if (findStudy == null)
{ {
@@ -646,7 +640,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
await _taskStudyRepository.AddAsync(study); await _taskStudyRepository.AddAsync(study);
studyMonitor.StudyCode = study.StudyCode; //studyMonitor.StudyCode = study.StudyCode;
foreach (var seriesItem in incommand.Study.SeriesList) foreach (var seriesItem in incommand.Study.SeriesList)
@@ -695,9 +689,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//重传的时候也要赋值检查Id ////重传的时候也要赋值检查Id
studyMonitor.StudyId = findStudy.Id; //studyMonitor.StudyId = findStudy.Id;
studyMonitor.StudyCode = findStudy.StudyCode; //studyMonitor.StudyCode = findStudy.StudyCode;
//特殊处理逻辑 //特殊处理逻辑
findStudy.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(findStudy.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct()); findStudy.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(findStudy.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
@@ -714,9 +708,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId); TaskSeries dicomSeries = await _taskSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var isNewSeries = false;
//判断重复 //判断重复
if (dicomSeries == null) if (dicomSeries == null)
{ {
isNewSeries = true;
var series = _mapper.Map<TaskSeries>(seriesItem); var series = _mapper.Map<TaskSeries>(seriesItem);
series.Id = seriesId; series.Id = seriesId;
@@ -742,6 +739,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//找到该序列已经存在的instanceId //找到该序列已经存在的instanceId
var existInstanceIdList = _taskInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList(); var existInstanceIdList = _taskInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList();
foreach (var instanceItem in seriesItem.InstanceList) foreach (var instanceItem in seriesItem.InstanceList)
{ {
var insntance = _mapper.Map<TaskInstance>(instanceItem); var insntance = _mapper.Map<TaskInstance>(instanceItem);
@@ -761,9 +759,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
await _taskInstanceRepository.AddAsync(insntance); await _taskInstanceRepository.AddAsync(insntance);
if (isNewSeries == false)
{
dicomSeries.InstanceCount++; dicomSeries.InstanceCount++;
}
findStudy.InstanceCount++; findStudy.InstanceCount++;
} }
else
{
//更新,需要删除缓存,并更新路径
await _oSSService.DeleteFromPrefix(insntance.Path, true);
await _taskInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new TaskInstance() { Path = insntance.Path });
}
} }
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 // 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
@@ -911,6 +920,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var subjectCode = inQuery.SubjectCode; var subjectCode = inQuery.SubjectCode;
var subjectId = inQuery.SubjectId; var subjectId = inQuery.SubjectId;
var doctorUserId = _userInfo.UserRoleId; var doctorUserId = _userInfo.UserRoleId;
bool? isIRImageDownloaded = null;
if (inQuery.VisitTaskId != null) if (inQuery.VisitTaskId != null)
{ {
@@ -922,18 +932,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code, SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
SubjectId = t.SubjectId, SubjectId = t.SubjectId,
t.DoctorUserId, t.DoctorUserId,
t.IsAnalysisCreate t.IsAnalysisCreate,
t.IsIRImageDownloaded,
}).FirstNotNullAsync(); }).FirstNotNullAsync();
subjectId = taskInfo.SubjectId; subjectId = taskInfo.SubjectId;
subjectCode = taskInfo.SubjectCode; subjectCode = taskInfo.SubjectCode;
doctorUserId = (Guid)taskInfo.DoctorUserId!; doctorUserId = (Guid)taskInfo.DoctorUserId!;
isIRImageDownloaded = taskInfo.IsIRImageDownloaded;
} }
var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
.Select(t => new { t.IsImageFilter, t.CriterionType, t.TrialId, t.CriterionModalitys, t.IsReadingTaskViewInOrder }).FirstNotNullAsync(); .Select(t => new { t.IsImageFilter, t.CriterionType, t.TrialId, t.CriterionModalitys, t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
var config = await _subjectRepository.Where(t => t.Id == subjectId).Select(t => new { t.Trial.ImageFormatList, t.Trial.StudyNameList, t.Trial.IsShowStudyName }).FirstOrDefaultAsync(); var config = await _subjectRepository.Where(t => t.Id == subjectId).Select(t => new { t.Trial.ImageFormatList, t.Trial.StudyNameList, t.Trial.IsShowStudyName, IsIRImageDownloaded= isIRImageDownloaded }).FirstOrDefaultAsync();
//靶段标注上传,查看访视级别,上传绑定访视级别 //靶段标注上传,查看访视级别,上传绑定访视级别
@@ -1056,7 +1068,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
else else
{ {
var query = from u in _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId var query = from u in _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed && t.DoctorUserId == doctorUserId && t.TaskState == TaskState.Effect) && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed /*&& t.DoctorUserId == doctorUserId*/ && t.TaskState == TaskState.Effect)
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查 //满足 有序,或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == subjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|")) join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == subjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|"))
@@ -1141,6 +1153,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var isQueryDicom = inQuery.DicomStudyIdList.Count > 0; var isQueryDicom = inQuery.DicomStudyIdList.Count > 0;
var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0; var isQueryNoneDicom = inQuery.NoneDicomStudyIdList.Count > 0;
var isExportReading = inQuery.IsExportReading == true;
var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom); var imageType = (isQueryDicom && isQueryNoneDicom) ? ImageType.DicomAndNoneDicom : (isQueryDicom ? ImageType.Dicom : ImageType.NoneDicom);
var dirDic = new Dictionary<string, string>(); var dirDic = new Dictionary<string, string>();
@@ -1150,11 +1164,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//有传输语法值的导出 才生成DIR //有传输语法值的导出 才生成DIR
//if (_subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId).SelectMany(t => t.StudyList.SelectMany(t => t.InstanceList)).All(c => c.TransferSytaxUID != string.Empty)) //if (_subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId).SelectMany(t => t.StudyList.SelectMany(t => t.InstanceList)).All(c => c.TransferSytaxUID != string.Empty))
if (!_instanceRepository.Where(t => inQuery.SubjectVisitId == t.SubjectVisitId).Any(c => c.TransferSytaxUID == string.Empty)) if (!_instanceRepository.Where(t => isExportReading ? (t.IsReading && t.DicomSerie.IsReading) : true)
.Where(t => inQuery.SubjectVisitId == t.SubjectVisitId).Any(c => c.TransferSytaxUID == string.Empty))
{ {
var list = _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId).SelectMany(t => t.StudyList) var list = _subjectVisitRepository.Where(t => t.Id == inQuery.SubjectVisitId).SelectMany(t => t.StudyList)
.Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false) .Where(t => isQueryDicom ? inQuery.DicomStudyIdList.Contains(t.Id) : false)
.SelectMany(t => t.InstanceList) .SelectMany(t => t.InstanceList.Where(t => isExportReading ? (t.IsReading && t.DicomSerie.IsReading) : true))
.Select(t => new StudyDIRInfo() .Select(t => new StudyDIRInfo()
{ {
@@ -1235,11 +1250,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
StudyInstanceUid = u.StudyInstanceUid, StudyInstanceUid = u.StudyInstanceUid,
StudyDIRPath = u.StudyDIRPath, StudyDIRPath = u.StudyDIRPath,
SeriesList = u.SeriesList.Select(z => new DownloadDicomSeriesDto() SeriesList = u.SeriesList.Where(t => isExportReading ? t.IsReading : true).Select(z => new DownloadDicomSeriesDto()
{ {
Modality = z.Modality, Modality = z.Modality,
InstanceList = z.DicomInstanceList.Select(k => new DownloadDicomInstanceDto() InstanceList = z.DicomInstanceList.Where(t => isExportReading ? t.IsReading : true).Select(k => new DownloadDicomInstanceDto()
{ {
IsEncapsulated = k.IsEncapsulated, IsEncapsulated = k.IsEncapsulated,
InstanceId = k.Id, InstanceId = k.Id,
@@ -1251,7 +1266,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}).ToList(), }).ToList(),
NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isExportReading ? t.IsReading : true).Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false)
.Select(nd => new DownloadNoneDicomStudyDto() .Select(nd => new DownloadNoneDicomStudyDto()
{ {
@@ -1259,7 +1274,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
StudyCode = nd.StudyCode, StudyCode = nd.StudyCode,
ImageDate = nd.ImageDate, ImageDate = nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new DownloadNoneDicomFileDto() FileList = nd.NoneDicomFileList.Where(t => isExportReading ? t.IsReading : true).Select(file => new DownloadNoneDicomFileDto()
{ {
FileName = file.FileName, FileName = file.FileName,
Path = file.Path, Path = file.Path,
@@ -1884,10 +1899,15 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// </summary> /// </summary>
/// <param name="trialImageDownloadId"></param> /// <param name="trialImageDownloadId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<IResponseOutput> DownloadImageSuccess(Guid trialImageDownloadId) public async Task<IResponseOutput> DownloadImageSuccess(Guid trialImageDownloadId, Guid? visitTaskId)
{ {
await _trialImageDownloadRepository.UpdatePartialFromQueryAsync(t => t.Id == trialImageDownloadId, u => new TrialImageDownload() await _trialImageDownloadRepository.UpdatePartialFromQueryAsync(t => t.Id == trialImageDownloadId, u => new TrialImageDownload()
{ DownloadEndTime = DateTime.Now, IsSuccess = true }, true); { DownloadEndTime = DateTime.Now, IsSuccess = true }, true);
if (visitTaskId != null)
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == visitTaskId.Value, u => new VisitTask() { IsIRImageDownloaded = true });
}
return ResponseOutput.Ok(); return ResponseOutput.Ok();
} }
@@ -2014,7 +2034,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
public async Task<List<Guid?>> GetTrialUnreadVisitList(Guid trialId) public async Task<List<Guid?>> GetTrialUnreadVisitList(Guid trialId)
{ {
var subjectVisitList = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.SourceSubjectVisitId!=null).Select(t => t.SourceSubjectVisitId) var subjectVisitList = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.SourceSubjectVisitId != null).Select(t => t.SourceSubjectVisitId)
.Distinct().ToListAsync(); .Distinct().ToListAsync();
return subjectVisitList; return subjectVisitList;
@@ -2064,6 +2084,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
TableQuestionRowPictureList = t.LesionList.Select(c => new TrialKeyPicturePath { PicturePath = c.PicturePath, OtherPicturePath = c.OtherPicturePath }).ToList(), TableQuestionRowPictureList = t.LesionList.Select(c => new TrialKeyPicturePath { PicturePath = c.PicturePath, OtherPicturePath = c.OtherPicturePath }).ToList(),
SegmentationFileList = t.SegmentationList.Select(c => new TrialKeyPicturePath { PicturePath = c.SEGUrl, SegmentationName = c.SegmentationName, OtherPicturePath = string.Empty }).ToList(),
Id = t.Id, Id = t.Id,
//裁判选择结果 //裁判选择结果
JudgeResultTaskId = t.JudgeVisitTask.JudgeResultTaskId, JudgeResultTaskId = t.JudgeVisitTask.JudgeResultTaskId,
@@ -3,16 +3,12 @@
// 生成时间 2021-12-06 10:54:55 // 生成时间 2021-12-06 10:54:55
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using DocumentFormat.OpenXml.EMMA; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using static ImageHelper;
namespace IRaCIS.Core.Application.Contracts namespace IRaCIS.Core.Application.Contracts
{ {
@@ -25,11 +21,176 @@ namespace IRaCIS.Core.Application.Contracts
IRepository<Trial> _trialRepository, IRepository<Trial> _trialRepository,
IDistributedLockProvider _distributedLockProvider, IDistributedLockProvider _distributedLockProvider,
IRepository<SubjectVisit> _subjectVisitRepository, IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<VisitTask> _visitTaskRepository, IRepository<VisitTask> _visitTaskRepository, IOSSService _oSSService,
QCCommon _qCCommon, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, INoneDicomStudyService QCCommon _qCCommon, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, INoneDicomStudyService
{ {
/// <summary>
/// 标注遮盖影像 路径后面加了.MaskNoneDicom_ 就是遮盖的新路径
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> NoneDicomStudyMaskImage(NoneDicomStudyMaskImageCommand inCommand)
{
if (inCommand.NodicomStudyId == null && inCommand.NoneDicomStudyFileIdList == null)
{
return ResponseOutput.NotOk("NodicomStudyId and NoneDicomStudyFileIdList can not both be null");
}
var idPathList = new List<DownloadFileDto>();
if (inCommand.NodicomStudyId == null && inCommand.NoneDicomStudyFileIdList != null)
{
idPathList = await _noneDicomStudyFileRepository.Where(t => inCommand.NoneDicomStudyFileIdList.Contains(t.Id)).ProjectTo<DownloadFileDto>(_mapper.ConfigurationProvider).ToListAsync();
}
else
{
idPathList = await _noneDicomStudyFileRepository.Where(t => inCommand.NodicomStudyId == t.NoneDicomStudyId).ProjectTo<DownloadFileDto>(_mapper.ConfigurationProvider).ToListAsync();
}
var errorList = new List<DownloadFileDto>();
var okList = new List<DownloadFileDto>();
var batchId = Guid.NewGuid();
foreach (var item in idPathList)
{
var path = item.Path;
try
{
// 1. 下载文件
using var inputStream = new MemoryStream();
await (await _oSSService.GetStreamFromOSSAsync(path)).CopyToAsync(inputStream);
inputStream.Position = 0;
// 2. 处理图片
using var outputStream = new MemoryStream();
await ImageMaskHelper.MaskAsync(inputStream, outputStream, inCommand.MaskRegionList);
outputStream.Position = 0;
var prefix = path.Substring(1, path.LastIndexOf('/') - 1);
//每次都用一个新的名字
var maskFileName = string.Empty;
if (path.Contains(".MaskNoneDicom_"))
{
//清理缓存的里面的遮盖图,多次遮盖同一张图时,清除缓存很重要
await _oSSService.DeleteFromPrefix(path, true); //清理缓存的里面的遮盖图,多次遮盖同一张图时,清除缓存很重要
//本身就是遮盖的图,那么就要要替换guid
var length = Guid.Empty.ToString().Length + ".MaskNoneDicom_".Length;
var restorePath = item.Path[..^length];
maskFileName = $"{Path.GetFileName(restorePath)}.MaskNoneDicom_{batchId}";
}
else
{
//没有遮盖的,直接加上.批次_MaskDicom
maskFileName = $"{Path.GetFileName(path)}.MaskNoneDicom_{batchId}";
}
await _oSSService.UploadToOSSAsync(outputStream, prefix, maskFileName, false);
var newPath = $"/{prefix}/{maskFileName}";
okList.Add(new DownloadFileDto() { Id = item.Id, Path = newPath });
await _noneDicomStudyFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new NoneDicomStudyFile() { Path = newPath, IsMasked = true });
}
catch (Exception ex)
{
errorList.Add(new DownloadFileDto() { Id = item.Id, Path = path });
Log.Logger.Error(ex, $"NoneDicomStudyMaskImage Error for NoneDicomStudyFileIdList Path:{path} {ex.Message}");
}
}
await _noneDicomStudyFileRepository.SaveChangesAsync();
return ResponseOutput.Ok(new { OkList = okList, ErrorList = errorList });
}
/// <summary>
/// 撤销遮盖的影像,可以单张,也可以整个检查
/// </summary>
/// <param name="inCommand"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> NoneDicomStudyUndoMaskImage(NoneDicomStudyUndoMaskImageCommand inCommand)
{
if (inCommand.NodicomStudyId == null && inCommand.NoneDicomStudyFileIdList == null)
{
return ResponseOutput.NotOk("NodicomStudyId and NoneDicomStudyFileIdList can not both be null");
}
var idPathList = new List<DownloadFileDto>();
if (inCommand.NodicomStudyId == null && inCommand.NoneDicomStudyFileIdList != null)
{
idPathList = await _noneDicomStudyFileRepository.Where(t => inCommand.NoneDicomStudyFileIdList.Contains(t.Id)).ProjectTo<DownloadFileDto>(_mapper.ConfigurationProvider).ToListAsync();
}
else
{
idPathList = await _noneDicomStudyFileRepository.Where(t => inCommand.NodicomStudyId == t.NoneDicomStudyId).ProjectTo<DownloadFileDto>(_mapper.ConfigurationProvider).ToListAsync();
}
var okList = new List<DownloadFileDto>();
foreach (var item in idPathList)
{
if (item.Path.Contains(".MaskNoneDicom_"))
{
await _oSSService.DeleteFromPrefix(item.Path, true);
var length = Guid.Empty.ToString().Length + ".MaskNoneDicom_".Length;
var newPath = item.Path[..^length];
okList.Add(new DownloadFileDto() { Id = item.Id, Path = newPath });
await _noneDicomStudyFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new NoneDicomStudyFile() { Path = newPath, IsMasked = false });
}
//if (item.Path.EndsWith("."))
//{
// await _oSSService.DeleteFromPrefix(item.Path, true);
// var newPath = item.Path[..^1];
// okList.Add(new InstanceIdPath() { Id = item.Id, Path = newPath });
// await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { Path = newPath, IsMasked = false });
//}
}
await _noneDicomStudyFileRepository.SaveChangesAsync();
return ResponseOutput.Ok(new { OkList = okList });
}
[HttpGet] [HttpGet]
public async Task<IResponseOutput<List<NoneDicomStudyView>>> GetNoneDicomStudyList( public async Task<IResponseOutput<List<NoneDicomStudyView>>> GetNoneDicomStudyList(
@@ -1,25 +1,16 @@
using FellowOakDicom; using DocumentFormat.OpenXml.InkML;
using FellowOakDicom;
using FellowOakDicom.Imaging; using FellowOakDicom.Imaging;
using FellowOakDicom.IO.Buffer; using FellowOakDicom.IO.Buffer;
using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using MathNet.Numerics;
using Medallion.Threading; using Medallion.Threading;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using NetTopologySuite.Algorithm;
using SharpCompress.Common;
using SkiaSharp;
using System.Data; using System.Data;
using System.Drawing;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application.Service.ImageAndDoc namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
@@ -77,14 +68,114 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
#endregion #endregion
} }
public class DeleteImagePathCommand
{
public string Path { get; set; }
}
public async Task<IResponseOutput> DeleteImageCache(DeleteImagePathCommand incommand)
{
await _oSSService.DeleteFromPrefix(incommand.Path, true);
return ResponseOutput.Ok();
}
public async Task<IResponseOutput> GetAnonymizeInfo(Guid visitTaskId, Guid? subjectVisitId)
{
Guid svId = Guid.Empty;
if (subjectVisitId != null)
{
svId = subjectVisitId.Value;
}
else
{
svId = (Guid)_visitTaskRepository.Where(t => t.Id == visitTaskId).Select(t => t.SourceSubjectVisitId).FirstOrDefault();
}
// 写入dicom 固定的信息,以及组织路径的信息 以及匿名化的信息
var otherData = GetSaveToDicomInfo(svId);
var anonymizeList = _fusionCache.GetOrSetAsync(CacheKeys.SystemAnonymization, _ => CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7)).Result;
return ResponseOutput.Ok(new
{
DicomStoreInfo = otherData,
AnonymizeFixedList = anonymizeList.Where(t => t.IsFixed).ToList(),
AnonymizeNotFixedList = anonymizeList.Where(t => t.IsFixed == false).ToList()
});
}
public async Task<IResponseOutput> UpdateModality(Guid seriesId, string modality, bool isCRCReplace,
[FromServices] IRepository<TaskSeries> _taskSeriesRepository,
[FromServices] IRepository<TaskStudy> _taskStudyRepository
)
{
if (isCRCReplace)
{
await _dicomSeriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new DicomSeries() { Modality = modality });
var studyId = _dicomSeriesRepository.Where(t => t.Id == seriesId).Select(t => t.StudyId).FirstOrDefault();
//处理Modality
var seriesModalityList = _dicomStudyRepository.Where(t => t.Id == studyId).SelectMany(u => u.SeriesList.Select(t => t.Modality)).Distinct();
string ModaliyStr = string.Join('、', seriesModalityList.ToList());
await _dicomStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == studyId, u => new DicomStudy() { Modalities = ModaliyStr });
}
else
{
await _taskSeriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new TaskSeries() { Modality = modality });
var studyId = _taskSeriesRepository.Where(t => t.Id == seriesId).Select(t => t.StudyId).FirstOrDefault();
//处理Modality
var seriesModalityList = _taskStudyRepository.Where(t => t.Id == studyId).SelectMany(u => u.SeriesList.Select(t => t.Modality)).Distinct();
string ModaliyStr = string.Join('、', seriesModalityList.ToList());
await _taskStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == studyId, u => new TaskStudy() { Modalities = ModaliyStr });
}
return ResponseOutput.Ok();
}
private static async Task<bool> TryWriteMergedDicomAsync(Func<Task<Stream>> sourceFactory, Stream output) private static async Task<bool> TryWriteMergedDicomAsync(Func<Task<Stream>> sourceFactory, Stream output)
{ {
try try
{ {
#region
//await using var source = await sourceFactory();
//// 如果你是从 stream 打开
//var dicomFile = await DicomFile.OpenAsync(source);
#endregion
#region
await using var source = await sourceFactory(); await using var source = await sourceFactory();
// 【关键修复】将 OSS 流缓冲到 MemoryStream
using var bufferedStream = new MemoryStream();
if (source.CanSeek)
{
source.Position = 0;
}
else
{
// 完全复制到内存流
await source.CopyToAsync(bufferedStream);
bufferedStream.Position = 0; // 重置位置
}
// 如果你是从 stream 打开 // 如果你是从 stream 打开
var dicomFile = await DicomFile.OpenAsync(source); var dicomFile = await DicomFile.OpenAsync(source.CanSeek ? source : bufferedStream);
#endregion
//获取像素是否为封装形式 //获取像素是否为封装形式
var syntax = dicomFile.Dataset.InternalTransferSyntax; var syntax = dicomFile.Dataset.InternalTransferSyntax;
@@ -104,11 +195,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data)); newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
} }
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData); //var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
var originOffsetTable = frag?.OffsetTable; //var originOffsetTable = frag?.OffsetTable;
newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray()); //newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// 替换原有的片段序列 // 替换原有的片段序列
dicomFile.Dataset.AddOrUpdate(newFragments); dicomFile.Dataset.AddOrUpdate(newFragments);
} }
@@ -565,9 +656,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}; };
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true); //var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
return ResponseOutput.Ok(addEntity.Id); return ResponseOutput.Ok(Guid.NewGuid());
} }
@@ -628,20 +719,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
var trialId = incommand.TrialId; var trialId = incommand.TrialId;
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId); //var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == incommand.StudyMonitorId);
studyMonitor.UploadFinishedTime = DateTime.Now; //studyMonitor.UploadFinishedTime = DateTime.Now;
studyMonitor.ArchiveFinishedTime = DateTime.Now; //studyMonitor.ArchiveFinishedTime = DateTime.Now;
studyMonitor.FailedFileCount = incommand.FailedFileCount; //studyMonitor.FailedFileCount = incommand.FailedFileCount;
studyMonitor.IsSuccess = incommand.FailedFileCount == 0; //studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
studyMonitor.RecordPath = incommand.RecordPath; //studyMonitor.RecordPath = incommand.RecordPath;
studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize); //studyMonitor.FileSize = incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Sum(t => t.FileSize);
var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString()); var studyId = IdentifierHelper.CreateGuid(incommand.Study.StudyInstanceUid, incommand.TrialId.ToString());
var findStudy = await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId); var findStudy = await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
studyMonitor.StudyId = studyId; //studyMonitor.StudyId = studyId;
studyMonitor.StudyCode = findStudy?.StudyCode ?? ""; //studyMonitor.StudyCode = findStudy?.StudyCode ?? "";
studyMonitor.IsDicomReUpload = findStudy != null; //studyMonitor.IsDicomReUpload = findStudy != null;
if (incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Count() == 0) if (incommand.Study.SeriesList.SelectMany(t => t.InstanceList).Count() == 0)
@@ -652,7 +743,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
} }
//上传 //上传
if (studyMonitor.IsDicomReUpload == false) if ((findStudy != null) == false)
{ {
var addStudy = _mapper.Map<DicomStudy>(incommand.Study); var addStudy = _mapper.Map<DicomStudy>(incommand.Study);
@@ -697,7 +788,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
studyMonitor.StudyCode = addStudy.StudyCode; //studyMonitor.StudyCode = addStudy.StudyCode;
foreach (var seriesItem in incommand.Study.SeriesList) foreach (var seriesItem in incommand.Study.SeriesList)
@@ -756,9 +847,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId); DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var isNewSeries = false;
//判断重复 //判断重复
if (dicomSeries == null) if (dicomSeries == null)
{ {
isNewSeries = true;
var series = _mapper.Map<DicomSeries>(seriesItem); var series = _mapper.Map<DicomSeries>(seriesItem);
series.Id = seriesId; series.Id = seriesId;
@@ -774,16 +870,23 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//新的序列 那么 检查的序列数量+1 //新的序列 那么 检查的序列数量+1
findStudy.SeriesCount += 1; findStudy.SeriesCount += 1;
} }
else //else
{ //{
//该序列掉了instance // //该序列掉了instance
dicomSeries.InstanceCount += seriesItem.InstanceList.Count; // dicomSeries.InstanceCount += seriesItem.InstanceList.Count;
} //}
//找到该序列已经存在的instanceId
var existInstanceIdList = _dicomInstanceRepository.Where(t => t.SeriesId == dicomSeries.Id).Select(t => t.Id).ToList();
foreach (var instanceItem in seriesItem.InstanceList) foreach (var instanceItem in seriesItem.InstanceList)
{ {
var insntance = _mapper.Map<DicomInstance>(instanceItem); var insntance = _mapper.Map<DicomInstance>(instanceItem);
insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString()); insntance.Id = IdentifierHelper.CreateGuid(insntance.StudyInstanceUid, insntance.SeriesInstanceUid, insntance.SopInstanceUid, trialId.ToString());
if (!existInstanceIdList.Any(t => t == insntance.Id))
{
insntance.StudyId = findStudy.Id; insntance.StudyId = findStudy.Id;
insntance.SeriesId = dicomSeries.Id; insntance.SeriesId = dicomSeries.Id;
@@ -792,11 +895,28 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
insntance.SubjectVisitId = incommand.SubjectVisitId; insntance.SubjectVisitId = incommand.SubjectVisitId;
await _dicomInstanceRepository.AddAsync(insntance); await _dicomInstanceRepository.AddAsync(insntance);
if (isNewSeries == false)
{
dicomSeries.InstanceCount++;
}
findStudy.InstanceCount++;
}
else
{
//更新,需要删除缓存,并更新路径
await _oSSService.DeleteFromPrefix(insntance.Path, true);
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == insntance.Id, u => new DicomInstance() { Path = insntance.Path });
}
} }
// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加 //// 不管是新的序列 还是 该序列 掉了Instance 重传的时候 检查的instance 数量都会增加
findStudy.InstanceCount += seriesItem.InstanceList.Count; //findStudy.InstanceCount += seriesItem.InstanceList.Count;
if (incommand.Study.RadionuclideTotalDose != string.Empty if (incommand.Study.RadionuclideTotalDose != string.Empty
@@ -4,6 +4,7 @@
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -13,7 +14,7 @@ namespace IRaCIS.Core.Application.Service
/// SystemAnonymizationService /// SystemAnonymizationService
/// </summary> /// </summary>
[ApiExplorerSettings(GroupName = "Image")] [ApiExplorerSettings(GroupName = "Image")]
public class SystemAnonymizationService(IRepository<SystemAnonymization> _systemAnonymizationRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ISystemAnonymizationService public class SystemAnonymizationService(IRepository<SystemAnonymization> _systemAnonymizationRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ISystemAnonymizationService
{ {
@@ -37,6 +38,7 @@ namespace IRaCIS.Core.Application.Service
var entity = await _systemAnonymizationRepository.InsertOrUpdateAsync(addOrEditSystemAnonymization, true); var entity = await _systemAnonymizationRepository.InsertOrUpdateAsync(addOrEditSystemAnonymization, true);
await _fusionCache.SetAsync(CacheKeys.SystemAnonymization, CacheHelper.GetSystemAnonymizationListAsync(_systemAnonymizationRepository), TimeSpan.FromDays(7));
return ResponseOutput.Ok(entity.Id.ToString()); return ResponseOutput.Ok(entity.Id.ToString());
@@ -189,6 +189,11 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.InstanceId, u => u.MapFrom(s => s.Id)); .ForMember(d => d.InstanceId, u => u.MapFrom(s => s.Id));
CreateMap<NoneDicomStudyFile, DownloadFileDto>();
} }
} }
@@ -449,6 +449,12 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
public List<GetTrialShowInspectionOutDto> Children { get; set; } public List<GetTrialShowInspectionOutDto> Children { get; set; }
} }
public class InspectionDto
{
public Guid Id { get; set; }
public string? JsonDetail { get; set; }
}
public class SetTrialShowInspection public class SetTrialShowInspection
{ {
@@ -27,6 +27,39 @@ namespace IRaCIS.Core.Application.Service.Inspection
IRepository<FrontAuditConfig> _frontAuditConfigRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IInspectionService IRepository<FrontAuditConfig> _frontAuditConfigRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IInspectionService
{ {
/// <summary>
/// 根据Id获取稽查记录
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> getInspectionById(InspectionDto inDto)
{
var dataInspection = await _dataInspectionRepository.Where(x=>x.Id==inDto.Id).Select(x=> new InspectionDto()
{
Id=x.Id,
JsonDetail = x.JsonDetail,
}).FirstOrDefaultAsync();
return ResponseOutput.Ok(dataInspection);
}
/// <summary>
/// 设置稽查记录JsonDetail
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetJsonDetail(InspectionDto inDto)
{
await _dataInspectionRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.Id, u => new DataInspection() { JsonDetail = inDto.JsonDetail });
return ResponseOutput.Ok(inDto);
}
/// <summary> /// <summary>
/// 设置项目稽查配置 /// 设置项目稽查配置
/// </summary> /// </summary>
@@ -127,9 +160,9 @@ namespace IRaCIS.Core.Application.Service.Inspection
join trialSign in _trialSignRepository.Where().IgnoreQueryFilters() on data.SignId equals trialSign.Id into trialSigntemp join trialSign in _trialSignRepository.Where().IgnoreQueryFilters() on data.SignId equals trialSign.Id into trialSigntemp
from lefttrialSign in trialSigntemp.DefaultIfEmpty() from lefttrialSign in trialSigntemp.DefaultIfEmpty()
join leftfrontAuditConfig in _frontAuditConfigRepository.Where().Where(x => x.ConfigType == "M" && x.Identification != null && x.IsEnable == true) on join leftfrontAuditConfig in _frontAuditConfigRepository.Where().Where(x => x.ConfigType == "M" && x.Identification != null && x.IsEnable == true) on
data.Identification.ToLower() data.Identification
equals equals
leftfrontAuditConfig.Identification.ToLower() leftfrontAuditConfig.Identification
join moduleTypec in _dictionaryRepository.Where() on new { ModuleType = leftfrontAuditConfig.ModuleTypeId!.Value } equals new { ModuleType = moduleTypec.Id } into moduleTypectemp join moduleTypec in _dictionaryRepository.Where() on new { ModuleType = leftfrontAuditConfig.ModuleTypeId!.Value } equals new { ModuleType = moduleTypec.Id } into moduleTypectemp
from leftmoduleTypec in moduleTypectemp.DefaultIfEmpty() from leftmoduleTypec in moduleTypectemp.DefaultIfEmpty()
join OptTypec in _dictionaryRepository.Where() on new { ModuleType = leftfrontAuditConfig.OptTypeId!.Value } equals new { ModuleType = OptTypec.Id } into optTypetemp join OptTypec in _dictionaryRepository.Where() on new { ModuleType = leftfrontAuditConfig.OptTypeId!.Value } equals new { ModuleType = OptTypec.Id } into optTypetemp
@@ -103,6 +103,8 @@ namespace IRaCIS.Application.Contracts
public bool IsZhiZhun { get; set; } public bool IsZhiZhun { get; set; }
public bool IsFirstAdd { get; set; } public bool IsFirstAdd { get; set; }
public bool IsNeedResetPwd { get; set; }
public bool NeedChangePassWord { get; set; } = false; public bool NeedChangePassWord { get; set; } = false;
@@ -207,7 +209,7 @@ namespace IRaCIS.Application.Contracts
public bool IsTestUser { get; set; } public bool IsTestUser { get; set; }
public UserWorkLanguage UserWorkLanguage { get; set; }
} }
/// <summary> /// <summary>
@@ -338,6 +340,8 @@ namespace IRaCIS.Application.Contracts
public Guid? AuditRecordId { get; set; } public Guid? AuditRecordId { get; set; }
public bool? IsAuditRecordUserSelect { get; set; } public bool? IsAuditRecordUserSelect { get; set; }
public UserWorkLanguage? UserWorkLanguage { get; set; }
} }
public class UserRoleInfoDTO public class UserRoleInfoDTO

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