Compare commits

..

416 Commits

Author SHA1 Message Date
he 431d2e7a97 修改密码验证
continuous-integration/drone/push Build is passing
2024-10-09 15:12:06 +08:00
he 7caac94d97 验证密码
continuous-integration/drone/push Build is passing
2024-10-09 15:02:22 +08:00
hang ceedafb6b9 修改映射配置
continuous-integration/drone/push Build is passing
2024-10-09 13:29:11 +08:00
hang 04e7cd5463 屏蔽mssql连接
continuous-integration/drone/push Build is failing
2024-10-09 13:01:30 +08:00
hang ba37700812 去掉aws 获取token
continuous-integration/drone/push Build is failing
2024-10-09 12:57:45 +08:00
he cdadad9ec5 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 failing
2024-10-09 10:27:19 +08:00
he 795e128ef9 代码修改 2024-10-09 10:27:17 +08:00
hang 658f9c7c40 1、阅片跟踪表
continuous-integration/drone/push Build is passing
2、接收记录表
3、接收影像检查表
4、下载记录表
2024-10-08 11:38:37 +08:00
hang 5bce1cafa3 修改lili 配置文件
continuous-integration/drone/push Build is passing
2024-10-08 10:46:10 +08:00
hang f539496f9f 切换nuget包所在 项目
continuous-integration/drone/push Build is passing
2024-10-08 08:55:24 +08:00
hang fac077d2b7 增加备注
continuous-integration/drone/push Build is passing
2024-10-07 21:27:44 +08:00
hang 874c8718b1 TestMasstransitMeditor
continuous-integration/drone/push Build is passing
2024-10-04 17:54:55 +08:00
he fea009bf0c 修改
continuous-integration/drone/push Build is passing
2024-09-30 13:30:48 +08:00
he 5ae837ac19 修改验证
continuous-integration/drone/push Build is passing
2024-09-30 12:47:43 +08:00
he eb55fafbc3 修改
continuous-integration/drone/push Build is failing
2024-09-30 11:55:44 +08:00
he 88893c9825 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
2024-09-30 11:52:50 +08:00
he c6a18aa18a 修改 2024-09-30 11:52:47 +08:00
hang 8829723c19 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-30 10:21:36 +08:00
hang 8768fe0437 上传列表 返回阅片任务状态,已阅片的不允许删除 2024-09-30 10:21:36 +08:00
he cb7098830c 修改
continuous-integration/drone/push Build is passing
2024-09-29 18:12:46 +08:00
he c69c139e00 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
2024-09-29 17:44:59 +08:00
he acb7e798e0 修改 2024-09-29 17:44:58 +08:00
hang 63d7bd5607 修改后处理影像筛选
continuous-integration/drone/push Build is passing
2024-09-29 16:39:34 +08:00
hang 99e3610be6 scp 增加注册 AddMediator
continuous-integration/drone/push Build is passing
2024-09-29 15:39:10 +08:00
hang 50712aefc6 修改bm 导航属性配置遗漏
continuous-integration/drone/push Build is passing
2024-09-29 15:00:10 +08:00
hang d5d728fea6 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-29 14:19:56 +08:00
hang 9e71732061 修改scp 2024-09-29 14:19:54 +08:00
he c24adcd09c 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
2024-09-29 13:59:21 +08:00
he 0da842871c 修改 2024-09-29 13:59:20 +08:00
hang 03702477d6 修改发布版本
continuous-integration/drone/push Build is running
2024-09-29 13:57:41 +08:00
hang e4a36f4689 修改codefirst 迁移文件名 2024-09-29 10:45:09 +08:00
hang cb6271daef Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-29 10:38:42 +08:00
hang 11fa028cd4 修改字段 2024-09-29 10:38:40 +08:00
he 5a1a710d5a 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
2024-09-29 10:21:29 +08:00
he e9e4b45823 修改 2024-09-29 10:21:28 +08:00
hang 7693c72802 MasstransitMeditor 不在efcore 同一个事务
continuous-integration/drone/push Build is passing
2024-09-28 21:21:52 +08:00
hang 1bacc222be 增加返回项目modality
continuous-integration/drone/push Build is passing
2024-09-27 18:06:05 +08:00
hang c5355e976f Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-27 17:42:38 +08:00
hang 95a84bb330 更新后处理上传的检查modality 2024-09-27 17:42:37 +08:00
he 6a60e4696b 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
2024-09-27 17:23:11 +08:00
he 7ff77554ff 修改 2024-09-27 17:23:10 +08:00
hang ba23950cd5 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2024-09-27 17:22:52 +08:00
hang 8ec2c676f1 构造函数去掉获取token 2024-09-27 17:22:51 +08:00
he b183622e13 修改
continuous-integration/drone/push Build is passing
2024-09-27 17:14:48 +08:00
he cd9f7f8812 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
2024-09-27 17:12:34 +08:00
he 513d773be3 修改 2024-09-27 17:12:34 +08:00
hang cf24583974 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2024-09-27 17:11:54 +08:00
hang f5fbf96772 oss 获取token方法改为同步测试 2024-09-27 17:11:53 +08:00
he 8dc2301184 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
2024-09-27 17:11:08 +08:00
he 7e135367b2 修改 2024-09-27 17:11:07 +08:00
hang 8626a6b453 修改触发
continuous-integration/drone/push Build is passing
2024-09-27 16:53:28 +08:00
hang 870dda49dd Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-27 16:16:09 +08:00
hang 171b8bac34 原始影像检查过滤 2024-09-27 16:16:09 +08:00
he 7c19ecc3f4 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
2024-09-27 15:16:05 +08:00
he 3e375ea6d1 修改 2024-09-27 15:16:04 +08:00
hang 416a94e302 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-27 15:11:50 +08:00
hang 7760b0736e Trigger 修改分类整理 2024-09-27 15:11:49 +08:00
he aba7dfdec9 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
2024-09-27 14:45:56 +08:00
he 1dabadfba4 修改 2024-09-27 14:45:55 +08:00
hang b8f5f32596 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-27 13:58:34 +08:00
hang b6459d2f9f 整理trigger 到不同的文件夹 2024-09-27 13:58:33 +08:00
he dded4f2d7c 代码修改
continuous-integration/drone/push Build is passing
2024-09-27 13:24:34 +08:00
he fadb7a9d0e 修改
continuous-integration/drone/push Build is passing
2024-09-27 13:08:04 +08:00
he 55f261b080 修改
continuous-integration/drone/push Build is passing
2024-09-27 13:06:16 +08:00
he ccf154e5e5 修改
continuous-integration/drone/push Build is passing
2024-09-27 11:43:37 +08:00
he 069ee25d18 修改
continuous-integration/drone/push Build is passing
2024-09-27 10:59:29 +08:00
he 64fd39ceb4 修改
continuous-integration/drone/push Build is passing
2024-09-27 10:52:21 +08:00
he 19cf8c7559 修改
continuous-integration/drone/push Build is passing
2024-09-27 10:42:25 +08:00
he 3c0199cebd 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
2024-09-27 10:37:45 +08:00
he 62965e5aa5 修改 2024-09-27 10:37:44 +08:00
hang 654fb7116b 修改bug
continuous-integration/drone/push Build is passing
2024-09-27 10:24:54 +08:00
hang da6746beea 影响筛选过滤
continuous-integration/drone/push Build is passing
2024-09-27 10:12:29 +08:00
hang 2461646d5f MassTransit Command 测试预备代码
continuous-integration/drone/push Build is passing
2024-09-27 09:54:16 +08:00
hang 02db483119 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-26 17:34:22 +08:00
hang b5e756ffa3 领域事件预备测试 2024-09-26 17:34:21 +08:00
he f3c29d3530 修改
continuous-integration/drone/push Build is passing
2024-09-26 17:29:01 +08:00
he f2d9c6fe38 修改
continuous-integration/drone/push Build is passing
2024-09-26 17:22:04 +08:00
he 0d4d984135 修改
continuous-integration/drone/push Build is passing
2024-09-26 17:13:27 +08:00
he f9c155a378 修改
continuous-integration/drone/push Build is passing
2024-09-26 15:05:32 +08:00
he a9a67c1db2 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
2024-09-26 15:03:01 +08:00
he 3d6d64175b 修改 2024-09-26 15:03:01 +08:00
hang 45c74694f2 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-26 14:22:05 +08:00
hang 033c47435f DateOnly 的使用,以及解耦数据库 2024-09-26 14:22:04 +08:00
he ea48967492 修改
continuous-integration/drone/push Build is passing
2024-09-26 13:57:34 +08:00
he 8ec35d90fb 修改
continuous-integration/drone/push Build is passing
2024-09-26 13:49:39 +08:00
he 53f3bb5d6d 修改
continuous-integration/drone/push Build is passing
2024-09-26 13:31:47 +08:00
he e6628e952f 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
2024-09-26 13:27:48 +08:00
he 1b26ed1b65 修改 2024-09-26 13:27:47 +08:00
hang d0018a3ec3 处理SeqId 是主键,但是Id是虚拟主键,显示配置导航属性,解决codefirst 迁移问题
continuous-integration/drone/push Build is passing
2024-09-26 13:22:11 +08:00
hang a423c7c73a 增加显示导航属性
continuous-integration/drone/push Build is passing
2024-09-26 11:41:31 +08:00
hang 8eacc969ed Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-26 11:29:12 +08:00
hang 33b02be6ed 增加dicom 显示文件大小,以及修改影像下载列表适配 随机阅片 2024-09-26 11:29:11 +08:00
he 9834335767 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
2024-09-26 10:47:03 +08:00
he d4d5ed0d9a 修改 2024-09-26 10:47:02 +08:00
hang 3fc7b72a45 显示标注seqId 导致后处理上传问题
continuous-integration/drone/push Build is passing
2024-09-26 10:39:47 +08:00
hang e525965d89 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-26 10:26:35 +08:00
hang af988e7276 修改影像key 显示标注 2024-09-26 10:26:34 +08:00
he 627f3bf4a9 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
2024-09-26 10:20:20 +08:00
he aca261ace2 导入修改 2024-09-26 10:20:18 +08:00
hang 328a8549c6 同步长度
continuous-integration/drone/push Build is passing
2024-09-26 00:15:08 +08:00
hang ff71e925ca 修改查询参数
continuous-integration/drone/push Build is passing
2024-09-25 17:34:57 +08:00
hang f46bbea98e 受试者随机随机排序修改
continuous-integration/drone/push Build is passing
2024-09-25 17:10:01 +08:00
hang 1d5c274e38 修改参数必传与否
continuous-integration/drone/push Build is passing
2024-09-25 16:47:50 +08:00
hang e32195c322 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-25 15:49:45 +08:00
hang 935b498ab5 修改上传验证 2024-09-25 15:49:43 +08:00
he 21925f6d88 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
2024-09-25 15:39:33 +08:00
he 54b75dd3d5 修改 2024-09-25 15:39:33 +08:00
hang 7ed54e3be3 修改上传列表限制
continuous-integration/drone/push Build is passing
2024-09-25 15:17:49 +08:00
hang 3a3184a5ac Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-25 15:06:26 +08:00
hang 41153e42d6 本地swagger 拦截排除 2024-09-25 15:06:26 +08:00
he 3ca9be0a29 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
2024-09-25 14:48:21 +08:00
he 6c5f669ab6 修改 2024-09-25 14:48:20 +08:00
hang 282ba96c61 修改冲突
continuous-integration/drone/push Build is running
2024-09-25 14:47:20 +08:00
hang fe80604331 修改长度 2024-09-25 14:45:11 +08:00
he 19fdd02429 修改
continuous-integration/drone/push Build is passing
2024-09-25 14:11:01 +08:00
he c2f72d677f 修改
continuous-integration/drone/push Build is passing
2024-09-25 14:06:29 +08:00
he 6713fff0e7 修改
continuous-integration/drone/push Build is passing
2024-09-25 13:44:41 +08:00
he ff8fa94341 修改
continuous-integration/drone/push Build is running
2024-09-25 13:44:16 +08:00
he 82f2185825 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
2024-09-25 13:12:24 +08:00
he 5fdf9e0606 导入修改 2024-09-25 13:12:22 +08:00
hang cf9823c682 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-25 10:59:42 +08:00
hang 73e7ed11b1 整理字段长度,迁移准备工作完毕 2024-09-25 10:59:40 +08:00
he 9adab8cef1 修改
continuous-integration/drone/push Build is passing
2024-09-25 10:44:40 +08:00
he 3d382635cc 代码修改
continuous-integration/drone/push Build is passing
2024-09-25 10:34:20 +08:00
he e389c1e581 计算修改
continuous-integration/drone/push Build is passing
2024-09-25 10:19:34 +08:00
he 1a3ebe1fc4 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
2024-09-25 09:44:20 +08:00
he fb6f12903e 代码修改 2024-09-25 09:44:19 +08:00
hang 1da4fbe23b 实体标注,修改默认长度
continuous-integration/drone/push Build is passing
2024-09-24 17:57:45 +08:00
hang 4d206ebf9d Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-24 16:42:29 +08:00
hang 9c4ada3e66 修改报错 2024-09-24 16:42:28 +08:00
he 0bc0421ee3 修改
continuous-integration/drone/push Build is passing
2024-09-24 15:09:09 +08:00
he a79aebe772 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
2024-09-24 14:59:06 +08:00
he d3ff114b6d 导入完成 2024-09-24 14:59:05 +08:00
hang 50a45e2260 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-24 14:31:15 +08:00
hang 8090668650 重阅任务排除 2024-09-24 14:31:13 +08:00
he d27b4af793 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
2024-09-24 14:14:50 +08:00
he b097ca1db3 导入代码修改 2024-09-24 14:14:49 +08:00
hang 609742c914 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-24 14:12:27 +08:00
hang 79d76dcbaf 修改验证接口 2024-09-24 14:12:26 +08:00
he 721ab8dfd3 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
2024-09-24 13:39:27 +08:00
he b2d90005f8 代码修改 2024-09-24 13:39:26 +08:00
hang c58d880e28 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-24 13:14:19 +08:00
hang 183fc6143f 国际化修改 2024-09-24 13:14:18 +08:00
he 9a71e1fa0f 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
2024-09-24 13:08:16 +08:00
he 5977ab34e9 代码修改 2024-09-24 13:08:15 +08:00
hang c71b58e0e9 后处理访视
continuous-integration/drone/push Build is passing
2024-09-24 11:25:08 +08:00
hang 1fcb871de2 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-23 18:01:47 +08:00
hang d7a76bc110 移动加密方法,测试值转换器ok 2024-09-23 18:01:46 +08:00
he 78b76da7ed 修改
continuous-integration/drone/push Build is passing
2024-09-23 16:46:41 +08:00
he a6c04d8fbb 修改
continuous-integration/drone/push Build is running
2024-09-23 16:45:40 +08:00
he 303cb54e7a 导出模板
continuous-integration/drone/push Build is passing
2024-09-23 16:15:51 +08:00
he 92e1a3f90b 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
2024-09-23 15:20:08 +08:00
he 8c51ae350c IVUS计算 2024-09-23 15:20:07 +08:00
hang 91fa8e75e1 发布日志 增加lili 版本
continuous-integration/drone/push Build is passing
2024-09-23 13:33:30 +08:00
hang 893bdaf0f2 修改过滤器
continuous-integration/drone/push Build is passing
2024-09-23 11:16:46 +08:00
hang 7051e68c09 修改部分字段更新bug
continuous-integration/drone/push Build is passing
2024-09-23 10:50:11 +08:00
hang e9bb71f5c9 同步数据库备注到实体
continuous-integration/drone/push Build is passing
2024-09-20 22:45:48 +08:00
hang 3ee0c2ccc7 整理数据库实体备注
continuous-integration/drone/push Build is passing
2024-09-20 21:42:18 +08:00
hang 40c8a51a31 整理数据库实体备注
continuous-integration/drone/push Build is passing
2024-09-20 18:20:37 +08:00
hang d3e3ed79ba 退出登录,让token 过期
continuous-integration/drone/push Build is passing
2024-09-20 16:54:06 +08:00
hang 83d3a547d1 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-20 16:35:59 +08:00
hang 3d428af85b 监控列表 增加字段 2024-09-20 16:35:59 +08:00
he c5b8743064 修改
continuous-integration/drone/push Build is passing
2024-09-20 15:14:18 +08:00
he 69d390da81 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
2024-09-20 14:59:46 +08:00
he ae0f601727 合并 2024-09-20 14:59:45 +08:00
hang d509bc1649 登录的bug
continuous-integration/drone/push Build is running
2024-09-20 14:58:08 +08:00
he 23ffe2b143 修改 2024-09-20 14:56:24 +08:00
hang 718ddefe97 批量处理实体类空行
continuous-integration/drone/push Build is passing
2024-09-20 14:34:32 +08:00
hang 7524d39213 清理实体类备注
continuous-integration/drone/push Build is passing
2024-09-20 14:18:16 +08:00
hang 7e705ccf37 pacs 确认了才能启动项目
continuous-integration/drone/push Build is passing
2024-09-20 14:02:16 +08:00
hang 7fc2de5eb3 清理检查字段
continuous-integration/drone/push Build is passing
2024-09-20 13:49:37 +08:00
hang b90f5f2d85 清理后端下载
continuous-integration/drone/push Build is passing
2024-09-20 11:47:02 +08:00
hang 97b28fd920 修改入组附件
continuous-integration/drone/push Build is passing
2024-09-20 11:07:26 +08:00
hang 3bdd5af113 修改医生实体模型
continuous-integration/drone/push Build is passing
2024-09-20 10:55:02 +08:00
hang 6dcfbb8717 修改时间问题
continuous-integration/drone/push Build is passing
2024-09-20 10:44:56 +08:00
hang 103d4b42a3 整理命名空间
continuous-integration/drone/push Build is passing
2024-09-20 10:35:35 +08:00
hang fc30cb39ee 增加Global Using
continuous-integration/drone/push Build is passing
2024-09-20 10:19:08 +08:00
hang 115017197b 删除废弃字段
continuous-integration/drone/push Build is passing
2024-09-20 09:32:42 +08:00
hang 32931e155c GlobalUsings 清理实体层
continuous-integration/drone/push Build is passing
2024-09-20 09:20:04 +08:00
hang 0a1ce59670 整理命名空间
continuous-integration/drone/push Build is passing
2024-09-20 00:00:13 +08:00
hang 42e4fe59ec 同步数据模型和数据库对应关系2
continuous-integration/drone/push Build is passing
2024-09-19 23:45:43 +08:00
hang 19f4385055 同步数据模型和数据库对应关系1
continuous-integration/drone/push Build is passing
2024-09-19 21:56:36 +08:00
hang d789c48004 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-19 18:01:09 +08:00
hang 32427f0f0c 修改实体模型 2024-09-19 18:01:08 +08:00
he 01ade2d62f 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
2024-09-19 17:48:54 +08:00
he cec038fb92 修改 2024-09-19 17:48:52 +08:00
hang b5d117f6fa 稽查实体给默认值
continuous-integration/drone/push Build is passing
2024-09-19 17:01:03 +08:00
hang b98df9dae8 优化数据库表
continuous-integration/drone/push Build is passing
2024-09-19 16:40:17 +08:00
hang 4e7ce826c8 清理邮件配置字段
continuous-integration/drone/push Build is passing
2024-09-19 13:59:00 +08:00
hang 7df247d5e7 删除字典废弃字段
continuous-integration/drone/push Build is passing
2024-09-19 13:24:56 +08:00
hang fb067534e7 加密解密测试代码完成
continuous-integration/drone/push Build is passing
2024-09-19 11:45:23 +08:00
hang de274e00d6 加密解密组件准备完毕
continuous-integration/drone/push Build is passing
2024-09-18 21:18:33 +08:00
hang 3501f2acdf 加解密预备
continuous-integration/drone/push Build is passing
2024-09-18 18:03:23 +08:00
hang 2dd86652f3 修改下载信息列表,返回标准信息
continuous-integration/drone/push Build is passing
2024-09-18 16:36:59 +08:00
hang bf39613789 登录接口返回公司信息
continuous-integration/drone/push Build is passing
2024-09-18 16:05:29 +08:00
hang a64cec987d codefirst 测试完毕
continuous-integration/drone/push Build is passing
2024-09-18 14:51:20 +08:00
hang 5b2b5fead9 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-18 10:43:11 +08:00
hang 0216665d5b 删除数据库模型,同时清理视图模型bug
continuous-integration/drone/push Build is passing
2024-09-18 10:30:01 +08:00
hang f1fadebfba 修改阅片期编辑
continuous-integration/drone/push Build is passing
2024-09-18 10:23:40 +08:00
hang 19b647fb4a 修改迁移配置以及测试
continuous-integration/drone/push Build is passing
2024-09-17 23:16:11 +08:00
hang 65e47d9918 decimal 精度解决
continuous-integration/drone/push Build is passing
2024-09-17 18:53:56 +08:00
hang ab68a63bdd 增加codefirst迁移配置
continuous-integration/drone/push Build is passing
2024-09-17 14:26:12 +08:00
hang 5990477fdc guid 生成修改
continuous-integration/drone/push Build is passing
2024-09-17 12:26:18 +08:00
hang 961ca49f76 整理仓储
continuous-integration/drone/push Build is running
2024-09-17 12:24:51 +08:00
hang 581e412106 修改代码模板
continuous-integration/drone/push Build is passing
2024-09-17 10:13:23 +08:00
hang 3813158b00 修改oss 配置
continuous-integration/drone/push Build is passing
2024-09-14 17:41:15 +08:00
hang 010fdf6e2c 修改排序bug
continuous-integration/drone/push Build is passing
2024-09-14 16:27:16 +08:00
hang f7c669a7d7 修改scp 服务配置文件
continuous-integration/drone/push Build is failing
2024-09-14 14:44:56 +08:00
hang 68dc09d969 修改中心调研
continuous-integration/drone/push Build is passing
2024-09-14 14:38:15 +08:00
hang a6a6765d9b x
continuous-integration/drone/push Build is passing
2024-09-14 14:13:03 +08:00
hang 5931a67825 修改中心调研bug
continuous-integration/drone/push Build is passing
2024-09-14 14:10:58 +08:00
hang f26441719f 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-14 13:51:47 +08:00
hang 67a930a208 修改配置文件
continuous-integration/drone/push Build is running
2024-09-14 13:50:47 +08:00
hang f189f9f361 修改s3 配置文件
continuous-integration/drone/push Build is passing
2024-09-14 13:46:48 +08:00
hang b6d0791f18 修改影像筛选过滤
continuous-integration/drone/push Build is passing
2024-09-14 13:35:10 +08:00
hang 7285a9d672 修改映射测试
continuous-integration/drone/push Build is passing
2024-09-14 13:16:15 +08:00
hang c3daa75e0e 修改阅片bug
continuous-integration/drone/push Build is passing
2024-09-14 13:13:52 +08:00
hang 564ac4d931 修改编译错误
continuous-integration/drone/push Build is passing
2024-09-14 12:37:47 +08:00
hang e065e44ab0 修改默认值给“”
continuous-integration/drone/push Build is passing
2024-09-14 12:33:37 +08:00
hang bbc737811a 解决截图不显示问题
continuous-integration/drone/push Build is passing
2024-09-14 11:41:53 +08:00
hang d507e625c6 字符串默认值问题
continuous-integration/drone/push Build is passing
2024-09-14 11:18:11 +08:00
hang e997cb2a8f 修改api bug
continuous-integration/drone/push Build is passing
2024-09-14 11:14:10 +08:00
hang bfa2d8afce 增加tiralSiteId
continuous-integration/drone/push Build is passing
2024-09-14 11:05:02 +08:00
hang 3840627ce7 修改scp 服务
continuous-integration/drone/push Build is passing
2024-09-14 10:49:50 +08:00
hang 8fed969bec 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-14 10:36:17 +08:00
hang d50091ed6b 修改文档bug
continuous-integration/drone/push Build is passing
2024-09-14 10:24:17 +08:00
hang 86864ae575 编译错误
continuous-integration/drone/push Build is passing
2024-09-14 09:47:13 +08:00
hang 0fdcc7c56e 修改对接bug
continuous-integration/drone/push Build is passing
2024-09-14 09:45:29 +08:00
hang 849f48db25 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-14 09:19:18 +08:00
hang b31821848d 修改scp 服务配置文件 2024-09-14 09:19:16 +08:00
hang e5be375308 自定义生成实体的模型,长度200的不标注,nvarcharmax 标注 MaxLength 其他长度标注StringLength
continuous-integration/drone/push Build is passing
2024-09-13 21:45:42 +08:00
hang 095db5786b 增加映射
continuous-integration/drone/push Build is passing
2024-09-13 17:54:55 +08:00
hang dcfe28d950 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-13 17:51:02 +08:00
hang f9f3a1422f aws bug
continuous-integration/drone/push Build is passing
2024-09-13 17:38:49 +08:00
hang 8dcd1f2f56 修改scp 配置
continuous-integration/drone/push Build is passing
2024-09-13 16:01:50 +08:00
hang 7d39bf43fe 缓存bug
continuous-integration/drone/push Build is passing
2024-09-13 15:10:11 +08:00
hang 8b8b52e0cc 修改配置
continuous-integration/drone/push Build is passing
2024-09-13 14:45:26 +08:00
hang 0cdc489278 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-13 14:38:32 +08:00
hang d4cef1148b 修改oss 各个环境配置
continuous-integration/drone/push Build is passing
2024-09-13 11:47:05 +08:00
hang 40d4806f22 修改配置文件
continuous-integration/drone/push Build is passing
2024-09-13 11:08:46 +08:00
hang 48427f2740 修改临时凭证
continuous-integration/drone/push Build is passing
2024-09-13 10:44:34 +08:00
hang a3296a1ab9 清理oss 数据
continuous-integration/drone/push Build is passing
2024-09-13 10:06:36 +08:00
hang 7404fabcda 修改列表排序
continuous-integration/drone/push Build is passing
2024-09-13 09:40:24 +08:00
hang 29842f484b 修改影像上传
continuous-integration/drone/push Build is passing
2024-09-13 09:28:37 +08:00
hang daac69c0d1 修改组间一致性分析
continuous-integration/drone/push Build is passing
2024-09-13 09:16:30 +08:00
hang 603f6e095c 修改测试迁移
continuous-integration/drone/push Build is passing
2024-09-12 23:51:51 +08:00
he c9b1e5f92a 修改
continuous-integration/drone/push Build is passing
2024-09-12 17:31:33 +08:00
he 6fd9bd94df 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
2024-09-12 17:07:48 +08:00
he fd6673c339 修改 2024-09-12 17:07:47 +08:00
hang 6fe4aa60d4 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-12 16:09:39 +08:00
hang df1665307a 修改上传逻辑 2024-09-12 16:09:37 +08:00
he 1ccb31fcf2 修改
continuous-integration/drone/push Build is passing
2024-09-12 16:04:24 +08:00
he 55f98d735e 修改
continuous-integration/drone/push Build is passing
2024-09-12 15:38:49 +08:00
he 4642e4e00e 修改
continuous-integration/drone/push Build is passing
2024-09-12 15:31:51 +08:00
he c6d74309f4 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
2024-09-12 15:27:06 +08:00
he 2abada285b 签名时间 2024-09-12 15:27:05 +08:00
hang d600862fb0 修改上传监控
continuous-integration/drone/push Build is passing
2024-09-12 14:00:50 +08:00
hang 4048be622f 修复映射bug
continuous-integration/drone/push Build is passing
2024-09-12 11:12:06 +08:00
hang eec0156fe7 参数名错误
continuous-integration/drone/push Build is passing
2024-09-12 10:22:43 +08:00
hang 85d1930730 修改导航属性bug
continuous-integration/drone/push Build is passing
2024-09-12 10:13:39 +08:00
hang 7420fdeda5 返回用户类型枚举
continuous-integration/drone/push Build is passing
2024-09-12 09:40:51 +08:00
he 4e2eb7b0a0 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
2024-09-12 09:32:13 +08:00
he 68e87a6c0e 修改 2024-09-12 09:32:12 +08:00
hang 19f9af8af8 返回IP
continuous-integration/drone/push Build is running
2024-09-12 09:31:18 +08:00
he 34faaaf231 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
2024-09-12 09:20:05 +08:00
he 136a9e54ca 修改 2024-09-12 09:20:04 +08:00
hang 5b63e58c1d 修改导入表格bug
continuous-integration/drone/push Build is passing
2024-09-12 09:08:05 +08:00
hang 70c381831d 测试迁移移除外键
continuous-integration/drone/push Build is passing
2024-09-11 23:53:58 +08:00
hang 2bf562d027 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-11 17:39:40 +08:00
hang c7e3403cae 修改dicom 上传为0 提示 2024-09-11 17:39:39 +08:00
he 2f41c21f75 修改
continuous-integration/drone/push Build is passing
2024-09-11 16:53:10 +08:00
he 1688392216 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
2024-09-11 16:37:31 +08:00
he 6a1a56f0bc 序号修改 2024-09-11 16:37:30 +08:00
hang 0f495a4568 下载提交事务
continuous-integration/drone/push Build is passing
2024-09-11 16:21:36 +08:00
hang 81abcf39fc 修改查询条件
continuous-integration/drone/push Build is passing
2024-09-11 16:11:45 +08:00
hang 247b11cec4 修改影像监控查询条件
continuous-integration/drone/push Build is passing
2024-09-11 15:46:48 +08:00
hang 21ded0d466 优化导航属性
continuous-integration/drone/push Build is passing
2024-09-11 15:40:22 +08:00
hang 36c354c8f0 增加下载监控接口
continuous-integration/drone/push Build is passing
2024-09-11 14:41:04 +08:00
hang cb6f93ec0a 删除qc 废弃的字段
continuous-integration/drone/push Build is passing
2024-09-11 09:57:39 +08:00
hang da8812868c Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-11 09:22:33 +08:00
hang 14ec78a2fd 删除历史sql 2024-09-11 09:22:32 +08:00
he eccb5dc562 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
2024-09-11 09:08:08 +08:00
he c11ff02a82 受试者随机阅片问题修改 2024-09-11 09:08:06 +08:00
hang b9b095a19c 一致性分析任务,下载列表优化
continuous-integration/drone/push Build is passing
2024-09-11 08:58:52 +08:00
hang 8678c3602f 优化导航属性
continuous-integration/drone/push Build is passing
2024-09-10 23:59:18 +08:00
hang 510a35e2b4 移动自身一对多关系到同一个文件,方便理解
continuous-integration/drone/push Build is passing
2024-09-10 23:38:39 +08:00
hang 5e1ec1ffb2 维护导航属性,重命名字段
continuous-integration/drone/push Build is passing
2024-09-10 23:30:51 +08:00
hang 3f38cf25c5 发布复位
continuous-integration/drone/push Build is passing
2024-09-10 21:08:40 +08:00
hang b32225b8bb 修改阅片器bug
continuous-integration/drone/push Build is passing
2024-09-10 21:05:59 +08:00
hang ecbc27fbb8 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
2024-09-10 20:28:52 +08:00
hang d3f13e844d 修改备注 2024-09-10 20:28:51 +08:00
hang 405454f71f 修改一致性分析 下载影像bug
continuous-integration/drone/push Build is passing
2024-09-10 18:46:00 +08:00
hang f7dd5117a0 修改医学审核bug
continuous-integration/drone/push Build is passing
2024-09-10 18:08:23 +08:00
hang 60330fbd93 修改反馈bug
continuous-integration/drone/push Build is failing
2024-09-10 17:54:20 +08:00
hang 6b7542b11f 修改阅片页面非dicom 检查看后处理
continuous-integration/drone/push Build is passing
2024-09-10 17:44:36 +08:00
hang e012384dfa 修改参数名
continuous-integration/drone/push Build is passing
2024-09-10 17:27:25 +08:00
hang 2aa63a6132 修改影像后处理nonedicom 切换问题
continuous-integration/drone/push Build is passing
2024-09-10 17:11:43 +08:00
hang e12935d9aa Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-10 16:58:42 +08:00
hang 21cb074469 修改迁移配置 2024-09-10 16:58:41 +08:00
he 204cb19d96 修改
continuous-integration/drone/push Build is passing
2024-09-10 16:16:03 +08:00
he 238fde7d01 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
2024-09-10 15:25:29 +08:00
he b59b46f938 还是过滤zip 2024-09-10 15:25:28 +08:00
hang 0fbfe6c0e1 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-10 15:13:02 +08:00
hang 31e2aa24b8 修改uat配置 2024-09-10 15:13:00 +08:00
he 5b52a3e67f 修改
continuous-integration/drone/push Build is running
2024-09-10 15:12:08 +08:00
he bb5844a8e8 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
2024-09-10 15:05:17 +08:00
he bc5956ed66 修改 2024-09-10 15:05:17 +08:00
hang 624d89563c 影像筛选过滤
continuous-integration/drone/push Build is passing
2024-09-10 14:40:48 +08:00
hang f6bcff7e13 后处理非dicom检查bug
continuous-integration/drone/push Build is passing
2024-09-10 14:25:25 +08:00
hang 36acbc1df8 修改参数名错误
continuous-integration/drone/push Build is passing
2024-09-10 13:50:35 +08:00
hang ca9ce6e4c5 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-10 13:29:42 +08:00
hang 08edc735e9 修改后处理上传验证 2024-09-10 13:29:37 +08:00
he 5b420a453b 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
2024-09-10 10:16:26 +08:00
he 6a6411dfb8 修改 2024-09-10 10:16:25 +08:00
hang 360bcd6bfe 字典测试生成枚举
continuous-integration/drone/push Build is passing
2024-09-09 18:05:59 +08:00
hang 16107dc8a9 受试者随机,重阅后,不重新编号
continuous-integration/drone/push Build is passing
2024-09-09 17:35:08 +08:00
hang 578281b707 修改上传缓存验证
continuous-integration/drone/push Build is passing
2024-09-09 17:28:21 +08:00
hang 3730d955dd 修改缓存key
continuous-integration/drone/push Build is passing
2024-09-09 17:06:37 +08:00
hang 3dbf329a31 修改下载过滤
continuous-integration/drone/push Build is passing
2024-09-09 16:36:29 +08:00
hang afa2b50951 修改筛选bug
continuous-integration/drone/push Build is passing
2024-09-09 15:55:08 +08:00
hang b219e4a055 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-09 15:21:09 +08:00
hang 6e38f3f3df 修改影像筛选 2024-09-09 15:21:07 +08:00
he 34370a36af 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
2024-09-09 15:09:43 +08:00
he 1dfb27f08e 标准的默认值修改 2024-09-09 15:09:43 +08:00
hang 3bf616667e 修改备注
continuous-integration/drone/push Build is running
2024-09-09 15:08:27 +08:00
hang 15a3fd17df Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-09 14:58:55 +08:00
hang 092a9c2dc6 后端上传也用临时token 2024-09-09 14:58:54 +08:00
he 6e1bf8265f 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
2024-09-09 14:48:14 +08:00
he d4389e5c35 修改 2024-09-09 14:48:13 +08:00
hang d30b1853de TrialReadingCriterionName 映射修改
continuous-integration/drone/push Build is passing
2024-09-09 13:36:09 +08:00
hang 532d7d155b Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2024-09-09 13:34:23 +08:00
hang 9cff6b9c87 返回标准名字 2024-09-09 13:34:21 +08:00
he e5f8b3dc71 修改
continuous-integration/drone/push Build is passing
2024-09-09 13:20:14 +08:00
he 8ac2de3434 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
2024-09-09 11:48:53 +08:00
he 74501c3584 修改 2024-09-09 11:48:53 +08:00
hang 757ccc3eb6 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2024-09-09 11:48:16 +08:00
hang 36fb3f2d53 修改下载接口 2024-09-09 11:48:14 +08:00
he 8092b0680b 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
2024-09-09 11:39:01 +08:00
he 42de7737cb 计算修改 2024-09-09 11:39:00 +08:00
hang 273d2a4b88 修改阅片接口默认值
continuous-integration/drone/push Build is passing
2024-09-09 10:51:14 +08:00
hang fe4b48f4bc 修改模板名称
continuous-integration/drone/push Build is passing
2024-09-09 09:31:03 +08:00
hang 444d3c3a59 删除不必要的提示
continuous-integration/drone/push Build is passing
2024-09-09 09:09:23 +08:00
hang c8596c6815 移除旧的模板
continuous-integration/drone/push Build is passing
2024-09-09 09:01:27 +08:00
hang e2dd4b2466 自动生成最终版本
continuous-integration/drone/push Build is passing
2024-09-09 00:37:20 +08:00
hang 429ca4dd6d 修改临时模板
continuous-integration/drone/push Build is passing
2024-09-09 00:07:17 +08:00
hang 55e0624dc6 模板准备完毕,剩下如何适配生成以后自动生成视图模型和service
continuous-integration/drone/push Build is passing
2024-09-08 21:42:13 +08:00
hang fff6ef5fe2 优化基础配置和模板
continuous-integration/drone/push Build is passing
2024-09-08 21:08:48 +08:00
hang 2127c47d00 T4模板生成的属性 按照顺序排序
continuous-integration/drone/push Build is passing
2024-09-08 18:57:36 +08:00
hang 564477b728 修改官方t4模板,适配我们自己的程序
continuous-integration/drone/push Build is passing
2024-09-08 17:39:47 +08:00
hang c7e80401e1 删除无用的导航属性
continuous-integration/drone/push Build is passing
2024-09-07 14:52:37 +08:00
hang 7fee1abdb5 字符串默认值+数据库统一维护
continuous-integration/drone/push Build is passing
2024-09-07 11:29:30 +08:00
hang 243fae4b19 默认值遗漏
continuous-integration/drone/push Build is passing
2024-09-07 00:46:08 +08:00
hang 6e2a58c3d7 给字符串增加默认值空
continuous-integration/drone/push Build is passing
2024-09-07 00:19:33 +08:00
hang 2d864de128 非dicom 数量问题
continuous-integration/drone/push Build is passing
2024-09-06 20:44:35 +08:00
hang bee09217a2 x
continuous-integration/drone/push Build is passing
2024-09-06 20:16:35 +08:00
hang bd0e039e7a Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 20:05:56 +08:00
hang f1423fba4f 移除废弃的html模板 2024-09-06 20:05:53 +08:00
he c439e1bb42 修改
continuous-integration/drone/push Build is passing
2024-09-06 16:31:15 +08:00
he 6a17c2a9a8 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
2024-09-06 16:14:26 +08:00
he 0b987f937d 修改 2024-09-06 16:14:25 +08:00
hang cd62a8741a Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 15:47:13 +08:00
hang 67a8f10b03 裁判任务不展示 上传下载功能 2024-09-06 15:47:13 +08:00
he 27749ec3cd 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
2024-09-06 14:58:02 +08:00
he 19220a1cbd 加测量值枚举 2024-09-06 14:58:01 +08:00
hang f4df76cccd Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 14:13:04 +08:00
hang 6c443ca089 重置为复杂密码 2024-09-06 14:13:03 +08:00
he 68be1d8583 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
2024-09-06 13:51:48 +08:00
he a965cf429f 修改 2024-09-06 13:51:48 +08:00
hang c1c5add001 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 13:23:46 +08:00
hang a8049f2a60 dicom 影像后处理预览接口 2024-09-06 13:23:45 +08:00
he 9d01b557ce 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
2024-09-06 13:05:03 +08:00
he 89b3bc94a2 修改 2024-09-06 13:05:03 +08:00
hang 7a7fde5fc0 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 11:41:51 +08:00
hang 632712cfee 非dicom 任务后上传 2024-09-06 11:41:50 +08:00
he 98be30449f 修改
continuous-integration/drone/push Build is running
2024-09-06 11:41:27 +08:00
he a7db67adb6 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
2024-09-06 11:31:22 +08:00
he c6fdae8879 计算修改 2024-09-06 11:31:21 +08:00
hang f925f8969a Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-06 10:29:40 +08:00
hang f1601e7017 增加验证接口 2024-09-06 10:29:37 +08:00
he caf5946b9e 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
2024-09-06 09:22:08 +08:00
he 7dce99e045 关联任务修改 2024-09-06 09:22:06 +08:00
hang 0e59617691 整理模板
continuous-integration/drone/push Build is passing
2024-09-05 23:35:57 +08:00
hang f0f688a1a3 除了数据库实体模型,其余模板准备ok
continuous-integration/drone/push Build is passing
2024-09-05 23:26:23 +08:00
hang 753941204f 增加视图模板
continuous-integration/drone/push Build is passing
2024-09-05 18:05:26 +08:00
hang 6fd239cf70 访视bug
continuous-integration/drone/push Build is passing
2024-09-05 16:57:53 +08:00
hang a8f6594142 修改美国正式配置文件
continuous-integration/drone/push Build is passing
2024-09-05 15:51:30 +08:00
hang 0d5d5105ce Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-05 15:31:19 +08:00
hang c078d496be ir 上传后处理检查预览数据接口 2024-09-05 15:31:18 +08:00
he bceffcad6a 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
2024-09-05 14:34:14 +08:00
he ccbf1f0544 计算修改 2024-09-05 14:34:13 +08:00
hang e5a8a06bbb Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2024-09-05 14:32:34 +08:00
hang af1d85e65c 修改登录mfa nonedicom 、dbcontext 2024-09-05 14:32:33 +08:00
he 7ace6c3593 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
2024-09-05 14:28:25 +08:00
he b3e0cf8ec1 修改 2024-09-05 14:28:21 +08:00
hang 4f77d1bfb3 MFA 第二种情况
continuous-integration/drone/push Build is passing
2024-09-05 13:26:10 +08:00
hang 72e54fe0d9 非dicom 检查列表返回任务Id
continuous-integration/drone/push Build is passing
2024-09-05 11:27:29 +08:00
hang 735083999e 非dicom 检查列表返回文件信息,同时增加IR 上传文件绑定
continuous-integration/drone/push Build is passing
2024-09-05 11:05:49 +08:00
hang 006a5729d6 发布美国环境修改配置文件
continuous-integration/drone/push Build is passing
2024-09-05 09:58:25 +08:00
hang e4c3521b04 mfa 登录逻辑遗漏
continuous-integration/drone/push Build is passing
2024-09-05 09:27:04 +08:00
hang dd13eddfe3 测试数据库上下文
continuous-integration/drone/push Build is passing
2024-09-05 00:04:41 +08:00
hang 706cb888c8 模板增加放入的目录
continuous-integration/drone/push Build is passing
2024-09-04 23:36:19 +08:00
hang bfe5379206 新的生成模板引擎引入
continuous-integration/drone/push Build is passing
2024-09-04 23:21:22 +08:00
hang 2ffd1a2520 修改序列化报错
continuous-integration/drone/push Build is passing
2024-09-04 16:05:13 +08:00
hang 784e453eaa Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-04 15:58:29 +08:00
hang 084b3d8822 修改模板 2024-09-04 15:58:28 +08:00
he c03fd57c25 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
2024-09-04 15:35:08 +08:00
he 34d5f809ee 修改 2024-09-04 15:35:07 +08:00
hang fd0d91faa4 修改模板
continuous-integration/drone/push Build is passing
2024-09-04 14:53:18 +08:00
hang 2450602227 删除T4模板废弃的
continuous-integration/drone/push Build is passing
2024-09-04 14:44:47 +08:00
hang 48ea90ce97 修改统计过滤
continuous-integration/drone/push Build is passing
2024-09-04 14:13:29 +08:00
hang 640ebdb835 修改统计
continuous-integration/drone/push Build is passing
2024-09-04 14:06:31 +08:00
hang 5d59d729d7 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2024-09-04 13:47:38 +08:00
hang afadc5e2be oss 过期时间转为服务器时间,服务器统一转为客户端时区 2024-09-04 13:47:35 +08:00
he dc3c3f7557 修改
continuous-integration/drone/push Build is passing
2024-09-04 13:43:16 +08:00
he 61cbfe231d 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
2024-09-04 11:45:15 +08:00
he 9ee2dd477e 修改 2024-09-04 11:45:15 +08:00
739 changed files with 97403 additions and 35285 deletions
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
namespace IRaCIS.Application.Services.BusinessFilter namespace IRaCIS.Core.Application.Service.BusinessFilter
{ {
/// <summary> /// <summary>
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码 /// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
@@ -7,7 +7,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Application.Services; using IRaCIS.Core.Application.Service;
using AutoMapper; using AutoMapper;
using IRaCIS.Core.SCP.Service; using IRaCIS.Core.SCP.Service;
+4 -1
View File
@@ -7,8 +7,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" /> <PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="3.7.402.7" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.16" />
<PackageReference Include="DistributedLock.Core" Version="1.0.7" /> <PackageReference Include="DistributedLock.Core" Version="1.0.7" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" /> <PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
<PackageReference Include="fo-dicom" Version="5.1.3" /> <PackageReference Include="fo-dicom" Version="5.1.3" />
+5
View File
@@ -113,6 +113,11 @@ builder.Services.AddAutoMapper(automapper =>
//EF ORM QueryWithNoLock //EF ORM QueryWithNoLock
builder.Services.AddEFSetup(_configuration); builder.Services.AddEFSetup(_configuration);
builder.Services.AddMediator(cfg =>
{
});
//转发头设置 获取真实IP //转发头设置 获取真实IP
builder.Services.Configure<ForwardedHeadersOptions>(options => builder.Services.Configure<ForwardedHeadersOptions>(options =>
+1 -1
View File
@@ -1,5 +1,5 @@
using AutoMapper; using AutoMapper;
using IRaCIS.Application.Services.BusinessFilter; using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
+11 -4
View File
@@ -176,6 +176,13 @@ namespace IRaCIS.Core.SCP.Service
await _SCPImageUploadRepository.AddAsync(_upload, true); await _SCPImageUploadRepository.AddAsync(_upload, true);
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
//将检查设置为传输结束
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
await SendAssociationReleaseResponseAsync(); await SendAssociationReleaseResponseAsync();
} }
@@ -236,11 +243,11 @@ namespace IRaCIS.Core.SCP.Service
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致 //奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
if (exception == null) if (exception == null)
{ {
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>(); //var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
//将检查设置为传输结束 ////将检查设置为传输结束
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true }); //await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
await _studyRepository.SaveChangesAndClearAllTrackingAsync(); //await _studyRepository.SaveChangesAndClearAllTrackingAsync();
} }
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}"); Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
File diff suppressed because it is too large Load Diff
+10 -17
View File
@@ -9,23 +9,16 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"bucketName": "zy-irc-store", "RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-store",
"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
"MinIO": {
"endpoint": "http://192.168.3.68",
"port": "8001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test"
} }
}, },
+13 -45
View File
@@ -9,15 +9,16 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"bucketName": "zy-irc-test-store", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-test-store",
"viewEndpoint": "https://zy-irc-test-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
}, },
"MinIO": { "MinIO": {
@@ -28,53 +29,20 @@
"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": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": false,
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
"secretKey": "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",
"bucketName": "ei-irc-test-store",
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
} }
}, },
"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": "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"
}, },
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test-study@extimaging.com",
"FromName": "Test_Study",
"AuthorizationCode": "zhanying123",
"SiteUrl": "http://study.test.extimaging.com/login"
},
"DicomSCPServiceConfig": { "DicomSCPServiceConfig": {
"CalledAEList": [ "CalledAEList": [
"STORESCP", "STORESCP"
"Value1",
"Value2",
"Value3"
], ],
"ServerPort": 11112 "ServerPort": 11112
} }
} }
+34
View File
@@ -0,0 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"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-lili-store",
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
+34
View File
@@ -0,0 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"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
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
+12 -44
View File
@@ -9,59 +9,27 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"bucketName": "zy-irc-uat-store", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-uat-store",
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai" "Region": "oss-cn-shanghai",
}, "DurationSeconds": 7200
"AWS": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": false,
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
"secretKey": "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",
"bucketName": "ei-irc-test-store",
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
}, },
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "uat-study@extimaging.com",
"FromName": "Uat_Study",
"AuthorizationCode": "zhanying123",
"SiteUrl": "http://study.uat.extimaging.com/login"
},
"DicomSCPServiceConfig": { "DicomSCPServiceConfig": {
"CalledAEList": [ "CalledAEList": [
"STORESCP", "STORESCP"
"Value1",
"Value2",
"Value3"
], ],
"ServerPort": 11112 "ServerPort": 11112
} }
} }
+1 -1
View File
@@ -17,7 +17,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
-99
View File
@@ -1,99 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace EFSaving.Concurrency
{
public class Sample
{
public static void Run()
{
// Ensure database is created and has a person in it
using (var setupContext = new PersonContext())
{
setupContext.Database.EnsureDeleted();
setupContext.Database.EnsureCreated();
setupContext.People.Add(new Person { FirstName = "John", LastName = "Doe" });
setupContext.SaveChanges();
}
#region ConcurrencyHandlingCode
using var context = new PersonContext();
// Fetch a person from database and change phone number
var person = context.People.Single(p => p.PersonId == 1);
person.PhoneNumber = "555-555-5555";
// Change the person's name in the database to simulate a concurrency conflict
context.Database.ExecuteSqlRaw(
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1");
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is Person)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
#endregion
}
public class PersonContext : DbContext
{
public DbSet<Person> People { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Requires NuGet package Microsoft.EntityFrameworkCore.SqlServer
optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=EFSaving.Concurrency;Trusted_Connection=True");
}
}
public class Person
{
public int PersonId { get; set; }
[ConcurrencyCheck]
public string FirstName { get; set; }
[ConcurrencyCheck]
public string LastName { get; set; }
public string PhoneNumber { get; set; }
}
}
}
+36 -98
View File
@@ -14,7 +14,7 @@ using System.Text;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Interfaces;
using System.Threading.Tasks; using System.Threading.Tasks;
using IRaCIS.Application.Services; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
@@ -37,6 +37,7 @@ using Amazon.SecurityToken.Model;
using Amazon.SecurityToken; using Amazon.SecurityToken;
using Amazon; using Amazon;
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest; using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
using AutoMapper;
namespace IRaCIS.Api.Controllers namespace IRaCIS.Api.Controllers
{ {
@@ -109,8 +110,12 @@ namespace IRaCIS.Api.Controllers
[FromServices] ITokenService _tokenService, [FromServices] ITokenService _tokenService,
[FromServices] IReadingImageTaskService readingImageTaskService, [FromServices] IReadingImageTaskService readingImageTaskService,
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig, [FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
[FromServices] IMailVerificationService _mailVerificationService) [FromServices] IMailVerificationService _mailVerificationService)
{ {
var emailConfig = _emailConfig.CurrentValue;
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN };
//MFA 邮箱验证 前端传递用户Id 和MFACode //MFA 邮箱验证 前端传递用户Id 和MFACode
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA) if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
@@ -143,10 +148,11 @@ namespace IRaCIS.Api.Controllers
// 验证阅片休息时间 // 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(userId); await readingImageTaskService.ResetReadingRestTime(userId);
await _fusionCache.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.UserToken(userId), loginReturn.JWTStr, TimeSpan.FromDays(7));
await _fusionCache.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes)); await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
loginReturn.CompanyInfo = companyInfo;
return ResponseOutput.Ok(loginReturn); return ResponseOutput.Ok(loginReturn);
} }
@@ -221,9 +227,9 @@ namespace IRaCIS.Api.Controllers
if (_verifyConfig.CurrentValue.OpenLoginMFA) if (_verifyConfig.CurrentValue.OpenLoginMFA)
{ {
//发版屏蔽
//returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
//MFA 发送邮件 //MFA 发送邮件
@@ -231,11 +237,21 @@ namespace IRaCIS.Api.Controllers
var email = returnModel.Data.BasicInfo.EMail; var email = returnModel.Data.BasicInfo.EMail;
var hiddenEmail = EmailMaskHelper.MaskEmail(email); var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
returnModel.Data.BasicInfo.EMail = hiddenEmail; returnModel.Data.BasicInfo.EMail = hiddenEmail;
await _userService.SendMFAEmail(userId); //修改密码
if (returnModel.Data.BasicInfo.IsFirstAdd || returnModel.Data.BasicInfo.LoginState == 1)
{
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
}
else
{
//正常登录才发送邮件
await _userService.SendMFAEmail(userId);
}
} }
else else
@@ -264,6 +280,8 @@ namespace IRaCIS.Api.Controllers
} }
} }
returnModel.Data.CompanyInfo = companyInfo;
return returnModel; return returnModel;
} }
@@ -273,8 +291,14 @@ namespace IRaCIS.Api.Controllers
} }
[AllowAnonymous]
[HttpGet, Route("user/getPublicKey")]
public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)
{
//var pemPublicKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey));
return ResponseOutput.Ok(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey);
}
[HttpGet, Route("imageShare/ShareImage")] [HttpGet, Route("imageShare/ShareImage")]
@@ -297,100 +321,14 @@ namespace IRaCIS.Api.Controllers
} }
[HttpGet("user/GetObjectStoreToken")] [HttpGet("user/GetObjectStoreToken")]
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options) public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
{ {
var serviceOption = options.CurrentValue;
if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS) var result = _oSSService.GetObjectStoreTempToken();
{
var ossOptions = serviceOption.AliyunOSS; //result.AWS = await GetAWSTemToken(options.CurrentValue);
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config() return ResponseOutput.Ok(result);
{
AccessKeyId = ossOptions.AccessKeyId,
AccessKeySecret = ossOptions.AccessKeySecret,
//AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8",
//AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
Endpoint = "sts.cn-hangzhou.aliyuncs.com"
});
var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
// 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称,例如oss-role-session。
assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
// 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
assumeRoleRequest.RoleArn = ossOptions.RoleArn;
//assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
var credentials = response.Body.Credentials;
var tempToken = new AliyunOSSTempToken()
{
AccessKeyId = credentials.AccessKeyId,
AccessKeySecret = credentials.AccessKeySecret,
Expiration = credentials.Expiration,
SecurityToken = credentials.SecurityToken,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
EndPoint = ossOptions.EndPoint,
ViewEndpoint = ossOptions.ViewEndpoint,
};
var awstempToken = await GetAWSTemToken(serviceOption);
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, AliyunOSS = tempToken,AWS= awstempToken });
}
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
{
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO});
}
else
{
var awsOptions = serviceOption.AWS;
//aws 临时凭证
// 创建 STS 客户端
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
// 使用 AssumeRole 请求临时凭证
var assumeRoleRequest = new AssumeRoleRequest
{
RoleArn = awsOptions.RoleArn, // 角色 ARN
RoleSessionName = $"session-name-{NewId.NextGuid()}",
DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
};
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
var credentials = assumeRoleResponse.Credentials;
var tempToken = new AWSTempToken()
{
AccessKeyId = credentials.AccessKeyId,
SecretAccessKey = credentials.SecretAccessKey,
SessionToken= credentials.SessionToken,
Expiration=credentials.Expiration,
Region=awsOptions.Region,
BucketName = awsOptions.BucketName,
EndPoint = awsOptions.EndPoint,
ViewEndpoint = awsOptions.ViewEndpoint,
};
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = tempToken });
}
} }
@@ -7,7 +7,7 @@ using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks; using System.Threading.Tasks;
using IRaCIS.Application.Services; using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.Inspection.DTO; using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
@@ -38,6 +38,7 @@ using Newtonsoft.Json;
using SharpCompress.Archives; using SharpCompress.Archives;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data; using System.Data;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -237,33 +238,7 @@ namespace IRaCIS.Core.API.Controllers
[HttpPost, Route("Study/PreArchiveStudy")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
[FromServices] IStudyService _studyService,
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
{
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
var studyMonitor = new StudyMonitor()
{
TrialId = savedInfo.TrialId,
SubjectId = savedInfo.SubjectId,
SubjectVisitId = savedInfo.SubjectVisitId,
IsSuccess = false,
UploadStartTime = DateTime.Now,
IsDicom = preArchiveStudyCommand.IsDicom,
IP = _userInfo.IP
};
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
return ResponseOutput.Ok(addEntity.Id);
}
/// <summary>Dicom 归档</summary> /// <summary>Dicom 归档</summary>
@@ -271,7 +246,7 @@ namespace IRaCIS.Core.API.Controllers
[DisableFormValueModelBinding] [DisableFormValueModelBinding]
[DisableRequestSizeLimit] [DisableRequestSizeLimit]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> ArchiveStudyNew( Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId, public async Task<IResponseOutput> ArchiveStudyNew(Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId,
[FromServices] ILogger<UploadDownLoadController> _logger, [FromServices] ILogger<UploadDownLoadController> _logger,
[FromServices] IStudyService _studyService, [FromServices] IStudyService _studyService,
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub, [FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
@@ -419,12 +394,26 @@ namespace IRaCIS.Core.API.Controllers
public class UploadNoneDicomFileCommand public class UploadNoneDicomFileCommand
{ {
public Guid TrialId { get; set; } [NotDefault]
public Guid SubjectVisitId { get; set; } public Guid SubjectVisitId { get; set; }
public Guid NoneDicomStudyId { get; set; }
[NotDefault]
public Guid StudyMonitorId { get; set; } public Guid StudyMonitorId { get; set; }
public Guid? NoneDicomStudyId { get; set; }
//IR 上传的时候跟任务绑定
public Guid? VisitTaskId { get; set; }
public string RecordPath { get; set; }
public int FailedFileCount { get; set; }
public long FileSize { get; set; }
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>(); public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
@@ -438,6 +427,41 @@ namespace IRaCIS.Core.API.Controllers
} }
} }
/// <summary>
/// 非dicom 上传预上传接口
/// </summary>
/// <param name="preArchiveStudyCommand"></param>
/// <param name="_studyService"></param>
/// <param name="_studyMonitorRepository"></param>
/// <returns></returns>
[HttpPost, Route("Study/PreArchiveStudy")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
[FromServices] IStudyService _studyService,
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
{
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
var studyMonitor = new StudyMonitor()
{
TrialId = savedInfo.TrialId,
SubjectId = savedInfo.SubjectId,
SubjectVisitId = savedInfo.SubjectVisitId,
IsSuccess = false,
UploadStartTime = DateTime.Now,
FileCount=preArchiveStudyCommand.FileCount,
IsDicom = preArchiveStudyCommand.IsDicom,
IP = _userInfo.IP
};
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
return ResponseOutput.Ok(addEntity.Id);
}
/// <summary> /// <summary>
/// 上传非Dicom 文件 支持压缩包 多文件上传 /// 上传非Dicom 文件 支持压缩包 多文件上传
/// </summary> /// </summary>
@@ -470,24 +494,37 @@ namespace IRaCIS.Core.API.Controllers
foreach (var item in incommand.UploadedFileList) foreach (var item in incommand.UploadedFileList)
{ {
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId,FileType=item.FileType,FileSize=item.FileFize }); //如果是跟任务绑,那么NoneDicomStudyId 设置为空,不影响之前的检查,同时设置 OriginNoneDicomStudyId 保证关系
if (incommand.VisitTaskId != null && incommand.VisitTaskId != Guid.Empty)
{
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, OriginNoneDicomStudyId = noneDicomStudyId.Value, VisitTaskId = incommand.VisitTaskId, FileType = item.FileType, FileSize = item.FileFize });
}
else
{
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
}
} }
var uploadFinishedTime = DateTime.Now; var uploadFinishedTime = DateTime.Now;
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId)); var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
noneDicomStudy.FileCount = noneDicomStudy.FileCount + incommand.UploadedFileList.Count; noneDicomStudy.FileCount = noneDicomStudy.FileCount + (incommand.VisitTaskId != null ? 0 : incommand.UploadedFileList.Count);
studyMonitor.FileCount = incommand.UploadedFileList.Count; studyMonitor.RecordPath = incommand.RecordPath;
studyMonitor.FailedFileCount = incommand.FailedFileCount;
studyMonitor.IsSuccess = incommand.FailedFileCount == 0;
studyMonitor.FileSize = incommand.UploadedFileList.Sum(t => t.FileFize); studyMonitor.FileSize = incommand.UploadedFileList.Sum(t => t.FileFize);
studyMonitor.IsDicom = false; studyMonitor.IsDicom = false;
studyMonitor.IsDicomReUpload = false; studyMonitor.IsDicomReUpload = false;
studyMonitor.StudyId = noneDicomStudyId; studyMonitor.StudyId = noneDicomStudyId.Value;
studyMonitor.StudyCode = noneDicomStudy.StudyCode; studyMonitor.StudyCode = noneDicomStudy.StudyCode;
studyMonitor.ArchiveFinishedTime = DateTime.Now; studyMonitor.ArchiveFinishedTime = DateTime.Now;
studyMonitor.IP = _userInfo.IP; studyMonitor.IP = _userInfo.IP;
studyMonitor.IsSuccess = true;
await _noneDicomStudyRepository.SaveChangesAsync(); await _noneDicomStudyRepository.SaveChangesAsync();
@@ -955,7 +992,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 }).ToList();
foreach (var item in excelList) foreach (var item in excelList)
{ {
@@ -979,9 +1016,9 @@ namespace IRaCIS.Core.API.Controllers
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).TrialSiteId; item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).TrialSiteId;
} }
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, list);
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, excelList.ToList());
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@@ -1,107 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<SignAssembly>false</SignAssembly>
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
<LangVersion>default</LangVersion>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
<NoWarn>1701;1702;1591;</NoWarn>
<OutputPath>..\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
<OutputPath>bin\Release\</OutputPath>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Controllers\ReviewerApi\**" />
<Compile Remove="UploadFile\**" />
<Content Remove="Controllers\ReviewerApi\**" />
<Content Remove="UploadFile\**" />
<EmbeddedResource Remove="Controllers\ReviewerApi\**" />
<EmbeddedResource Remove="UploadFile\**" />
<None Remove="Controllers\ReviewerApi\**" />
<None Remove="UploadFile\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="web.config" />
<Content Remove="wwwroot\swagger\ui\abp.js" />
<Content Remove="wwwroot\swagger\ui\abp.swagger.js" />
<Content Remove="wwwroot\swagger\ui\Index.html" />
</ItemGroup>
<ItemGroup>
<None Remove=".preview.jpg" />
<None Remove="GrpcToken.proto" />
<None Remove="IRaCIS.Core.API.xml" />
<None Remove="Protos\GrpcToken.proto" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="GrpcToken.proto" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js" />
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js" />
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\GrpcToken.proto">
<GrpcServices>Client</GrpcServices>
</Protobuf>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.4.1" />
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.4.1" />
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.41.0" />
<PackageReference Include="Grpc.Tools" Version="2.42.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Hangfire.Tags.SqlServer" Version="1.8.0" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="1.1.4" />
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\PublishProfiles\" />
</ItemGroup>
<ItemGroup>
<Content Update="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties anonymizetagsetting_1json__JsonSchema="http://json.schemastore.org/jovo-language-model" /></VisualStudio></ProjectExtensions>
</Project>
+94 -138
View File
@@ -1,156 +1,112 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <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>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Version>1.0.1.001</Version> <Version>1.0.1.001</Version>
<Company>上海展影医疗科技有限公司</Company> <Company>上海展影医疗科技有限公司</Company>
<Product>IRC影像系统 (EICS)</Product> <Product>IRC影像系统 (EICS)</Product>
<Copyright>上海展影医疗科技有限公司版权所有</Copyright> <Copyright>上海展影医疗科技有限公司版权所有</Copyright>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile> <DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
<NoWarn>1701;1702;1591;1570;</NoWarn> <NoWarn>1701;1702;1591;1570;</NoWarn>
<OutputPath>..\bin\</OutputPath> <OutputPath>..\bin\</OutputPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile> <DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<NoWarn>1701;1702;1591</NoWarn> <NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Remove="web.config" /> <Content Remove="web.config" />
<Content Remove="wwwroot\swagger\ui\abp.js" /> <Content Remove="wwwroot\swagger\ui\abp.js" />
<Content Remove="wwwroot\swagger\ui\abp.swagger.js" /> <Content Remove="wwwroot\swagger\ui\abp.swagger.js" />
<Content Remove="wwwroot\swagger\ui\Index.html" /> <Content Remove="wwwroot\swagger\ui\Index.html" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove=".preview.jpg" /> <None Remove=".preview.jpg" />
<None Remove="GrpcToken.proto" /> <None Remove="GrpcToken.proto" />
<None Remove="IRaCIS.Core.API.xml" /> <None Remove="IRaCIS.Core.API.xml" />
<None Remove="Protos\GrpcToken.proto" /> <None Remove="Protos\GrpcToken.proto" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ApplicationDefinition Include="GrpcToken.proto" /> <ApplicationDefinition Include="GrpcToken.proto" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js"> <EmbeddedResource Include="wwwroot\swagger\ui\abp.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js"> <EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html"> <EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Protobuf Include="Protos\GrpcToken.proto"> <Protobuf Include="Protos\GrpcToken.proto">
<GrpcServices>Client</GrpcServices> <GrpcServices>Client</GrpcServices>
</Protobuf> </Protobuf>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" /> <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.13" />
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.InMemory" Version="0.10.3" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.14" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.7.3" />
</ItemGroup>
<ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" /> <PrivateAssets>all</PrivateAssets>
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" /> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</ItemGroup> </PackageReference>
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.InMemory" Version="0.10.3" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.14" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.7.3" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" /> <ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
</ItemGroup> <ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html"> <None Include="..\.editorconfig" Link=".editorconfig" />
<CopyToOutputDirectory>Always</CopyToOutputDirectory> </ItemGroup>
</Content>
<Content Update="wwwroot\EmailTemplate\AdminResetUser_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\AdminResetUser.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\AdminAddUser.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\UserOptCommon_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\UserOptCommon.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Properties\PublishProfiles\" /> <Folder Include="Properties\PublishProfiles\" />
</ItemGroup> </ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions> <ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties properties_4launchsettings_1json__JsonSchema="" />
</VisualStudio>
</ProjectExtensions>
</Project> </Project>
+11 -7
View File
@@ -29,7 +29,7 @@
<param name="doctorId"></param> <param name="doctorId"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Application.Services.IMailVerificationService)"> <member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Service.IMailVerificationService)">
<summary> 系统用户登录接口[New] </summary> <summary> 系统用户登录接口[New] </summary>
</member> </member>
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})"> <member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
@@ -41,7 +41,7 @@
<param name="param"></param> <param name="param"></param>
<returns>新记录Id</returns> <returns>新记录Id</returns>
</member> </member>
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)"> <member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Core.Application.Service.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
<summary> <summary>
添加或更新工作量[AUTH] 添加或更新工作量[AUTH]
</summary> </summary>
@@ -281,6 +281,15 @@
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{System.Guid},System.Guid,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},IRaCIS.Core.Application.Contracts.IStudyService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.UploadHub,IRaCIS.Core.API.IUploadClient},IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})"> <member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{System.Guid},System.Guid,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},IRaCIS.Core.Application.Contracts.IStudyService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.UploadHub,IRaCIS.Core.API.IUploadClient},IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
<summary>Dicom 归档</summary> <summary>Dicom 归档</summary>
</member> </member>
<member name="M:IRaCIS.Core.API.Controllers.StudyController.PreArchiveStudy(IRaCIS.Core.Application.Contracts.PreArchiveStudyCommand,IRaCIS.Core.Application.Contracts.IStudyService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
<summary>
非dicom 上传预上传接口
</summary>
<param name="preArchiveStudyCommand"></param>
<param name="_studyService"></param>
<param name="_studyMonitorRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFileCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile})"> <member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFileCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile})">
<summary> <summary>
上传非Dicom 文件 支持压缩包 多文件上传 上传非Dicom 文件 支持压缩包 多文件上传
@@ -366,11 +375,6 @@
<param name="memberSerialization">序列化成员</param> <param name="memberSerialization">序列化成员</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:TimeZoneAdjustmentMiddleware">
<summary>
废弃,没用
</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>
对称可逆加密 对称可逆加密
@@ -1,118 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// 废弃,没用
/// </summary>
public class TimeZoneAdjustmentMiddleware
{
private readonly RequestDelegate _next;
public TimeZoneAdjustmentMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (string.IsNullOrEmpty(context.Request.ContentType))
{
// 请求没有内容体,可能是一个没有请求体的请求,比如 GET 请求
await _next(context);
return;
}
var timeZoneId = "Asia/Shanghai"; // 客户端默认时区
var timeZoneIdHeaderValue = context.Request.Headers["TimeZoneId"];
if (!string.IsNullOrEmpty(timeZoneIdHeaderValue))
{
timeZoneId = timeZoneIdHeaderValue;
}
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
// 处理 JSON 请求体中的时间字段
if (context.Request.ContentType.StartsWith("application/json"))
{
var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
// 使用 JSON.NET 或 System.Text.Json 解析 JSON 请求体
// 假设请求体中有一个名为 "dateTime" 的时间字段
dynamic jsonData = JsonConvert.DeserializeObject(requestBody);
if (jsonData.dateTime != null)
{
if (DateTime.TryParse((string)jsonData.dateTime, out DateTime dateTime))
{
// 将 JSON 请求体中的时间字段转换为服务器时区的时间
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
jsonData.dateTime = serverTime;
}
}
// 将修改后的 JSON 请求体重新写入请求流中
var jsonBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonData));
context.Request.Body = new MemoryStream(jsonBytes);
context.Request.ContentLength = jsonBytes.Length;
}
// 处理 URL 表单参数
var modifiedQuery = new Dictionary<string, StringValues>();
foreach (var key in context.Request.Query.Keys)
{
if (DateTime.TryParse(context.Request.Query[key], out DateTime dateTime))
{
// 将 URL 表单参数中的时间转换为服务器时区的时间
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
modifiedQuery[key] = new StringValues(serverTime.ToString());
}
else
{
modifiedQuery[key] = context.Request.Query[key];
}
}
context.Request.Query = new QueryCollection(modifiedQuery);
// 处理Form请求体中的参数
if (context.Request.HasFormContentType)
{
var modifiedForm = new Dictionary<string, StringValues>();
foreach (var key in context.Request.Form.Keys)
{
if (DateTime.TryParse(context.Request.Form[key], out DateTime dateTime))
{
// 将请求体中的时间转换为服务器时区的时间
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
modifiedForm[key] = new StringValues(serverTime.ToString());
}
else
{
modifiedForm[key] = context.Request.Form[key];
}
}
var newFormCollection = new FormCollection(modifiedForm);
// 将新的表单集合设置回请求对象
context.Request.Form = newFormCollection;
}
await _next(context);
}
}
+26 -5
View File
@@ -20,7 +20,7 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using IRaCIS.Application.Services.BackGroundJob; using IRaCIS.Core.Application.Service.BackGroundJob;
using LogDashboard; using LogDashboard;
using FellowOakDicom.Network; using FellowOakDicom.Network;
using IRaCIS.Core.Application.Service.ImageAndDoc; using IRaCIS.Core.Application.Service.ImageAndDoc;
@@ -33,6 +33,8 @@ using Newtonsoft.Json;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using IRaCIS.Core.Application.MassTransit.Command; using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MassTransit.Consumer; using IRaCIS.Core.Application.MassTransit.Consumer;
using DocumentFormat.OpenXml.InkML;
using IRaCIS.Core.Domain;
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true); AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
@@ -110,7 +112,7 @@ builder.Services.AddControllers(options =>
options.Filters.Add<ModelActionFilter>(); options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>(); options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>(); options.Filters.Add<UnitOfWorkFilter>();
options.Filters.Add<EncreptApiResultFilter>(10); //options.Filters.Add<EncreptApiResultFilter>(10);
options.Filters.Add<LimitUserRequestAuthorization>(); options.Filters.Add<LimitUserRequestAuthorization>();
@@ -121,16 +123,18 @@ builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.Ge
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig")); builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS")); builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService")); builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
builder.Services.AddOptions().Configure<EncreptResponseOption>(_configuration.GetSection("EncrypteResponseConfig")); builder.Services.AddOptions().Configure<IRCEncreptOption>(_configuration.GetSection("EncrypteResponseConfig"));
builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig")); builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
builder.Services.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码 //动态WebApi + UnifiedApiResultFilter 省掉控制器代码
builder.Services.AddDynamicWebApiSetup(); builder.Services.AddDynamicWebApiSetup();
//AutoMapper //AutoMapper
builder.Services.AddAutoMapperSetup(); builder.Services.AddAutoMapperSetup();
//EF ORM QueryWithNoLock //EF ORM QueryWithNoLock
builder.Services.AddEFSetup(_configuration,enviromentName); builder.Services.AddEFSetup(_configuration, enviromentName);
//Http 响应压缩 //Http 响应压缩
builder.Services.AddResponseCompressionSetup(); builder.Services.AddResponseCompressionSetup();
//Swagger Api 文档 //Swagger Api 文档
@@ -143,15 +147,30 @@ builder.Services.AddJWTAuthSetup(_configuration);
#region MassTransit #region MassTransit
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR //masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
//参考链接:https://masstransit.io/documentation/concepts/mediator#scoped-mediator
builder.Services.AddMediator(cfg => builder.Services.AddMediator(cfg =>
{ {
cfg.AddConsumer<ConsistencyCheckConsumer>(); cfg.AddConsumer<ConsistencyCheckConsumer>();
cfg.AddConsumer<AddSubjectTriggerConsumer>();
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
//cfg.ConfigureMediator((context, cfg) => cfg.UseHttpContextScopeFilter(context));
}); });
//添加 MassTransit 和 InMemory 传输
builder.Services.AddMassTransit(cfg => builder.Services.AddMassTransit(cfg =>
{ {
cfg.UsingInMemory(); // 注册消费者
cfg.AddConsumer<AddSubjectTriggerConsumer>(); // 替换为你的消费者类
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
// 使用 InMemory 作为消息传递机制
cfg.UsingInMemory((context, cfg) =>
{
// 这里可以进行额外的配置
cfg.ConfigureEndpoints(context); // 自动配置所有消费者的端点
});
}); });
#endregion #endregion
@@ -193,6 +212,7 @@ builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); //builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
//builder.Services.AddProblemDetails(); //builder.Services.AddProblemDetails();
#region #region
//builder.Services.AddMemoryCache(); //builder.Services.AddMemoryCache();
////上传限制 配置 ////上传限制 配置
@@ -215,6 +235,7 @@ var env = app.Environment;
#region #region
app.UseMiddleware<EncryptionRequestMiddleware>();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@@ -1,7 +1,7 @@
using Hangfire; using Hangfire;
using Hangfire.Dashboard; using Hangfire.Dashboard;
using Hangfire.Dashboard.BasicAuthorization; using Hangfire.Dashboard.BasicAuthorization;
using IRaCIS.Application.Services.BackGroundJob; using IRaCIS.Core.Application.Service.BackGroundJob;
using IRaCIS.Core.API.Filter; using IRaCIS.Core.API.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@@ -18,6 +18,7 @@ namespace IRaCIS.Core.API
// 全局忽略 DomainEvents 属性 // 全局忽略 DomainEvents 属性
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents)); automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
automapper.AddGlobalIgnore(nameof(Entity.DomainCommands));
#region 使 IncludeMembers 使 #region 使 IncludeMembers 使
//mapping an EntityFramework Core DbContext-object. //mapping an EntityFramework Core DbContext-object.
@@ -9,7 +9,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Application.Services; using IRaCIS.Core.Application.Service;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using AutoMapper; using AutoMapper;
@@ -8,9 +8,11 @@ using Medallion.Threading;
using Medallion.Threading.SqlServer; using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration; 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 StackExchange.Redis; using StackExchange.Redis;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
@@ -46,10 +48,11 @@ namespace IRaCIS.Core.API
else else
{ {
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
} }
//迁移的时候,不生成外键
options.ReplaceService<IMigrationsSqlGenerator, NoForeignKeyMigrationsSqlGenerator>();
options.UseLoggerFactory(logFactory); options.UseLoggerFactory(logFactory);
@@ -72,18 +75,15 @@ namespace IRaCIS.Core.API
options.UseTriggers(triggerOptions => options.UseTriggers(triggerOptions =>
{ {
triggerOptions.AddTrigger<AddSubjectTrigger>(); triggerOptions.AddTrigger<SubjectTrigger>();
triggerOptions.AddTrigger<ChallengeStateTrigger>(); triggerOptions.AddTrigger<ChallengeStateTrigger>();
triggerOptions.AddTrigger<SubjectStateTrigger>();
triggerOptions.AddTrigger<AddCRCCliniaclDataTrigger>();
triggerOptions.AddTrigger<SubjectVisitCheckPassedTrigger>();
triggerOptions.AddTrigger<SubjectVisitFinalVisitTrigger>();
triggerOptions.AddTrigger<SubjectVisitTrigger>(); triggerOptions.AddTrigger<SubjectVisitTrigger>();
triggerOptions.AddTrigger<SubjectVisitScanDateTrigger>();
triggerOptions.AddTrigger<TrialCriterionSignTrigger>(); triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
triggerOptions.AddTrigger<TableQuestionRowTrigger>(); triggerOptions.AddTrigger<TableQuestionRowTrigger>();
//triggerOptions.AddTrigger<AddlTrialUserTrigger>(); //triggerOptions.AddTrigger<AddlTrialUserTrigger>();
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>(); triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
triggerOptions.AddTrigger<VisitTaskIbeforeTrigger>(); triggerOptions.AddTrigger<JudgeVisitTaskTrigger>();
triggerOptions.AddTrigger<UserLogTrigger>(); triggerOptions.AddTrigger<UserLogTrigger>();
@@ -35,7 +35,9 @@ namespace IRaCIS.Core.API
else else
{ {
// Default or English date format // Default or English date format
_dateFormat = "MM/dd/yyyy HH:mm:ss"; //_dateFormat = "MM/dd/yyyy HH:mm:ss";
_dateFormat = "yyyy-MM-dd HH:mm:ss";
} }
#endregion #endregion
+12 -10
View File
@@ -13,15 +13,16 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"bucketName": "zy-irc-store", "RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-store",
"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
}, },
"MinIO": { "MinIO": {
"endpoint": "http://192.168.3.68", "endpoint": "http://192.168.3.68",
@@ -63,7 +64,8 @@
"CompanyName": "Extensive Imaging", "CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗" "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
} }
+12 -10
View File
@@ -15,15 +15,16 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"bucketName": "zy-irc-store", "RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-store",
"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
}, },
"MinIO": { "MinIO": {
"endpoint": "http://192.168.3.68", "endpoint": "http://192.168.3.68",
@@ -67,7 +68,8 @@
"CompanyName": "Extensive Imaging", "CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗" "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
"Port": "11113", "Port": "11113",
+9 -8
View File
@@ -19,10 +19,10 @@
"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": "LTAI5tJV76pYX5yPg1N9QVE8", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "roRNLa9YG1of4pYruJGCNKBXEWTAWa", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-test-store", "BucketName": "zy-irc-test-store",
"RoleArn": "acs:ram::1899121822495495:role/webdirect",
"ViewEndpoint": "https://zy-irc-test-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
@@ -40,11 +40,11 @@
"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
} }
}, },
@@ -88,7 +88,8 @@
"CompanyName": "Extensive Imaging", "CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗" "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
+16 -19
View File
@@ -15,18 +15,6 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "AWS", "ObjectStoreUse": "AWS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "",
"accessKeySecret": "",
"bucketName": "zy-irc-test-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": { "MinIO": {
"endPoint": "44.210.231.169", "endPoint": "44.210.231.169",
"port": "9001", "port": "9001",
@@ -38,12 +26,15 @@
}, },
"AWS": { "AWS": {
"endPoint": "s3.us-east-1.amazonaws.com", "Region": "us-east-1",
"useSSL": true, "EndPoint": "s3.us-east-1.amazonaws.com",
"accessKey": "AKIAW3MEAFJX5P32P6NA", "UseSSL": true,
"secretKey": "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", "RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
"bucketName": "ei-med-s3-lili-store", "AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/" "SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-store",
"ViewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com",
"DurationSeconds": 7200
} }
}, },
"BasicSystemConfig": { "BasicSystemConfig": {
@@ -82,7 +73,13 @@
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging", "CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗", "CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login" "SiteUrl": "https://lili.elevateimaging.ai/login",
"IsEnv_US": true
},
"SystemPacsConfig": {
"Port": "104",
"IP": "44.210.231.169"
} }
} }
+23 -24
View File
@@ -13,19 +13,7 @@
"ObjectStoreService": { "ObjectStoreService": {
"ObjectStoreUse": "MinIO", "ObjectStoreUse": "AWS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-test-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": { "MinIO": {
//"endPoint": "hir-oss.uat.extimaging.com", //"endPoint": "hir-oss.uat.extimaging.com",
//"port": "443", //"port": "443",
@@ -44,23 +32,26 @@
}, },
"AWS": { "AWS": {
"endPoint": "s3.us-east-1.amazonaws.com", "Region": "us-east-1",
"useSSL": true, "EndPoint": "s3.us-east-1.amazonaws.com",
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU", "UseSSL": true,
"secretKey": "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", "RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"bucketName": "ei-irc-test-store", "AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/" "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": { "BasicSystemConfig": {
"OpenUserComplexPassword": false, "OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": false, "OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true, "OpenTrialRelationDelete": true,
"OpenLoginLimit": false, "OpenLoginLimit": true,
"LoginMaxFailCount": 5, "LoginMaxFailCount": 5,
@@ -72,7 +63,9 @@
"ReadingRestTimeMin": 10, "ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true, "IsNeedChangePassWord": true,
"ChangePassWordDays": 90 "ChangePassWordDays": 90,
"OpenLoginMFA": true
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
@@ -88,7 +81,13 @@
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"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
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
} }
} }
+23 -14
View File
@@ -7,11 +7,11 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", //"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" //"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", "RemoteNew": "Server=3.226.182.187,1435;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true" "Hangfire": "Server=3.226.182.187,1435;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
}, },
"ObjectStoreService": { "ObjectStoreService": {
@@ -36,19 +36,22 @@
}, },
"AWS": { "AWS": {
"endPoint": "s3.us-east-1.amazonaws.com", "Region": "us-east-1",
"useSSL": true, "EndPoint": "s3.us-east-1.amazonaws.com",
"accessKey": "AKIAW3MEAFJXUO6XYFYN", "UseSSL": true,
"secretKey": "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", "RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"bucketName": "ei-med-s3-lili-uat-store", "AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"viewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/" "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": { "BasicSystemConfig": {
"OpenUserComplexPassword": false, "OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": false, "OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true, "OpenTrialRelationDelete": true,
@@ -66,7 +69,7 @@
"ChangePassWordDays": 90, "ChangePassWordDays": 90,
"OpenLoginMFA": true "OpenLoginMFA": false
}, },
"SystemEmailSendConfig": { "SystemEmailSendConfig": {
@@ -82,7 +85,13 @@
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"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
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
} }
} }
+23 -10
View File
@@ -15,15 +15,16 @@
"ObjectStoreUse": "AliyunOSS", "ObjectStoreUse": "AliyunOSS",
"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": "LTAI5tKvzs7ed3UfSpNk3xwQ", "AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"bucketName": "zy-irc-uat-store", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"roleArn": "acs:ram::1899121822495495:role/oss-upload", "BucketName": "zy-irc-uat-store",
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai" "Region": "oss-cn-shanghai",
"DurationSeconds": 7200
}, },
"MinIO": { "MinIO": {
@@ -38,6 +39,17 @@
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ", "secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat" "bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload",
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z",
"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
} }
}, },
@@ -74,7 +86,8 @@
"CompanyName": "Extensive Imaging", "CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司", "CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging", "CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗" "CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
}, },
"SystemPacsConfig": { "SystemPacsConfig": {
+4 -36
View File
@@ -43,40 +43,6 @@
} }
] ]
}, },
"easycaching": {
"inmemory": {
"MaxRdSecond": 120,
"EnableLogging": false,
"LockMs": 5000,
"SleepMs": 300,
"DBConfig": {
"SizeLimit": 10000,
"ExpirationScanFrequency": 60,
"EnableReadDeepClone": true,
"EnableWriteDeepClone": false
}
},
"redis": {
"MaxRdSecond": 120,
"EnableLogging": false,
"LockMs": 5000,
"SleepMs": 300,
"dbconfig": {
"Password": "xc@123456",
"IsSsl": false,
"SslHost": null,
"ConnectionTimeout": 5000,
"AllowAdmin": true,
"Endpoints": [
{
"Host": "47.117.164.182",
"Port": 6379
}
],
"Database": 0
}
}
},
"IRaCISImageStore": { "IRaCISImageStore": {
"SwitchingMode": "RemainingDiskCapacity", "SwitchingMode": "RemainingDiskCapacity",
"SwitchingRatio": 80, "SwitchingRatio": 80,
@@ -88,13 +54,15 @@
"QCChallengeCodePrefix": "Q", "QCChallengeCodePrefix": "Q",
"NoneDicomStudyCodePrefix": "NST", "NoneDicomStudyCodePrefix": "NST",
"DicomStudyCodePrefix": "ST", "DicomStudyCodePrefix": "ST",
"TaskStudyCodePrefix": "P-ST",
"SystemSiteCodePrefix": "S", "SystemSiteCodePrefix": "S",
"DefaultPassword": "123456", "DefaultPassword": "123456",
"ImageShareExpireDays": 10 "ImageShareExpireDays": 10
}, },
"EncrypteResponseConfig": { "EncrypteResponseConfig": {
"IsEnable": true, "Base64RSAPublicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBaHp3T1hYTWYyaEFkS1ZoWHczYUYNCmNaT3QycE1lcmdEaFVrOUdQK2s4VDBrUjFTRVlGVGtzNlkzaEVvL0dRTExqMHZFYVV3bTNhSFNuTTl5NmdLRWoNCmY5cTN6dkoyZzRSQjE4Z0UrTnNWWi9DMkVRZ3k5OWFiWGc5TitGREVlT0NmSjlSRTJPV3JBQ2s0V0RPbFFUdXYNCnhvR2JmcnkwVElSaFBrOGtuYkFmVkZ1and1VXJGblpJZ0ExYXhKZVZ6aDhwcmV1SEgreW1jdHp6NVo4V1pSV3kNCi9ISURHUy90dkg2NUMra2l6cUxRYUpKNHYwODMrRGpaVTBmNzNCdkk5eWt1dW1saXFzY1pvU2preDFOUFJwSkUNCkFtMVFNQ0hMRCtFdzlHT2Vsc2Mwa1ZxdjdaeEF1TkFrMkZuUURNRk1BUmZuUFd0aGVhOGZYVTJsMW9ROWs3WDcNCmN3SURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==",
"Base64RSAPrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRW9nSUJBQUtDQVFFQWh6d09YWE1mMmhBZEtWaFh3M2FGY1pPdDJwTWVyZ0RoVWs5R1ArazhUMGtSMVNFWQ0KRlRrczZZM2hFby9HUUxMajB2RWFVd20zYUhTbk05eTZnS0VqZjlxM3p2SjJnNFJCMThnRStOc1ZaL0MyRVFneQ0KOTlhYlhnOU4rRkRFZU9DZko5UkUyT1dyQUNrNFdET2xRVHV2eG9HYmZyeTBUSVJoUGs4a25iQWZWRnVqd3VVcg0KRm5aSWdBMWF4SmVWemg4cHJldUhIK3ltY3R6ejVaOFdaUld5L0hJREdTL3R2SDY1QytraXpxTFFhSko0djA4Mw0KK0RqWlUwZjczQnZJOXlrdXVtbGlxc2Nab1Nqa3gxTlBScEpFQW0xUU1DSExEK0V3OUdPZWxzYzBrVnF2N1p4QQ0KdU5BazJGblFETUZNQVJmblBXdGhlYThmWFUybDFvUTlrN1g3Y3dJREFRQUJBb0lCQUNDRFoxNi9XWWFYZmpOZA0KQ29pemU2VFJZU2llVzI5eFJic0ExVDV6YUcwVmY4U1NsdFF2Y1dWYmw2UGJUa3BxMkF4MHJDUVB2M2xOSm8vNA0KL3h3QzRlS1E1c1ZLRlFWTXJIbmhISlRxTTJ6UWVpMkJINlBuaEdZcVh0QVhOdzFxejhrSEoyQlFZM3IvN2d5Qw0KcWpZVFVCRDFRem5HeThCanlXOXVIcnNNeDVPRHRRZWxBM3B1TFd1bXZNb3Z1L2JhaDZvTGtOSHY4b0VTdzhGSQ0KTllyTUtscHhFTjZaWUdwSTl2VTZnYUhuTmhEa2ExTHlvUnZ5NnA2dTRLR0FsRTc1VXk4T0dsdncydU5uay9sdg0KSEMyYnY5TnlCRGJpSFNDY0MyK1JXUXMrN0tNWFlwYnBvTVFCR0hqV01GRHVBODFaUCs1TWYxUm9yQUpRNGxrRw0KQnRDQThva0NnWUVBeWY4alBjcFIvQ3dJNU5MYnlwb3ZUWEFHVkFKMmtWRlJVUC9HT2ZOMkFyYWMvL20wdDJ5NA0KemNYVkJZc0pJeHkvVWYxRTFJNFg3VFg3V3NBNGxVNGlPTkwzTnN4dDBEbk1PV2tKUlBPZlF1bW1JaWw5QVRiYQ0KTnRVWFNlTmRoUFFGMGlCb21acFFJYWpSN1RmUnVBbzR6dmpTLzkzeXZZY0lIWU1zM0tjR00ya0NnWUVBcTJPbg0KZlp0RmhLTElGanVlRzRrNklGTWdjbytEUUh5TTFWSUp5Tk05K1o2TEgybzI5eDJCaSs2Qm82M2NKUjQ2STZncQ0KNWUrSTBvdzZRYmNQeTZUNHFSQ0o3Ujd6MllkdEw4eXdJTkNYS3U0cC9qaFNqNWJ1TzFJWlI3ZStSV29CakNtUQ0KWFd0ZVBCbldqWVlLdVRCazROc2FXV09GTXg1QndKdUp2MjBnQ0hzQ2dZQlV4QnFYM1lWV0cyeUlDZXh1TXhIUw0KbjBZb2p2Z090MTgyYkg5VTVsUUpnM1NTL3NqVmlHeHMvYTROSzNGa0tMWW93KzNVZk9TUmlPdTRBNTQ3R1pURw0KMzlFYVQrTnRWRFBkaTdSMkdQNG1hRUp0WjVlcm9NY2w1M3BrYVdOZlhiL3JrK29STzI2UkVYVTI1UXUrL1pzbA0KVDhuTDBlb0JtdDdPODdNcHpYV09zUUtCZ0ZxVGFQSGx2RUNUY3FEbFV2S0VmRmFXOTkvelhrOFhRNnA5RjdTdA0KaHVSRDJJeDZxcC9BVlRWcGo5Tzd6MHRDaFVGUTM1THpHMkVDUU10My9uNEdLbS9XMEwyakRRWWFIeWNTeXNZYw0KMXJjV2ROVG9XU0dQaDBtTVl0WFhFbFJHNkpoMVl0a3NJL29wUVkwN21MRTBGU3dNUHdtY29jbFpKVEN3UW9VTA0KRzlHL0FvR0FWM25kcWcydnUyR0x4TlRUbm1UTWRJNFB3UzBmN0V4VnVNUnRicGZyOWhKNzlDakVNTGFXQ1FsNg0KeE43TElMTnArNVQwQW1DZVBqcitkbnJkRUNidFZPTDFybDc3Z0krRkwzaVVqYmZmMVZqa0N3M0x6K3cyb1FFdA0KbGE4aTZrL1NRK01iYkRPaWRJOVczdlN6MmlJRlZobWJiK1Q2SlZwakxqNjlkblM3eUxZPQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg==",
"IsResponseEncreptEnable": true,
"ApiPathList": [ "ApiPathList": [
"/test/get" "/test/get"
] ]
@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}为您添加了账户,账户信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
用户名: {1}
</div>
<div>
角色: {2}
</div>
<div>
首次登陆前,请通过该链接修改您的账户信息:
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
初始化账号信息
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0} ,
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation} has created an account for you. The account information is as follows:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
User ID: {1}
</div>
<div>
Role: {2}
</div>
<div>
Before logging in for the first time, please modify the account information through this link
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
Initialize account information
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}将您的账户密码已重置,账户信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
用户名: {1}
</div>
<div>
角色: {2}
</div>
<div>
密码: {3}
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0} ,
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation} has reset your account password, and the account information is as follows:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
User ID: {1}
</div>
<div>
Role: {2}
</div>
<div>
Password: {3}
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,27 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
感谢您使用展影云平台。
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{0}。
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,27 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
Thank you for using {company abbreviation} Cloud System.
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{0}。
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目阅片相关工作。
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
该项目采用电子化工作流,系统及您的账号信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
项目编号: {3}
</div>
<div>
试验方案号: {2}
</div>
<div>
试验名称: {1}
</div>
<div>
用户名: {4}
</div>
<div>
角色: {5}
</div>
<div>
系统登录地址:
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
点击跳转
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0},
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
{company abbreviation} invites you to participate in the IRC work of a trial ({1} , {2}).
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
Your account information is as follows
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
Trial ID: {3}
</div>
<div>
Protocol ID: {2}
</div>
<div>
Study Name: {1}
</div>
<div>
User ID: {4}
</div>
<div>
Role: {5}
</div>
<div>
Login URL:
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
Click to login
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
该项目采用电子化工作流,系统及您的账号信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
项目编号: {3}
</div>
<div>
试验方案号: {2}
</div>
<div>
试验名称: {1}
</div>
<div>
用户名: {4}
</div>
<div>
角色: {5}
</div>
<div>
首次登陆前,请通过该链接修改您的账户信息:
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
初始化账号信息
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0},
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
Your account information is as follows
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
Trial ID: {3}
</div>
<div>
Protocol ID: {2}
</div>
<div>
Study Name: {1}
</div>
<div>
User ID: {4}
</div>
<div>
Role: {5}
</div>
<div>
Before logging in for the first time, please modify the account information through this link
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
Initialize account information
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
您填写的中心调研表被驳回,详细信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
项目编号: {1}
</div>
<div>
试验方案号: {2}
</div>
<div>
试验名称: {3}
</div>
<div>
中心编号: {4}
</div>
<div>
中心名称: {5}
</div>
<div>
驳回原因: {6}
</div>
</div>
<a href='{7}' style='margin-left:60px;font-size:14px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;'>
登陆并查看
</a>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0} ,
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
The site survey form you filled in has been rejected. The details are as follows
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
Trial ID: {1}
</div>
<div>
Protocol ID: {2}
</div>
<div>
Study Name: {3}
</div>
<div>
Site ID: {4}
</div>
<div>
Site name: {5}
</div>
<div>
Reason for rejection: {6}
</div>
</div>
<a href='{7}' style='margin-left:60px;font-size:14px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;'>
Login and view
</a>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目相关工作,欢迎您提供指导和建议,非常感谢!
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
该项目采用电子化工作流,系统及您的账号信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
项目编号: {3}
</div>
<div>
试验方案号: {2}
</div>
<div>
试验名称: {1}
</div>
<div>
用户名: {4}
</div>
<div>
角色: {5}
</div>
<div>
系统登录地址:
<a href='{6}' style='margin-left:5px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
点击跳转
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0},
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
Your account information is as follows
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
Trial ID: {3}
</div>
<div>
Protocol ID: {2}
</div>
<div>
Study Name: {1}
</div>
<div>
User ID: {4}
</div>
<div>
Role: {5}
</div>
<div>
Login URL:
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
Click to login
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
尊敬的 {0} ,您好:
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
该项目采用电子化工作流,系统及您的账号信息如下:
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
项目编号: {3}
</div>
<div>
试验方案号: {2}
</div>
<div>
试验名称: {1}
</div>
<div>
用户名: {4}
</div>
<div>
角色: {5}
</div>
<div>
首次登陆前,请通过该链接修改您的账户信息:
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
初始化账号信息
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0},
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
Your account information is as follows
</div>
<span style="color: #00D1B2"></span>
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
<div>
Trial ID: {3}
</div>
<div>
Protocol ID: {2}
</div>
<div>
Study Name: {1}
</div>
<div>
User ID: {4}
</div>
<div>
Role: {5}
</div>
<div>
Before logging in for the first time, please modify the account information through this link
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
Initialize the account information
</a>
</div>
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,29 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
{0}您好,
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
感谢您使用展影云平台。
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{1},验证码是: <span style="font-weight:bold">{2}</span>
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
请在3分钟内输入该验证码,进行后续操作
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>祝您顺利!</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
@@ -1,30 +0,0 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Title</title>
</head>
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
<div style='padding-left: 40px;background: #f6f6f6'>
<div style='padding-top: 20px;'>
<div style='line-height: 40px;font-size: 18px'>
Dear {0},
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
{1}
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
The verification code is <span style="font-weight:bold">{2}</span>.
</div>
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
This code will expire in 3 minutes.
</div>
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
<div>Best regards,</div>
<div style="font-size: 14px;">{company}</div>
</div>
</div>
</div>
</body>
</html>
+3 -3
View File
@@ -31,9 +31,9 @@ namespace IRaCIS.Core.Application.Auth
Id = user.Id, Id = user.Id,
FullName = user.UserName, FullName = user.UserName,
RealName = user.RealName, RealName = user.RealName,
UserTypeEnum=user.UserTypeEnum, UserTypeEnum = user.UserTypeEnum,
UserTypeId=user.UserTypeId, UserTypeId = user.UserTypeId,
IsTestUser=user.IsTestUser, IsTestUser = user.IsTestUser,
Code = user.Code, Code = user.Code,
PermissionStr = user.PermissionStr, PermissionStr = user.PermissionStr,
+2 -8
View File
@@ -1,10 +1,4 @@
using System; namespace IRaCIS.Core.Application.Auth
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Auth
{ {
@@ -13,7 +7,7 @@ namespace IRaCIS.Core.Application.Auth
public const string CRC = "CRC"; public const string CRC = "CRC";
public const string PM = "PM"; public const string PM = "PM";
+1 -2
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic; using Microsoft.IdentityModel.Tokens;
using System.Text; using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace IRaCIS.Core.Application.Auth namespace IRaCIS.Core.Application.Auth
{ {
+3 -3
View File
@@ -1,7 +1,7 @@
using System.IdentityModel.Tokens.Jwt; using IRaCIS.Core.Domain.Share;
using System.Security.Claims;
using IRaCIS.Core.Domain.Share;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
namespace IRaCIS.Core.Application.Auth namespace IRaCIS.Core.Application.Auth
{ {
@@ -1,16 +1,10 @@
using Hangfire; using Hangfire;
using Hangfire.Storage; using Hangfire.Storage;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SharpCompress.Common;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services.BackGroundJob namespace IRaCIS.Core.Application.Service.BackGroundJob
{ {
public interface IIRaCISHangfireJob public interface IIRaCISHangfireJob
@@ -1,11 +1,10 @@
using IRaCIS.Core.Infra.EFCore; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.Application.BackGroundJob namespace IRaCIS.Core.Application.BackGroundJob
{ {
public interface IObtainTaskAutoCancelJob public interface IObtainTaskAutoCancelJob
{ {
Task CancelQCObtaion(Guid subjectVisitId,DateTime startTime); Task CancelQCObtaion(Guid subjectVisitId, DateTime startTime);
} }
public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob
@@ -13,7 +12,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
private readonly IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly ILogger<ObtainTaskAutoCancelJob> _logger; private readonly ILogger<ObtainTaskAutoCancelJob> _logger;
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger) public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
{ {
_subjectVisitRepository = subjectVisitRepository; _subjectVisitRepository = subjectVisitRepository;
_logger = logger; _logger = logger;
@@ -30,7 +29,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
var success = await _subjectVisitRepository.SaveChangesAsync(); var success = await _subjectVisitRepository.SaveChangesAsync();
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{ subjectVisitId }success:{success}"); _logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{subjectVisitId}success:{success}");
} }
catch (Exception e) catch (Exception e)
{ {
+4 -5
View File
@@ -1,17 +1,16 @@
using AutoMapper; using AutoMapper;
using IRaCIS.Application.Services.BusinessFilter; using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Panda.DynamicWebApi; using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes; using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using ZiggyCreatures.Caching.Fusion; using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application.Service
{ {
#pragma warning disable CS8618 #pragma warning disable CS8618
@@ -1,71 +0,0 @@
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.BusinessFilter
{
public class EncreptApiResultFilter : IAsyncResultFilter
{
private readonly IOptionsMonitor<EncreptResponseOption> _encreptResponseMonitor;
public EncreptApiResultFilter(IOptionsMonitor<EncreptResponseOption> encreptResponseMonitor)
{
_encreptResponseMonitor = encreptResponseMonitor;
}
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if(_encreptResponseMonitor.CurrentValue.IsEnable)
{
if (context.Result is ObjectResult objectResult)
{
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
var objectValue = objectResult.Value;
if (objectValue is IResponseOutput)
{
var responseOutput = objectValue as IResponseOutput<object>;
var path = context.HttpContext?.Request.Path.Value?.ToLower();
if(!string.IsNullOrEmpty(path) && path.Length>5 && _encreptResponseMonitor.CurrentValue.ApiPathList.Contains(path.ToLower()))
{
if(responseOutput.IsSuccess)
{
responseOutput.Code = ApiResponseCodeEnum.ResultEncrepted;
responseOutput.Data = JsonConvert.SerializeObject(Convert.ToBase64String(Encoding.UTF8.GetBytes(responseOutput.Data.ToString())));
objectResult.Value = responseOutput;
}
}
}
}
}
await next.Invoke();
}
}
}
@@ -0,0 +1,60 @@
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System.Text;
namespace IRaCIS.Core.Application.BusinessFilter;
/// <summary>
/// 测试加密API 返回的结果
/// </summary>
public class EncreptApiResultFilter : IAsyncResultFilter
{
private readonly IOptionsMonitor<IRCEncreptOption> _encreptResponseMonitor;
public EncreptApiResultFilter(IOptionsMonitor<IRCEncreptOption> encreptResponseMonitor)
{
_encreptResponseMonitor = encreptResponseMonitor;
}
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (_encreptResponseMonitor.CurrentValue.IsResponseEncreptEnable)
{
if (context.Result is ObjectResult objectResult)
{
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
var objectValue = objectResult.Value;
if (objectValue is IResponseOutput)
{
var responseOutput = objectValue as IResponseOutput<object>;
var path = context.HttpContext?.Request.Path.Value?.ToLower();
if (!string.IsNullOrEmpty(path) && path.Length > 5 && _encreptResponseMonitor.CurrentValue.ApiPathList.Contains(path.ToLower()))
{
if (responseOutput.IsSuccess)
{
responseOutput.Code = ApiResponseCodeEnum.ResultEncrepted;
responseOutput.Data = JsonConvert.SerializeObject(Convert.ToBase64String(Encoding.UTF8.GetBytes(responseOutput.Data.ToString())));
objectResult.Value = responseOutput;
}
}
}
}
}
await next.Invoke();
}
}
@@ -0,0 +1,130 @@
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Encryption;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System.Text;
namespace IRaCIS.Core.Application.BusinessFilter;
public class EncryptionRequestMiddleware
{
private readonly RequestDelegate _next;
private readonly IRCEncreptOption _IRCEncreptOption;
public EncryptionRequestMiddleware(RequestDelegate next, IOptionsMonitor<IRCEncreptOption> encreptResponseMonitor)
{
_next = next;
_IRCEncreptOption = encreptResponseMonitor.CurrentValue;
}
public async Task InvokeAsync(HttpContext context)
{
//模拟前端已经设置该请求头
//context.Request.Headers["X-Encrypted-Key"] = "hW8JuJocBzIPWSHURUnYJMZ0l68g6uP9rEdMho8ioFO8amD6GIH+R6RIX5jVFzOwO+lmgBi+4gaVJGGkWJMTcoDTfzzzT1EmfPV+UhFLE9HWvCkEXmDOLE9xCHrbG8TrR1I9+Qd3cvo9HLmrQ58n13cJsM82FBw+reUgiWeklPCkEWM9br2qc9VkCp6gKzimTldNTWBezV86S6j3qHbZpVZm0atdDtGb+zSC9LLA3+oHQwRLJAAGSOAi8CUiRmIQsygRd824wBndkaH2ImEeRjBMs7PqCeK3KsoDp13yHdj2AE751gsfNzf4SF547UPf72m0F2/rBFgrSNy+Jz0T9w==";
// 检查请求头中是否包含加密的对称密钥
if (context.Request.Headers.ContainsKey("X-Encrypted-Key"))
{
var encryptedSymmetricKeyStr = context.Request.Headers["X-Encrypted-Key"].ToString();
var pemSecretKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.Base64RSAPrivateKey));
// 使用私钥解密对称密钥
var decryptedSymmetricKey = RSAEncryption.Decrypt(pemSecretKey, encryptedSymmetricKeyStr);
#region
// 处理路径参数解密
var path = context.Request.Path.Value;
// 假设加密的参数在路径中,按照顺序解密路径中的每个部分
var pathSegments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
for (int i = 2; i < pathSegments.Length; i++)
{
if (!string.IsNullOrEmpty(pathSegments[i]))
{
try
{
var decryptedSegment = AesEncryption.Decrypt(pathSegments[i], decryptedSymmetricKey);
pathSegments[i] = decryptedSegment;
}
catch
{
// 如果不能解密该部分,保持原值
}
}
}
// 将解密后的路径重新拼接并设置到请求的Path
context.Request.Path = "/" + string.Join("/", pathSegments);
#endregion
#region url
// 处理 URL 查询参数的解密
var queryParams = context.Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString());
var decryptedQueryParams = new Dictionary<string, string>();
foreach (var param in queryParams)
{
var encryptedValue = param.Value;
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
decryptedQueryParams[param.Key] = decryptedValue;
}
// 构造解密后的查询字符串
var decryptedQueryString = new QueryString("?" + string.Join("&", decryptedQueryParams.Select(kvp => $"{kvp.Key}={kvp.Value}")));
context.Request.QueryString = decryptedQueryString;
#endregion
#region body传参
// 读取并解密请求体中的JSON数据
context.Request.EnableBuffering();
using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: true))
{
var encryptedBody = await reader.ReadToEndAsync();
context.Request.Body.Position = 0;
if (!string.IsNullOrEmpty(encryptedBody))
{
// 尝试解析为JObject
var encryptedJson = JObject.Parse(encryptedBody);
var decryptedJson = new JObject();
// 解密每个字段的值
foreach (var property in encryptedJson.Properties())
{
var encryptedValue = property.Value.ToString();
var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
decryptedJson[property.Name] = decryptedValue;
}
// 将解密后的JSON对象转换回字符串,并替换原始请求体
var decryptedBody = decryptedJson.ToString();
var bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(decryptedBody));
context.Request.Body = bodyStream;
context.Request.ContentLength = bodyStream.Length;
bodyStream.Seek(0, SeekOrigin.Begin);
}
}
#endregion
}
// 调用下一个中间件
await _next(context);
}
}
@@ -1,50 +1,43 @@
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.BusinessFilter namespace IRaCIS.Core.Application.BusinessFilter;
/// <summary>
/// 不生效,不知道为啥
/// </summary>
public class GlobalExceptionHandler : IExceptionHandler
{ {
private readonly ILogger<GlobalExceptionHandler> _logger;
/// <summary> public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
/// 不生效,不知道为啥 {
/// </summary> this._logger = logger;
public class GlobalExceptionHandler : IExceptionHandler }
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{ {
private readonly ILogger<GlobalExceptionHandler> _logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
this._logger = logger;
}
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
httpContext.Response.ContentType = "application/json"; httpContext.Response.ContentType = "application/json";
var ex = exception; var ex = exception;
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : ""); var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}")); httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
_logger.LogError(errorInfo); _logger.LogError(errorInfo);
// return true to signal that this exception is handled // return true to signal that this exception is handled
return ValueTask.FromResult(false); return ValueTask.FromResult(false);
}
} }
} }
@@ -1,13 +1,11 @@
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using ZiggyCreatures.Caching.Fusion; using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application.Filter; namespace IRaCIS.Core.Application.Filter;
@@ -25,7 +23,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig; private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer ,IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig) public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
{ {
_fusionCache = fusionCache; _fusionCache = fusionCache;
_userInfo = userInfo; _userInfo = userInfo;
@@ -55,7 +53,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
{ {
context.HttpContext.Response.ContentType = "application/json"; context.HttpContext.Response.ContentType = "application/json";
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK; context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
//---当前请求未从Header/Url取到用户Token,请联系开发者 //---当前请求未从Header/Url取到用户Token,请联系开发者
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]))); //await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
@@ -1,37 +1,34 @@
using IRaCIS.Core.Infrastructure.Extention; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter;
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
{ {
public IStringLocalizer _localizer;
public ModelActionFilter(IStringLocalizer localizer)
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
{ {
public IStringLocalizer _localizer; _localizer = localizer;
public ModelActionFilter(IStringLocalizer localizer)
{
_localizer = localizer;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var validationErrors = context.ModelState
.Keys
.SelectMany(k => context.ModelState[k]!.Errors)
.Select(e => e.ErrorMessage)
.ToArray();
//---提供给接口的参数无效。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject( validationErrors)));
}
}
} }
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var validationErrors = context.ModelState
.Keys
.SelectMany(k => context.ModelState[k]!.Errors)
.Select(e => e.ErrorMessage)
.ToArray();
//---提供给接口的参数无效。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
}
}
} }
@@ -1,28 +1,26 @@
using System;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter;
#region snippet_DisableFormValueModelBindingAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{ {
#region snippet_DisableFormValueModelBindingAttribute public void OnResourceExecuting(ResourceExecutingContext context)
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{ {
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories; var factories = context.ValueProviderFactories;
//factories.RemoveType<FormValueProviderFactory>(); //factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>(); factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>(); factories.RemoveType<JQueryFormValueProviderFactory>();
context.HttpContext.Request.EnableBuffering(); context.HttpContext.Request.EnableBuffering();
} }
public void OnResourceExecuted(ResourceExecutedContext context) public void OnResourceExecuted(ResourceExecutedContext context)
{ {
}
} }
#endregion
} }
#endregion
@@ -1,77 +1,75 @@
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter;
public class ProjectExceptionFilter : Attribute, IExceptionFilter
{ {
public class ProjectExceptionFilter : Attribute, IExceptionFilter private readonly ILogger<ProjectExceptionFilter> _logger;
public IStringLocalizer _localizer;
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
{ {
private readonly ILogger<ProjectExceptionFilter> _logger; _logger = logger;
_localizer = localizer;
}
public void OnException(ExceptionContext context)
{
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
public IStringLocalizer _localizer; if (!context.ExceptionHandled)
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
{ {
_logger = logger; if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
_localizer = localizer;
}
public void OnException(ExceptionContext context)
{
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
if (!context.ExceptionHandled)
{ {
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException") //---并发更新,当前不允许该操作
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
}
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
{
var error = context.Exception as BusinessValidationFailedException;
var info = string.Empty;
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
{ {
//---并发更新,当前不允许该操作 info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
} }
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
{
var error = context.Exception as BusinessValidationFailedException;
var info = string.Empty; context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
{
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
}
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info)); //warning 级别记录
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
}
//warning 级别记录 else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); {
} context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
{
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
}
else
{
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
}
context.ExceptionHandled = true;//标记当前异常已经被处理过了
//throw new Exception("test-result-exceptioin");
} }
else else
{ {
//继续 context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
} }
context.ExceptionHandled = true;//标记当前异常已经被处理过了
//throw new Exception("test-result-exceptioin");
}
else
{
//继续
} }
} }
} }
@@ -8,174 +8,189 @@ using System.Text.RegularExpressions;
using ZiggyCreatures.Caching.Fusion; using ZiggyCreatures.Caching.Fusion;
using static IRaCIS.Core.Domain.Share.StaticData; using static IRaCIS.Core.Domain.Share.StaticData;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter;
/// <summary>
/// 主要为了 处理项目结束 锁库,不允许操作
/// </summary>
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
{ {
/// <summary> private readonly IUserInfo _userInfo;
/// 主要为了 处理项目结束 锁库,不允许操作 private readonly IFusionCache _fusionCache;
/// </summary> public IStringLocalizer _localizer;
public class TrialResourceFilter : Attribute, IAsyncResourceFilter private readonly IRepository<Trial> _trialRepository;
private readonly List<string> _trialOptList = new List<string>();
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
{ {
private readonly IUserInfo _userInfo; _fusionCache = fusionCache;
private readonly IFusionCache _fusionCache; _userInfo = userInfo;
public IStringLocalizer _localizer; _localizer = localizer;
private readonly IRepository<Trial> _trialRepository; _trialRepository = trialRepository;
private readonly List<string> _trialOptList = new List<string>();
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) }
//优先选择异步的方法
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
// 获取当前请求的 Host 信息
var requestHost = context.HttpContext.Request.Host;
// 检查请求是否来自 localhost:6100
if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305))
{ {
_fusionCache = fusionCache; await next.Invoke();
_userInfo = userInfo;
_localizer = localizer;
_trialRepository = trialRepository;
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
return;
} }
//优先选择异步的方法 #region
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ {
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault(); //---对不起,您的账户没有操作权限。
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList(); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
#region return;
}
// 后期列举出具体的类型,其他任何用户类型,都不允许操作 #endregion
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
var trialIdStr = string.Empty;
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
{
trialIdStr = context.HttpContext.Request.Query["trialId"];
}
//先尝试从path中取TrialId
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
{
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
}
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
{
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
var trialIdIndex = headerStr.IndexOf("trialId");
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
if (matchResult.Success)
{ {
//---对不起,您的账户没有操作权限。 trialIdStr = matchResult.Value;
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); }
else
return; {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
#endregion }
else
{
#region body
//设置可以多次读
context.HttpContext.Request.EnableBuffering();
var reader = new StreamReader(context.HttpContext.Request.Body);
var contentFromBody = await reader.ReadToEndAsync();
//读取后,流的位置还原
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
//context.HttpContext.Request.Body.Position = 0;
//找到参数位置在字符串中的索引
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
//TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url if (trialIdIndex > -1)
var trialIdStr = string.Empty;
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
{ {
trialIdStr = context.HttpContext.Request.Query["trialId"]; // (?<="trialId" *: *").*?(?=",)
}
//先尝试从path中取TrialId //使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
{
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
}
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
{
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
var trialIdIndex = headerStr.IndexOf("trialId"); var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
if (matchResult.Success) if (matchResult.Success)
{ {
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
trialIdStr = matchResult.Value; trialIdStr = matchResult.Value;
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
//数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
return;
}
} }
else else
{ {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查 //---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
return;
} }
} //使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
else //trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
{
#region body
//设置可以多次读
context.HttpContext.Request.EnableBuffering();
var reader = new StreamReader(context.HttpContext.Request.Body);
var contentFromBody = await reader.ReadToEndAsync();
//读取后,流的位置还原
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
//context.HttpContext.Request.Body.Position = 0;
//找到参数位置在字符串中的索引
var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
if (trialIdIndex > -1)
{
// (?<="trialId" *: *").*?(?=",)
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
if (matchResult.Success)
{
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
trialIdStr = matchResult.Value;
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
//数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
}
}
else
{
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
}
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
}
#endregion
} }
//通过path 或者body 找到trialId 了 #endregion
if (!string.IsNullOrWhiteSpace(trialIdStr)) }
//通过path 或者body 找到trialId 了
if (!string.IsNullOrWhiteSpace(trialIdStr))
{
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{ {
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{
await next.Invoke();
}
// 项目停止、或者完成 不允许操作
else
{
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
}
}
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
{
await next.Invoke(); await next.Invoke();
}
}
// 项目停止、或者完成 不允许操作
else else
{ {
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改 //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
//---该接口参数中,没有传递项目编号,请核对。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
} }
} }
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
{
await next.Invoke();
}
else
{
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
//---该接口参数中,没有传递项目编号,请核对。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
}
} }
} }
@@ -1,123 +1,122 @@
using Microsoft.AspNetCore.Mvc.Filters; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace IRaCIS.Application.Services.BusinessFilter namespace IRaCIS.Core.Application.Service.BusinessFilter;
/// <summary>
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
/// by zhouhang 2021.09.12 周末
/// </summary>
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{ {
/// <summary> private readonly ILogger _logger;
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
/// by zhouhang 2021.09.12 周末 public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
/// </summary>
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{ {
private readonly ILogger _logger; _logger = logger;
}
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger) /// <summary>
/// 异步版本
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.Result is ObjectResult objectResult)
{ {
_logger = logger; var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
}
/// <summary> //是200 并且没有包装 那么包装结果
/// 异步版本 if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.Result is ObjectResult objectResult)
{ {
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
//是200 并且没有包装 那么包装结果 var type = objectResult.Value?.GetType();
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
{ {
var type = objectResult.Value?.GetType(); //报错
//var tuple = (object, object))objectResult.Value;
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>))) //var apiResponse = ResponseOutput.Ok(val1, val2);
{
//OK
//报错 var tuple = (dynamic)objectResult.Value;
//var tuple = (object, object))objectResult.Value; var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
//var apiResponse = ResponseOutput.Ok(val1, val2);
//OK
var tuple = (dynamic)objectResult.Value;
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType();
}
else
{
var apiResponse = ResponseOutput.Ok(objectResult.Value);
objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType();
}
objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType();
} }
//如果是200 是IResponseOutput 记录下日志 else
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
{ {
var result = objectResult.Value as IResponseOutput; var apiResponse = ResponseOutput.Ok(objectResult.Value);
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
{
//统一在这里记录国际化的日志信息
_logger.LogWarning($"{result.LocalizedInfo}");
}
}
else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
{
//---程序错误,请联系开发人员。
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
objectResult.Value = apiResponse; objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType(); objectResult.DeclaredType = apiResponse.GetType();
} }
} }
//如果是200 是IResponseOutput 记录下日志
await next.Invoke(); else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
}
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type == typeof(Tuple))
return true;
while (type != null)
{ {
if (type.IsGenericType) var result = objectResult.Value as IResponseOutput;
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
{ {
var genType = type.GetGenericTypeDefinition(); //统一在这里记录国际化的日志信息
if (genType == typeof(Tuple<>) _logger.LogWarning($"{result.LocalizedInfo}");
|| genType == typeof(Tuple<,>)
|| genType == typeof(Tuple<,>))
return true;
} }
if (!checkBaseTypes)
break;
type = type.BaseType;
} }
return false; else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
{
//---程序错误,请联系开发人员。
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType();
}
} }
await next.Invoke();
}
public static bool IsTupleType(Type type, bool checkBaseTypes = false)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type == typeof(Tuple))
return true;
while (type != null)
{
if (type.IsGenericType)
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(Tuple<>)
|| genType == typeof(Tuple<,>)
|| genType == typeof(Tuple<,>))
return true;
}
if (!checkBaseTypes)
break;
type = type.BaseType;
}
return false;
} }
} }
@@ -0,0 +1,164 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System.ComponentModel;
namespace IRaCIS.Core.Domain.Share;
[Description("多环境 配置环境实体")]
public class ServiceVerifyConfigOption
{
public bool OpenUserComplexPassword { get; set; }
public bool OpenSignDocumentBeforeWork { get; set; }
public bool OpenTrialRelationDelete { get; set; }
public bool OpenLoginLimit { get; set; }
public int LoginMaxFailCount { get; set; }
public int LoginFailLockMinutes { get; set; }
public int AutoLoginOutMinutes { get; set; }
public bool OpenLoginMFA { get; set; }
[Description("连续阅片时间 (min)")]
public int ContinuousReadingTimeMin { get; set; }
[Description("休息时间 (min)")]
public int ReadingRestTimeMin { get; set; }
[Description("是否需要修改密码")]
public bool IsNeedChangePassWord { get; set; }
[Description("修改密码的天数")]
public int ChangePassWordDays { get; set; }
}
public class SystemEmailSendConfig
{
public int Port { get; set; }
public string Host { get; set; } = string.Empty;
public string FromEmail { get; set; } = string.Empty;
public string FromName { get; set; } = string.Empty;
public string AuthorizationCode { get; set; } = string.Empty;
public string SiteUrl { get; set; } = string.Empty;
public string OrganizationName { get; set; } = string.Empty;
public string OrganizationNameCN { get; set; } = string.Empty;
public string CompanyName { get; set; } = string.Empty;
public string CompanyNameCN { get; set; } = string.Empty;
public string CompanyShortName { get; set; } = string.Empty;
public string CompanyShortNameCN { get; set; } = string.Empty;
public bool IsEnv_US { get; set; }
}
public class SystemEmailSendConfigView
{
public string CompanyName { get; set; } = string.Empty;
public string CompanyNameCN { get; set; } = string.Empty;
public string CompanyShortName { get; set; } = string.Empty;
public string CompanyShortNameCN { get; set; } = string.Empty;
}
public class SystemPacsConfig
{
public int Port { get; set; }
public string IP { get; set; } = string.Empty;
}
public class IRCEncreptOption
{
public string Base64RSAPublicKey { get; set; }
public string Base64RSAPrivateKey { get; set; }
public bool IsResponseEncreptEnable { get; set; }
public List<string> ApiPathList { get; set; }
}
public class IRaCISBasicConfigOption
{
public string DoctorCodePrefix { get; set; }
public string UserCodePrefix { get; set; }
public string QCChallengeCodePrefix { get; set; }
public string DicomStudyCodePrefix { get; set; }
public string TaskStudyCodePrefix { get; set; }
public string NoneDicomStudyCodePrefix { get; set; }
public int ImageShareExpireDays { get; set; }
public string SystemSiteCodePrefix { get; set; }
public string BlindTaskPrefix { get; set; }
public string DefaultPassword { get; set; }
}
[Description("项目基础配置规则")]
public static class AppSettings
{
public static IRaCISBasicConfigOption IRaCISBasicConfig { get; set; }
static AppSettings()
{
var configuration = new ConfigurationBuilder()
.Add(new JsonConfigurationSource
{
Path = "appsettings.json",
ReloadOnChange = true
})
.Build();
// 手动绑定配置
var appSettings = new IRaCISBasicConfigOption();
configuration.GetSection("IRaCISBasicConfig").Bind(appSettings);
IRaCISBasicConfig = appSettings;
}
//获取实体编码字符串
public static string GetCodeStr(int codeInt, string typeStr)
{
switch (typeStr)
{
case nameof(Doctor):
return IRaCISBasicConfig.DoctorCodePrefix + codeInt.ToString("D4");
case nameof(User):
return IRaCISBasicConfig.UserCodePrefix + codeInt.ToString("D4");
case nameof(QCChallenge):
return IRaCISBasicConfig.QCChallengeCodePrefix + codeInt.ToString("D5");
case nameof(NoneDicomStudy):
return IRaCISBasicConfig.NoneDicomStudyCodePrefix + codeInt.ToString("D5");
case nameof(DicomStudy):
return IRaCISBasicConfig.DicomStudyCodePrefix + codeInt.ToString("D5");
case nameof(TaskStudy):
return IRaCISBasicConfig.TaskStudyCodePrefix + codeInt.ToString("D5");
case nameof(VisitTask):
return "W" + codeInt.ToString("D5");
case nameof(Site):
return IRaCISBasicConfig.SystemSiteCodePrefix + codeInt.ToString("D4");
default:
return string.Empty;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
global using AutoMapper.QueryableExtensions;
global using IRaCIS.Core.Application.Service;
global using IRaCIS.Core.Domain.Models;
global using IRaCIS.Core.Infra.EFCore;
global using IRaCIS.Core.Infrastructure.Extention;
global using Microsoft.EntityFrameworkCore;
global using System.Linq.Expressions;
@@ -1,9 +1,4 @@
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper
{ {
@@ -19,9 +14,9 @@ namespace IRaCIS.Core.Application.Helper
//是否翻译依赖其他属性 //是否翻译依赖其他属性
public bool IsTranslateDenpendOtherProperty =>!string.IsNullOrWhiteSpace(DependPropertyName); public bool IsTranslateDenpendOtherProperty => !string.IsNullOrWhiteSpace(DependPropertyName);
public string DependPropertyName { get; set; }=string.Empty; public string DependPropertyName { get; set; } = string.Empty;
public string DependPropertyValueStr { get; set; } = string.Empty; public string DependPropertyValueStr { get; set; } = string.Empty;
@@ -33,7 +28,7 @@ namespace IRaCIS.Core.Application.Helper
} }
//针对不同的标准 翻译的字典不一样 //针对不同的标准 翻译的字典不一样
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType ) public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType)
{ {
DicParentCode = dicParentCode; DicParentCode = dicParentCode;
@@ -42,7 +37,7 @@ namespace IRaCIS.Core.Application.Helper
//针对业务某个属性的值 不一样 用的翻译字典不一样 //针对业务某个属性的值 不一样 用的翻译字典不一样
public DictionaryTranslateAttribute(string dicParentCode,string dependPropertyName, string dependPropertyValueStr) public DictionaryTranslateAttribute(string dicParentCode, string dependPropertyName, string dependPropertyValueStr)
{ {
DicParentCode = dicParentCode; DicParentCode = dicParentCode;
+58 -64
View File
@@ -1,75 +1,69 @@
using IRaCIS.Core.Domain.Models; namespace IRaCIS.Core.Application.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
public static class CacheKeys
{ {
//项目缓存
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
public static class CacheKeys //检查编号递增锁
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
//CRC上传影像提交锁key
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
//影像后处理上传提交锁key
public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
//系统匿名化
public static string SystemAnonymization => $"SystemAnonymization";
//前端国际化
public static string FrontInternational => $"FrontInternationalList";
//登录挤账号
public static string UserToken(Guid userId) => $"UserToken:{userId}";
//超时没请求接口自动退出
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
/// <summary>
/// 跳过阅片
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
/// <summary>
/// 开始阅片时间
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
/// <summary>
/// 开始休息时间
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
}
public static class CacheHelper
{
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
{ {
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}"; var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
public static string SystemAnonymization => $"SystemAnonymization";
public static string FrontInternational => $"FrontInternationalList";
//登录挤账号
public static string UserToken(Guid userId) => $"UserToken:{userId}";
//超时没请求接口自动退出
public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
// 你可以为其他实体和模块定义更多的键
/// <summary>
/// 跳过阅片
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
/// <summary>
/// 开始阅片时间
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
/// <summary>
/// 开始休息时间
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
return statusStr;
} }
public static class CacheHelper public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
{ {
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository) var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
{
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
return statusStr; return list;
}
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
{
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
return list;
}
} }
} }
@@ -1,44 +0,0 @@
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class EmailMaskHelper
{
//显示位数:3分之2的位数,向上取整
//取哪几个个值:最后一位和前面几位
//其他:3个***。
//比如:hlj23@126.com
//为:hlj***3@126.com
//he@126.com
//为:h*** e@126.com
public static string MaskEmail(string email)
{
// 找到 "@" 符号的位置
int atIndex = email.IndexOf('@');
string visiblePartBefore = email.Substring(0, atIndex);
string afterAt = email.Substring(atIndex + 1);
int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
// 替换中间两位字符为星号
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
// 组合隐藏和可见部分
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
return hiddenEmail;
}
}
}
@@ -1,29 +1,37 @@
using DocumentFormat.OpenXml.Drawing.Diagrams; using IRaCIS.Application.Contracts;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces; using IRaCIS.Application.Interfaces;
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson; using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using MiniExcelLibs; using MiniExcelLibs;
using MiniExcelLibs.OpenXml; using MiniExcelLibs.OpenXml;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.HSSF.UserModel; using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel; using NPOI.XSSF.UserModel;
using System.Collections; using System.Collections;
using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.IO;
namespace IRaCIS.Core.Application.Service; namespace IRaCIS.Core.Application.Service;
public static class ExcelExportHelper public static class ExcelExportHelper
{ {
//MiniExcel_Export //MiniExcel_Export
/// <summary>
///
/// </summary>
/// <param name="code"></param>
/// <param name="data"></param>
/// <param name="exportFileNamePrefix">文件名前缀</param>
/// <param name="_commonDocumentRepository"></param>
/// <param name="_hostEnvironment"></param>
/// <param name="_dictionaryService"></param>
/// <param name="translateType"></param>
/// <param name="criterionType"></param>
/// <returns></returns>
public static async Task<IActionResult> DataExportAsync(string code, ExcelExportInfo data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null) public static async Task<IActionResult> DataExportAsync(string code, ExcelExportInfo data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
{ {
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
@@ -68,7 +76,7 @@ public static class ExcelExportHelper
{ {
if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result)) if (DateTime.TryParse(itemValuePair.Value?.ToString(), out DateTime result))
{ {
itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result ); itemDic[itemValuePair.Key] = ExportExcelConverterDate.DateTimeInternationalToString(result);
} }
} }
@@ -348,6 +356,85 @@ public static class ExcelExportHelper
} }
/// <summary>
/// 导出文件模板
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public static async Task<FileResult> ExportTemplateAsync(ExportTemplateServiceDto inDto)
{
var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(inDto.hostEnvironment, inDto.commonDocumentRepository, inDto.TemplateCode);
//模板路径
var tplPath = physicalPath;
#region sheet
// 打开模板文件
var templateFile = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
// 获取文件流
var templateStream = new MemoryStream();
templateFile.CopyTo(templateStream);
templateStream.Seek(0, SeekOrigin.Begin);
var workbook = new XSSFWorkbook(templateStream);
int sheetCount = workbook.NumberOfSheets;
if (sheetCount == 2)
{
if (inDto.IsEnglish)
{
workbook.RemoveSheetAt(0);
}
else
{
workbook.RemoveSheetAt(1);
}
}
#endregion
ISheet sheet = workbook.GetSheetAt(0); // 获取第一个工作表
for (int i = 0; i < sheet.LastRowNum + 1; i++)
{
IRow row = sheet.GetRow(i);
for (int j = 0; j < sheet.LastRowNum; j++)
{
ICell cell = row.GetCell(j);
foreach (var property in inDto.Data.GetType().GetProperties())
{
var value = property.GetValue(inDto.Data);
if (cell!=null&&cell.ToString() == "{{" + property.Name + "}}")
{
sheet.GetRow(i).GetCell(j).SetCellValue(value.ToString());
}
}
}
}
var memoryStream2 = new MemoryStream();
workbook.Write(memoryStream2, true);
memoryStream2.Seek(0, SeekOrigin.Begin);
templateStream = memoryStream2;
return new FileStreamResult(templateStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"{(string.IsNullOrEmpty(inDto.ExportFileName) ? "" : inDto.ExportFileName + "_")}{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
};
}
} }
@@ -1,39 +1,33 @@
using System; using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper;
public class FileConvertHelper
{ {
public class FileConvertHelper
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
{ {
// 设置 libreoffice 命令行参数
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
// 启动 libreoffice 进程
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir) using (Process process = new Process())
{ {
// 设置 libreoffice 命令行参数 process.StartInfo.FileName = "libreoffice";
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\""; process.StartInfo.Arguments = arguments;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
// 启动 libreoffice 进程 process.Start();
using (Process process = new Process())
{
process.StartInfo.FileName = "libreoffice";
process.StartInfo.Arguments = arguments;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start(); // 等待进程结束
process.WaitForExit();
// 等待进程结束
process.WaitForExit();
}
} }
} }
} }
@@ -1,12 +1,7 @@
using IRaCIS.Core.Domain.Share;
using Aliyun.OSS;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Configuration;
using System.Globalization; using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -16,7 +11,7 @@ public static class FileStoreHelper
{ {
//处理文件名 压缩包,或者目录类的 会带上相对路径 //处理文件名 压缩包,或者目录类的 会带上相对路径
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false) public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName, bool isChangeToPdfFormat = false)
{ {
//带目录层级,需要后端处理前端的路径 //带目录层级,需要后端处理前端的路径
@@ -41,14 +36,14 @@ public static class FileStoreHelper
var trustedFileNameForFileStorage = string.Empty; var trustedFileNameForFileStorage = string.Empty;
if (isChangeToPdfFormat==false) if (isChangeToPdfFormat == false)
{ {
trustedFileNameForFileStorage= Guid.NewGuid().ToString() + fileName; trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName;
} }
else else
{ {
trustedFileNameForFileStorage=Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf"; trustedFileNameForFileStorage = Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
} }
return (trustedFileNameForFileStorage, fileName); return (trustedFileNameForFileStorage, fileName);
@@ -136,10 +131,10 @@ public static class FileStoreHelper
{ {
var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code); var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code);
var isEn_US = CultureInfo.CurrentCulture.Name!= StaticData.CultureInfo.zh_CN; var isEn_US = CultureInfo.CurrentCulture.Name != StaticData.CultureInfo.zh_CN;
if (doc == null) if (doc == null)
{ {
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。 //---数据库没有找到对应的数据模板文件,请联系系统运维人员。
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound")); throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
} }
@@ -147,11 +142,11 @@ public static class FileStoreHelper
if (!System.IO.File.Exists(filePath)) if (!System.IO.File.Exists(filePath))
{ {
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。 //---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid")); throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
} }
return (filePath, isEn_US? doc.Name.Trim('/'): doc.NameCN.Trim('/')); return (filePath, isEn_US ? doc.Name.Trim('/') : doc.NameCN.Trim('/'));
} }
@@ -202,7 +197,7 @@ public static class FileStoreHelper
// 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径 // 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId,bool isChangeToPdfFormat=false) public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId, bool isChangeToPdfFormat = false)
{ {
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
@@ -221,19 +216,19 @@ public static class FileStoreHelper
} }
public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment,Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId) public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
{ {
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder); return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder);
} }
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId) public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
{ {
#region #region
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); //var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
#endregion #endregion
var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder) ; var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder);
@@ -246,7 +241,7 @@ public static class FileStoreHelper
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
} }
var physicalPath = Path.Combine(path, instanceId.ToString() ); var physicalPath = Path.Combine(path, instanceId.ToString());
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}"; var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
@@ -260,7 +255,7 @@ public static class FileStoreHelper
public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment) public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment)
{ {
var json = File.ReadAllText( Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json")); var json = File.ReadAllText(Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException(); JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException();
@@ -274,7 +269,7 @@ public static class FileStoreHelper
{ {
//---解析Json文件配置出现问题 //---解析Json文件配置出现问题
throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message); throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message);
} }
//默认存储的路径 //默认存储的路径
@@ -1,15 +1,5 @@
using Hangfire; using Hangfire;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper
{ {
@@ -65,7 +55,7 @@ namespace IRaCIS.Core.Application.Helper
} }
public static void AddOrUpdateTrialCronJob (string jobId, Guid trialId, EmailBusinessScenario businessScenario, string emailCron) public static void AddOrUpdateTrialCronJob(string jobId, Guid trialId, EmailBusinessScenario businessScenario, string emailCron)
{ {
switch (businessScenario) switch (businessScenario)
+101 -107
View File
@@ -1,111 +1,105 @@
using RestSharp; using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper;
#region
public class HolidayCalendar
{ {
public string Name { get; set; }
#region public string Version { get; set; }
public class HolidayCalendar public string Generated { get; set; }
{ public string Timezone { get; set; }
public string Name { get; set; } public string Author { get; set; }
public string Version { get; set; } public string URL { get; set; }
public string Generated { get; set; } public Dictionary<string, List<HolidayYear>> Years { get; set; }
public string Timezone { get; set; } }
public string Author { get; set; }
public string URL { get; set; } public class HolidayYear
public Dictionary<string, List<HolidayYear>> Years { get; set; } {
} public string Name { get; set; }
public DateTime StartDate { get; set; }
public class HolidayYear public DateTime EndDate { get; set; }
{ public int Duration { get; set; }
public string Name { get; set; } public List<DateTime> CompDays { get; set; }
public DateTime StartDate { get; set; } public string URL { get; set; }
public DateTime EndDate { get; set; } public string Memo { get; set; }
public int Duration { get; set; } }
public List<DateTime> CompDays { get; set; } #endregion
public string URL { get; set; }
public string Memo { get; set; }
}
#endregion
public class HolidayHelper
{
/// <summary>
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file 
public class HolidayHelper /// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
{ /// </summary>
/// <summary> private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
/// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file 
/// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage private static HolidayCalendar _holidayCalendar { get; set; }
/// </summary>
private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
private static List<DateTime> _holidays = new List<DateTime>();
private static HolidayCalendar _holidayCalendar { get; set; } private static List<DateTime> _compensatedWorkdays = new List<DateTime>();
static HolidayHelper()
private static List<DateTime> _holidays = new List<DateTime>(); {
private static List<DateTime> _compensatedWorkdays = new List<DateTime>(); _holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar();
static HolidayHelper() foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
{ {
_holidayCalendar = _client.Get<HolidayCalendar>(new RestRequest()) ?? new HolidayCalendar(); // 添加节假日到假日集合
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x)) {
{ _holidays.Add(date);
// 添加节假日到假日集合 }
for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
{ // 添加补班日到补班日集合
_holidays.Add(date); foreach (var compDay in year.CompDays)
} {
_compensatedWorkdays.Add(compDay);
// 添加补班日到补班日集合 }
foreach (var compDay in year.CompDays) }
{
_compensatedWorkdays.Add(compDay); }
}
} public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
{
} if (startDate > endDate)
{
public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate) throw new ArgumentException("结束日期必须大于或等于开始日期");
{ }
if (startDate > endDate)
{ var diffTimeSpan = endDate - startDate;
throw new ArgumentException("结束日期必须大于或等于开始日期");
} // 初始化工作日数为0
int workdays = 0;
var diffTimeSpan = endDate - startDate;
// 找出在给定日期范围内的假期和补班日
// 初始化工作日数为0 var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
int workdays = 0; var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
// 找出在给定日期范围内的假期和补班日 // 遍历日期范围,计算工作日 注意 这里是小于
var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList(); for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList(); {
// 判断是否为工作日
// 遍历日期范围,计算工作日 注意 这里是小于 bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1)) bool isHoliday = filteredHolidays.Contains(date);
{ bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
// 判断是否为工作日
bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday; // 如果是补班日,或是平日(非假期,非周末),则算作工作日
bool isHoliday = filteredHolidays.Contains(date); if (isCompensatedWorkday || (!isWeekend && !isHoliday))
bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date); {
workdays++;
// 如果是补班日,或是平日(非假期,非周末),则算作工作日 }
if (isCompensatedWorkday || (!isWeekend && !isHoliday)) }
{
workdays++; return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
}
}
}
return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
}
}
} }
@@ -0,0 +1,77 @@
namespace IRaCIS.Core.Application.Helper;
public static class IRCEmailPasswordHelper
{
private static readonly Random Random = new Random();
//显示位数:3分之2的位数,向上取整
//取哪几个个值:最后一位和前面几位
//其他:3个***。
//比如:hlj23@126.com
//为:hlj***3@126.com
//he@126.com
//为:h*** e@126.com
public static string MaskEmail(string email)
{
// 找到 "@" 符号的位置
int atIndex = email.IndexOf('@');
string visiblePartBefore = email.Substring(0, atIndex);
string afterAt = email.Substring(atIndex + 1);
int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
// 替换中间两位字符为星号
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
// 组合隐藏和可见部分
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
return hiddenEmail;
}
/// <summary>
/// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
/// </summary>
/// <returns></returns>
public static string GenerateRandomPassword(int length)
{
// 必须包含的字符组
const string numbers = "0123456789";
const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
const string specialCharacters = "~!-@#$%^&*_+?";
// 随机选择至少一个字符
char[] requiredCharacters =
{
numbers[Random.Next(numbers.Length)],
upperCaseLetters[Random.Next(upperCaseLetters.Length)],
lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
specialCharacters[Random.Next(specialCharacters.Length)]
};
// 构建剩余的字符集,用于填充密码的其余部分
string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
// 确保密码长度满足用户要求
char[] password = new char[length];
// 将必须包含的字符放入密码中
requiredCharacters.CopyTo(password, 0);
// 填充剩余的字符
for (int i = requiredCharacters.Length; i < length; i++)
{
password[i] = allCharacters[Random.Next(allCharacters.Length)];
}
// 随机打乱密码字符顺序
return new string(password.OrderBy(_ => Random.Next()).ToArray());
}
}
@@ -1,10 +1,8 @@
using FellowOakDicom.Imaging; using FellowOakDicom.Imaging;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using System.Security.Cryptography;
using System.Text;
namespace IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Helper;
@@ -4,211 +4,204 @@ using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static IRaCIS.Core.Application.Service.Common.SystemMonitor;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper;
public static class InternationalizationHelper
{ {
public static class InternationalizationHelper public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
private static void VerifyFolder()
{ {
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources); if (!Directory.Exists(JsonFileFolder) ||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
private static void VerifyFolder()
{ {
if (!Directory.Exists(JsonFileFolder) || throw new BusinessValidationFailedException("国际化Json文件目录有误");
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
{
throw new BusinessValidationFailedException("国际化Json文件目录有误");
}
} }
}
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos) public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
{
VerifyFolder();
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
//更新json 文件 同时更新内存缓存的数据
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{ {
VerifyFolder(); var json = await File.ReadAllTextAsync(filePath);
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json); JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
// 添加或更新指定的键值对
//更新json 文件 同时更新内存缓存的数据 if (filePath.Contains(StaticData.En_US_Json))
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{ {
var json = await File.ReadAllTextAsync(filePath); foreach (var item in batchAddDtos)
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
// 添加或更新指定的键值对
if (filePath.Contains(StaticData.En_US_Json))
{ {
foreach (var item in batchAddDtos) jsonObject[item.Code] = item.Value;
{
jsonObject[item.Code] = item.Value;
StaticData.En_US_Dic[item.Code] = item.Value; StaticData.En_US_Dic[item.Code] = item.Value;
//日志记录该信息方便自己人看, 返回给客户的是配置的
StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
}
}
else
{
foreach (var item in batchAddDtos)
{
jsonObject[item.Code] = item.Value;
StaticData.Zh_CN_Dic[item.Code] = item.Value;
}
}
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
}
}
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN,string description)
{
VerifyFolder();
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
//更新json 文件 同时更新内存缓存的数据
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{
var json = await File.ReadAllTextAsync(filePath);
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
// 添加或更新指定的键值对
if (filePath.Contains(StaticData.En_US_Json))
{
jsonObject[key] = value;
StaticData.En_US_Dic[key] = value;
//日志记录该信息方便自己人看, 返回给客户的是配置的 //日志记录该信息方便自己人看, 返回给客户的是配置的
StaticData.Log_Locoalize_Dic[key] = description; StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
} }
else }
else
{
foreach (var item in batchAddDtos)
{ {
jsonObject[key] = valueCN; jsonObject[item.Code] = item.Value;
StaticData.Zh_CN_Dic[key] = valueCN; StaticData.Zh_CN_Dic[item.Code] = item.Value;
} }
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
} }
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
} }
}
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
{
VerifyFolder();
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository) //更新json 文件 同时更新内存缓存的数据
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{ {
//查询数据库的数据 var json = await File.ReadAllTextAsync(filePath);
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
// 添加或更新指定的键值对
if (filePath.Contains(StaticData.En_US_Json))
{ {
t.Code, jsonObject[key] = value;
t.Value,
t.ValueCN,
t.Description
}).ToListAsync();
//组织成json 文件 StaticData.En_US_Dic[key] = value;
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
//本地静态文件国际化需要
foreach (var tojsonItem in toJsonList)
{
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
//日志记录该信息方便自己人看, 返回给客户的是配置的 //日志记录该信息方便自己人看, 返回给客户的是配置的
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description; StaticData.Log_Locoalize_Dic[key] = description;
} }
else
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
//监测Json文件变更 实时刷新数据
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
{ {
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound")); jsonObject[key] = valueCN;
StaticData.Zh_CN_Dic[key] = valueCN;
} }
// //监测Json文件变更 实时刷新数据 await File.WriteAllTextAsync(filePath, jsonObject.ToString());
FileSystemWatcher_US = new FileSystemWatcher
{
Path = Path.GetDirectoryName(usJsonPath)!,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
Filter = Path.GetFileName(usJsonPath),
EnableRaisingEvents = true,
};
// 添加文件更改事件的处理程序
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
FileSystemWatcher_CN = new FileSystemWatcher
{
Path = Path.GetDirectoryName(cnJsonPath)!,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
Filter = Path.GetFileName(cnJsonPath),
EnableRaisingEvents = true,
};
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
} }
private static void LoadJsonFile(string filePath)
{
Console.WriteLine("刷新json内存数据");
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
IConfigurationRoot enConfiguration = builder.Build();
foreach (IConfigurationSection section in enConfiguration.GetChildren())
{
if (filePath.Contains(StaticData.En_US_Json))
{
StaticData.En_US_Dic[section.Key] = section.Value;
}
else
{
StaticData.Zh_CN_Dic[section.Key] = section.Value;
}
}
}
} }
public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository<Internationalization> _internationalizationRepository)
{
//查询数据库的数据
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
{
t.Code,
t.Value,
t.ValueCN,
t.Description
}).ToListAsync();
//组织成json 文件
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
//本地静态文件国际化需要
foreach (var tojsonItem in toJsonList)
{
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
//日志记录该信息方便自己人看, 返回给客户的是配置的
StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
}
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
//监测Json文件变更 实时刷新数据
if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
{
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
}
// //监测Json文件变更 实时刷新数据
FileSystemWatcher_US = new FileSystemWatcher
{
Path = Path.GetDirectoryName(usJsonPath)!,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
Filter = Path.GetFileName(usJsonPath),
EnableRaisingEvents = true,
};
// 添加文件更改事件的处理程序
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
FileSystemWatcher_CN = new FileSystemWatcher
{
Path = Path.GetDirectoryName(cnJsonPath)!,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
Filter = Path.GetFileName(cnJsonPath),
EnableRaisingEvents = true,
};
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
}
private static void LoadJsonFile(string filePath)
{
Console.WriteLine("刷新json内存数据");
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
IConfigurationRoot enConfiguration = builder.Build();
foreach (IConfigurationSection section in enConfiguration.GetChildren())
{
if (filePath.Contains(StaticData.En_US_Json))
{
StaticData.En_US_Dic[section.Key] = section.Value;
}
else
{
StaticData.Zh_CN_Dic[section.Key] = section.Value;
}
}
}
} }
File diff suppressed because it is too large Load Diff
@@ -1,97 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace IRaCIS.Core.Application.Helper
{
/// <summary>
/// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
/// </summary>
public class RSAHelper
{
public static AsymmetricCipherKeyPair GenerateRSAKeyPair(int keySize)
{
var keyGenerationParameters = new KeyGenerationParameters(new SecureRandom(), keySize);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
return keyPairGenerator.GenerateKeyPair();
}
public static string ExportPublicKey(AsymmetricKeyParameter publicKey)
{
using (StringWriter sw = new StringWriter())
{
PemWriter pw = new PemWriter(sw);
pw.WriteObject(publicKey);
pw.Writer.Flush();
return sw.ToString();
}
}
public static string ExportPrivateKey(AsymmetricKeyParameter privateKey)
{
using (StringWriter sw = new StringWriter())
{
PemWriter pw = new PemWriter(sw);
pw.WriteObject(privateKey);
pw.Writer.Flush();
return sw.ToString();
}
}
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privateKey">私钥</param>
/// <param name="decryptstring">待解密的字符串(Base64)</param>
/// <returns>解密后的字符串</returns>
public static string Decrypt(string privateKey, string decryptstring)
{
using (TextReader reader = new StringReader(privateKey))
{
dynamic key = new PemReader(reader).ReadObject();
var rsaDecrypt = new Pkcs1Encoding(new RsaEngine());
if (key is AsymmetricKeyParameter)
{
key = (AsymmetricKeyParameter)key;
}
else if (key is AsymmetricCipherKeyPair)
{
key = ((AsymmetricCipherKeyPair)key).Private;
}
rsaDecrypt.Init(false, key); //这里加密是true;解密是false
byte[] entData = Convert.FromBase64String(decryptstring);
entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length);
return Encoding.UTF8.GetString(entData);
}
}/// <summary>
/// 加密
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="encryptstring">待加密的字符串</param>
/// <returns>加密后的Base64</returns>
public static string Encrypt(string publicKey, string encryptstring)
{
using (TextReader reader = new StringReader(publicKey))
{
AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter;
Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine());
pkcs1.Init(true, key);//加密是true;解密是false;
byte[] entData = Encoding.UTF8.GetBytes(encryptstring);
entData = pkcs1.ProcessBlock(entData, 0, entData.Length);
return Convert.ToBase64String(entData);
}
}
}
}
@@ -1,9 +1,7 @@
using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Domain.Share;
using MailKit; using MailKit;
using MailKit.Security; using MailKit.Security;
using MimeKit; using MimeKit;
using NPOI.HPSF;
namespace IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Helper;
@@ -44,7 +42,7 @@ public static class SendEmailHelper
{ {
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员 //---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
throw new Exception(StaticData.International("SendEmail_SendFail"),new Exception(ex.Message)); throw new Exception(StaticData.International("SendEmail_SendFail"), new Exception(ex.Message));
} }
@@ -1,101 +1,95 @@
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using NPOI.XWPF.UserModel; using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xceed.Document.NET; using Xceed.Document.NET;
using Xceed.Words.NET; using Xceed.Words.NET;
namespace IRaCIS.Core.Application.Helper namespace IRaCIS.Core.Application.Helper;
/// <summary>
/// 利用DocX 库 处理word国际化模板
/// </summary>
public static class WordTempleteHelper
{ {
/// <summary> public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
/// 利用DocX 库 处理word国际化模板
/// </summary>
public static class WordTempleteHelper
{ {
public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
using (DocX document = DocX.Load(filePath))
{ {
// 查找书签
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; if (bookmarkEn_Start != null)
using (DocX document = DocX.Load(filePath))
{ {
// 查找书签 // 获取书签的起始位置
var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark); //int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
if (bookmarkEn_Start != null) var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
// 创建一个要删除段落的列表
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
foreach (var item in document.Paragraphs)
{ {
// 获取书签的起始位置 //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
//int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex; if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
// 创建一个要删除段落的列表
List<Paragraph> paragraphsToRemove = new List<Paragraph>();
foreach (var item in document.Paragraphs)
{ {
//中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的 paragraphsToRemove.Add(item);
if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
{
paragraphsToRemove.Add(item);
}
} }
foreach (var paragraph in paragraphsToRemove)
{
document.RemoveParagraph(paragraph);
}
} }
// 保存修改 foreach (var paragraph in paragraphsToRemove)
document.SaveAs(memoryStream);
}
}
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
XWPFDocument doc = new XWPFDocument(fs);
// 查找包含指定书签的段落及其索引
var bookmarkParagraph = doc.Paragraphs
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
if (bookmarkParagraph != null)
{ {
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph); document.RemoveParagraph(paragraph);
if (isEn_US)
{
// 从书签所在段落开始,删除之前的所有段落
for (int i = bookmarkIndex - 1; i >= 0; i--)
{
doc.RemoveBodyElement(i);
}
}
else
{
// 删除书签之后的所有段落
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
{
doc.RemoveBodyElement(i);
}
}
} }
doc.Write(memoryStream);
}
}
}
// 保存修改
document.SaveAs(memoryStream);
}
} }
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
XWPFDocument doc = new XWPFDocument(fs);
// 查找包含指定书签的段落及其索引
var bookmarkParagraph = doc.Paragraphs
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
if (bookmarkParagraph != null)
{
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
if (isEn_US)
{
// 从书签所在段落开始,删除之前的所有段落
for (int i = bookmarkIndex - 1; i >= 0; i--)
{
doc.RemoveBodyElement(i);
}
}
else
{
// 删除书签之后的所有段落
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
{
doc.RemoveBodyElement(i);
}
}
}
doc.Write(memoryStream);
}
}
} }
@@ -19,21 +19,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Using Include="IRaCIS.Core.Application;" />
<Using Include="AutoMapper.QueryableExtensions;" />
<Using Include="Microsoft.EntityFrameworkCore;" />
<Using Include="IRaCIS.Core.Domain.Models;" />
<Using Include="IRaCIS.Core.Infrastructure.Extention;" />
<Using Include="IRaCIS.Core.Infra.EFCore;" />
<!-- Global using -->
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="WebAppConfig.cs" /> <Compile Remove="WebAppConfig.cs" />
</ItemGroup> </ItemGroup>
@@ -58,8 +43,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.16" />
<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="3.7.402.4" /> <PackageReference Include="AWSSDK.S3" Version="3.7.402.7" />
<PackageReference Include="DocX" Version="3.0.1" /> <PackageReference Include="DocX" Version="3.0.1" />
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" /> <PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
<PackageReference Include="Hangfire.Core" Version="1.8.14" /> <PackageReference Include="Hangfire.Core" Version="1.8.14" />
@@ -71,8 +58,8 @@
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" /> <PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
<PackageReference Include="fo-dicom.Codecs" Version="5.14.5" /> <PackageReference Include="fo-dicom.Codecs" Version="5.14.5" />
<PackageReference Include="IP2Region.Net" Version="2.0.2" /> <PackageReference Include="IP2Region.Net" Version="2.0.2" />
<PackageReference Include="MailKit" Version="4.2.0" /> <PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="MimeKit" Version="4.2.0" /> <PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="MiniExcel" Version="1.34.1" /> <PackageReference Include="MiniExcel" Version="1.34.1" />
<PackageReference Include="Minio" Version="6.0.3" /> <PackageReference Include="Minio" Version="6.0.3" />
<PackageReference Include="MiniWord" Version="0.8.0" /> <PackageReference Include="MiniWord" Version="0.8.0" />
@@ -84,7 +71,6 @@
<PackageReference Include="RestSharp" Version="112.0.0" /> <PackageReference Include="RestSharp" Version="112.0.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="MassTransit.AspNetCore" Version="7.3.1" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" /> <PackageReference Include="ZiggyCreatures.FusionCache" Version="1.3.0" />
</ItemGroup> </ItemGroup>
@@ -98,4 +84,8 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Triggers\TempAbandon\" />
</ItemGroup>
</Project> </Project>
File diff suppressed because it is too large Load Diff
@@ -1,10 +1,5 @@
using MiniExcelLibs.Attributes; using MiniExcelLibs.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Command namespace IRaCIS.Core.Application.MassTransit.Command
{ {
@@ -0,0 +1,26 @@
using AutoMapper;
using IP2Region.Net.Abstractions;
using IRaCIS.Core.Domain;
using IRaCIS.Core.Domain.Models;
using MassTransit;
namespace IRaCIS.Core.Application.MassTransit.Consumer;
//国家|区域|省份|城市|ISP 缺省的地域信息默认是0
//0|0|0|内网IP|内网IP
// 中国|0|湖北省|武汉市|电信
public class AddUserLogTriggerConsumer(ISearcher _searcher) : IConsumer<AddUserLogTriggerCommand>
{
public async Task Consume(ConsumeContext<AddUserLogTriggerCommand> context)
{
var userLog = context.Message.UserLog;
var ipinfo = _searcher.Search(userLog.IP);
userLog.IPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3));
}
}
@@ -5,12 +5,7 @@ using IRaCIS.Core.Domain.Share;
using MassTransit; using MassTransit;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Newtonsoft.Json; using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Consumer namespace IRaCIS.Core.Application.MassTransit.Consumer
{ {
@@ -0,0 +1,101 @@
using AutoMapper;
using IRaCIS.Core.Domain;
using MassTransit;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.Application.MassTransit.Consumer;
/// <summary>
/// 添加Subject 触发添加访视 不能代替 Trigger,稽查BatchId 不一致
/// 因为消费者这里的数据库上下文 和消息发送者上下文不是同一个,相当于两个独立的事务
/// </summary>
/// <param name="_subjectVisitRepository"></param>
/// <param name="_visitStageRepository"></param>
/// <param name="_trialRepository"></param>
/// <param name="_mapper"></param>
public class AddSubjectTriggerConsumer(IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<Trial> _trialRepository,
IMapper _mapper) : IConsumer<AddSubjectTriggerCommand>
{
public async Task Consume(ConsumeContext<AddSubjectTriggerCommand> context)
{
var addSubjectEvent = context.Message;
{
Console.WriteLine(_visitStageRepository._dbContext.GetHashCode());
Console.WriteLine("两个 DbContext 不是同一个实例");
}
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync();
var svList = _mapper.Map<List<SubjectVisit>>(visitPlanList);
var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
svList.ForEach(t =>
{
t.SubjectId = addSubjectEvent.SubjectId;
t.TrialId = addSubjectEvent.TrialId;
t.TrialSiteId = addSubjectEvent.TrialSiteId;
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
t.Id = NewId.NextGuid();
});
await _subjectVisitRepository.AddRangeAsync(svList);
}
}
public class AddSubjectTriggerConsumer2(IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<Trial> _trialRepository,
IMapper _mapper) : IConsumer<AddSubjectTriggerCommand2>
{
public async Task Consume(ConsumeContext<AddSubjectTriggerCommand2> context)
{
var addSubjectEvent = context.Message;
{
Console.WriteLine(_visitStageRepository._dbContext.GetHashCode());
Console.WriteLine("两个 DbContext 不是同一个实例");
}
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == addSubjectEvent.TrialId && t.IsConfirmed).ToListAsync();
var svList = _mapper.Map<List<SubjectVisit>>(visitPlanList);
var IsEnrollementQualificationConfirm = await _trialRepository.Where(t => t.Id == addSubjectEvent.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
svList.ForEach(t =>
{
t.SubjectId = addSubjectEvent.SubjectId;
t.TrialId = addSubjectEvent.TrialId;
t.TrialSiteId = addSubjectEvent.TrialSiteId;
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
t.Id = NewId.NextGuid();
});
await _subjectVisitRepository.AddRangeAsync(svList);
}
}
@@ -0,0 +1,83 @@
using IRaCIS.Core.Application.MassTransit.Consumer;
using MassTransit;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.Application.MassTransit.Consumer;
/// <summary>
/// 参考链接:https://github.com/MassTransit/MassTransit/discussions/2498
/// </summary>
public static class MediatorHttpContextScopeFilterExtensions
{
public static void UseHttpContextScopeFilter(this IMediatorConfigurator configurator, IServiceProvider serviceProvider)
{
var filter = new HttpContextScopeFilter(serviceProvider.GetRequiredService<IHttpContextAccessor>());
configurator.ConfigurePublish(x => x.UseFilter(filter));
configurator.ConfigureSend(x => x.UseFilter(filter));
configurator.UseFilter(filter);
}
}
public class HttpContextScopeFilter :
IFilter<PublishContext>,
IFilter<SendContext>,
IFilter<ConsumeContext>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextScopeFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
private void AddPayload(PipeContext context)
{
if (_httpContextAccessor.HttpContext == null)
return;
var serviceProvider = _httpContextAccessor.HttpContext.RequestServices;
context.GetOrAddPayload(() => serviceProvider);
context.GetOrAddPayload<IServiceScope>(() => new NoopScope(serviceProvider));
}
public Task Send(PublishContext context, IPipe<PublishContext> next)
{
AddPayload(context);
return next.Send(context);
}
public Task Send(SendContext context, IPipe<SendContext> next)
{
AddPayload(context);
return next.Send(context);
}
public Task Send(ConsumeContext context, IPipe<ConsumeContext> next)
{
AddPayload(context);
return next.Send(context);
}
public void Probe(ProbeContext context)
{
}
private class NoopScope :
IServiceScope
{
public NoopScope(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public void Dispose()
{
}
public IServiceProvider ServiceProvider { get; }
}
}
@@ -3,12 +3,10 @@
// 生成时间 2022-06-07 13:16:33 // 生成时间 2022-06-07 13:16:33
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts;
using IRaCIS.Core.Domain.Share;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Application.ViewModel namespace IRaCIS.Core.Application.ViewModel
{ {
@@ -112,7 +110,8 @@ namespace IRaCIS.Core.Application.ViewModel
public List<CriterionReadingCategory> CriterionCategoryList => public List<CriterionReadingCategory> CriterionCategoryList =>
TrialReadingCriterionList.Select(t => TrialReadingCriterionList.Select(t =>
new CriterionReadingCategory() { new CriterionReadingCategory()
{
EnrollId = EnrollId, EnrollId = EnrollId,
TrialReadingCriterionId = t.TrialReadingCriterionId, TrialReadingCriterionId = t.TrialReadingCriterionId,
ReadingCategorys = CriterionReadingCategoryList.Where(c => c.TrialReadingCriterionId == t.TrialReadingCriterionId).Select(t => t.ReadingCategory).OrderBy(c => c).ToList() ReadingCategorys = CriterionReadingCategoryList.Where(c => c.TrialReadingCriterionId == t.TrialReadingCriterionId).Select(t => t.ReadingCategory).OrderBy(c => c).ToList()
@@ -120,10 +119,10 @@ namespace IRaCIS.Core.Application.ViewModel
//CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() : //CriterionReadingCategoryList.Count == 0 ? TrialReadingCriterionList.Select(t => new CriterionReadingCategory() { EnrollId = EnrollId, TrialReadingCriterionId = t.TrialReadingCriterionId }).ToList() :
// CriterionReadingCategoryList // CriterionReadingCategoryList
//.GroupBy(t => new { t.TrialReadingCriterionId, t.EnrollId }) //.GroupBy(t => new { t.TrialReadingCriterionId, t.EnrollId })
//.Select(g => new CriterionReadingCategory() { EnrollId = g.Key.EnrollId, TrialReadingCriterionId = g.Key.TrialReadingCriterionId, ReadingCategorys = g.Select(t => t.ReadingCategory).OrderBy(t=>t).ToList() }).ToList(); //.Select(g => new CriterionReadingCategory() { EnrollId = g.Key.EnrollId, TrialReadingCriterionId = g.Key.TrialReadingCriterionId, ReadingCategorys = g.Select(t => t.ReadingCategory).OrderBy(t=>t).ToList() }).ToList();
} }
@@ -3,9 +3,7 @@
// 生成时间 2022-07-01 15:33:01 // 生成时间 2022-07-01 15:33:01
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@@ -81,7 +79,7 @@ namespace IRaCIS.Core.Application.ViewModel
public Guid DoctorUserId { get; set; } public Guid DoctorUserId { get; set; }
} }
public class ConsistentConfirmGenerateCommand: SelfConsistentSimpleQuery public class ConsistentConfirmGenerateCommand : SelfConsistentSimpleQuery
{ {
@@ -104,7 +102,7 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsAutoAllocateGenerateTask { get; set; } public bool IsAutoAllocateGenerateTask { get; set; }
} }
public class DoctorSelfConsistentSubjectView: ConsistentCommonView public class DoctorSelfConsistentSubjectView : ConsistentCommonView
{ {
public string FirstGlobalVisitName { get; set; } = string.Empty; public string FirstGlobalVisitName { get; set; } = string.Empty;
public string? BlindSubjectCode { get; set; } public string? BlindSubjectCode { get; set; }
@@ -130,14 +128,14 @@ namespace IRaCIS.Core.Application.ViewModel
public int? ValidVisitCount { get; set; } public int? ValidVisitCount { get; set; }
} }
public class DoctorGroupConsistentSubjectView: ConsistentCommonView public class DoctorGroupConsistentSubjectView : ConsistentCommonView
{ {
public List<VisitTaskGroupSimpleDTO> SubjectTaskVisitList => VisitTaskList.GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Select(g => g.First()).OrderBy(t=>t.VisitTaskNum).ToList(); public List<VisitTaskGroupSimpleDTO> SubjectTaskVisitList => VisitTaskList.GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Select(g => g.First()).OrderBy(t => t.VisitTaskNum).ToList();
public List<VisitTaskGroupSimpleDTO> VisitTaskList { get; set; } = new List<VisitTaskGroupSimpleDTO>(); public List<VisitTaskGroupSimpleDTO> VisitTaskList { get; set; } = new List<VisitTaskGroupSimpleDTO>();
public List<UserSimpleInfo> DoctorUserList { get; set; }=new List<UserSimpleInfo>(); public List<UserSimpleInfo> DoctorUserList { get; set; } = new List<UserSimpleInfo>();
} }
public class VisitTaskGroupSimpleDTO public class VisitTaskGroupSimpleDTO
@@ -175,7 +173,7 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsClinicalDataSign { get; set; } public bool IsClinicalDataSign { get; set; }
} }
public class VisitTaskSimpleDTO :VisitTaskGroupSimpleDTO public class VisitTaskSimpleDTO : VisitTaskGroupSimpleDTO
{ {
public Guid? Id { get; set; } public Guid? Id { get; set; }
@@ -289,7 +287,7 @@ namespace IRaCIS.Core.Application.ViewModel
public class GetConsistentRuleOut public class GetConsistentRuleOut
{ {
public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; } public TaskConsistentRuleBasic? ConsistentRuleBasic { get; set; }
/// <summary> /// <summary>
/// 任务展示访视 读片任务显示是否顺序 /// 任务展示访视 读片任务显示是否顺序
/// </summary> /// </summary>
@@ -316,7 +314,7 @@ namespace IRaCIS.Core.Application.ViewModel
public string VirtualSiteCode { get; set; } public string VirtualSiteCode { get; set; }
} }
public class UpdateTrialSiteCodeCommandView: UpdateTrialSiteCodeCommand public class UpdateTrialSiteCodeCommandView : UpdateTrialSiteCodeCommand
{ {
public DateTime Creatime { get; set; } public DateTime Creatime { get; set; }
} }
@@ -3,11 +3,8 @@
// 生成时间 2022-06-29 13:36:46 // 生成时间 2022-06-29 13:36:46
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Application.ViewModel namespace IRaCIS.Core.Application.ViewModel
{ {
@@ -3,9 +3,7 @@
// 生成时间 2022-06-29 10:59:50 // 生成时间 2022-06-29 10:59:50
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Application.ViewModel namespace IRaCIS.Core.Application.ViewModel
@@ -69,7 +67,7 @@ namespace IRaCIS.Core.Application.ViewModel
{ {
if (!ReadingDurationTimeSpan.HasValue) if (!ReadingDurationTimeSpan.HasValue)
return ""; return "";
else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds) else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds)
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/; /*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
} }
} }
@@ -102,18 +100,18 @@ namespace IRaCIS.Core.Application.ViewModel
public Guid? SubjectId { get; set; } public Guid? SubjectId { get; set; }
public Guid? MedicalManagerUserId { get; set; } public Guid? MedicalManagerUserId { get; set; }
public DateTime? BeginSignTime { get; set; } public DateTime? BeginSignTime { get; set; }
public AuditAdvice? AuditAdviceEnum { get; set; } public AuditAdvice? AuditAdviceEnum { get; set; }
public DateTime? EndSignTime { get; set; } public DateTime? EndSignTime { get; set; }
public bool IsGetBeRead { get; set; } = false; public bool IsGetBeRead { get; set; } = false;
public bool IsGetNextMedicalReviewTask { get; set; } = false; public bool IsGetNextMedicalReviewTask { get; set; } = false;
public string SubjectCode { get; set; } = String.Empty; public string SubjectCode { get; set; } = String.Empty;
public string TrialSiteCode { get; set; } = String.Empty; public string TrialSiteCode { get; set; } = String.Empty;
public string TaskName { get; set; } = String.Empty; public string TaskName { get; set; } = String.Empty;
@@ -133,7 +131,7 @@ namespace IRaCIS.Core.Application.ViewModel
public Guid? TrialReadingCriterionId { get; set; } public Guid? TrialReadingCriterionId { get; set; }
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; } public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
public Arm? ArmEnum { get; set; } public Arm? ArmEnum { get; set; }
@@ -3,11 +3,9 @@
// 生成时间 2022-06-07 14:10:54 // 生成时间 2022-06-07 14:10:54
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//-------------------------------------------------------------------- //--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Application.ViewModel namespace IRaCIS.Core.Application.ViewModel
{ {
@@ -163,7 +161,7 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsCanEditUrgentState { get; set; } public bool IsCanEditUrgentState { get; set; }
public DateTime? FirstReadingTime { get;set; } public DateTime? FirstReadingTime { get; set; }
public string ReadingDuration public string ReadingDuration
{ {
@@ -221,11 +219,10 @@ namespace IRaCIS.Core.Application.ViewModel
public class AnalysisTaskView : ReadingTaskView public class AnalysisTaskView : ReadingTaskView
{ {
public bool? IsSelfAnalysis { get; set; }
public int ConsistentClinicalDataCount { get; set; } = 0; public int ConsistentClinicalDataCount { get; set; } = 0;
public bool IsReReadingOrBackInfluenceAnalysis { get; set; } public bool IsReReadingOrBackInfluenceAnalysis { get; set; }
} }
@@ -298,6 +295,8 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsUrgent => UnReadCanReadTaskList.Any(t => t.IsUrgent); public bool IsUrgent => UnReadCanReadTaskList.Any(t => t.IsUrgent);
public bool IsSubjectJudge => UnReadCanReadTaskList.All(t => t.ReadingCategory == ReadingCategory.Judge);
public int UnReadTaskCount { get; set; } public int UnReadTaskCount { get; set; }
public int UnReadCanReadTaskCount { get; set; } public int UnReadCanReadTaskCount { get; set; }
@@ -317,7 +316,7 @@ namespace IRaCIS.Core.Application.ViewModel
if (this.SuggesteFinishedTime != null) if (this.SuggesteFinishedTime != null)
{ {
var date = DateTime.Now; var date = DateTime.Now;
var timeSpan = SuggesteFinishedTime.Value- date; var timeSpan = SuggesteFinishedTime.Value - date;
if (timeSpan.TotalDays <= 2) if (timeSpan.TotalDays <= 2)
{ {
return 1; return 1;
@@ -338,14 +337,12 @@ namespace IRaCIS.Core.Application.ViewModel
} }
} }
public int UrgentCount { get; set; } public int UrgentCount { get; set; }
// public int UrgentCount => UnReadCanReadTaskList.Count(t => t.IsUrgent);
public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>(); public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>();
// public List<IRUnreadTaskView> UnReadCanReadTaskList => UnReadTaskList.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).ToList();
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>(); public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
} }
public class IRUnreadTaskView public class IRUnreadTaskView
@@ -392,13 +389,13 @@ namespace IRaCIS.Core.Application.ViewModel
} }
public class GetReadingIQueryableInDto:PageInput public class GetReadingIQueryableInDto : PageInput
{ {
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
public Guid? SubjectId { get; set; } public Guid? SubjectId { get; set; }
public Guid TrialReadingCriterionId { get; set; } public Guid TrialReadingCriterionId { get; set; }
public string? SubjectCode { get; set; } = null; public string? SubjectCode { get; set; } = null;
@@ -410,7 +407,7 @@ namespace IRaCIS.Core.Application.ViewModel
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; } public Guid? TrialSiteId { get; set; }
public Guid? SubjectId { get; set; } public Guid? SubjectId { get; set; }
@@ -436,7 +433,7 @@ namespace IRaCIS.Core.Application.ViewModel
public DateTime? BeginSignTime { get; set; } public DateTime? BeginSignTime { get; set; }
public DateTime? EndSignTime { get; set; } public DateTime? EndSignTime { get; set; }
public DateTime? BeginRequestReReadingTime { get; set; } public DateTime? BeginRequestReReadingTime { get; set; }
public DateTime? EndRequestReReadingTime { get; set; } public DateTime? EndRequestReReadingTime { get; set; }
@@ -554,7 +551,7 @@ namespace IRaCIS.Core.Application.ViewModel
public int? SubjectAllocateState { get; set; } public int? SubjectAllocateState { get; set; }
public List<Arm> ArmList { get; set; }=new List<Arm>() { }; public List<Arm> ArmList { get; set; } = new List<Arm>() { };
[NotDefault] [NotDefault]
public Guid TrialReadingCriterionId { get; set; } public Guid TrialReadingCriterionId { get; set; }
@@ -602,9 +599,9 @@ namespace IRaCIS.Core.Application.ViewModel
[JsonIgnore] [JsonIgnore]
public List<SubjectUserView> DoctorUserList { get; set; } public List<SubjectUserView> DoctorUserList { get; set; }
public List<SubjectUserView> PreviousDoctorUserList => DoctorUserList.Where(t => t.OrignalSubjectUserId != null).ToList(); public List<SubjectUserView> PreviousDoctorUserList => DoctorUserList.Where(t => t.ReplacedSubjectUserId != null).ToList();
public List<SubjectUserView> NowDoctorUserList => DoctorUserList.Where(t => t.OrignalSubjectUserId == null).ToList(); public List<SubjectUserView> NowDoctorUserList => DoctorUserList.Where(t => t.ReplacedSubjectUserId == null).ToList();
@@ -622,7 +619,7 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsConfirmed { get; set; } public bool IsConfirmed { get; set; }
//该属性有值 说明该医生被替换了 分配的时候 要过滤掉 //该属性有值 说明该医生被替换了 分配的时候 要过滤掉
public Guid? OrignalSubjectUserId { get; set; } public Guid? ReplacedSubjectUserId { get; set; }
public UserSimpleInfo DoctorUser { get; set; } public UserSimpleInfo DoctorUser { get; set; }
} }
@@ -7,18 +7,18 @@
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
namespace IRaCIS.Core.Application.Interfaces namespace IRaCIS.Core.Application.Interfaces
{ {
/// <summary> /// <summary>
/// ITaskAllocationRuleService /// ITaskAllocationRuleService
/// </summary> /// </summary>
public interface ITaskAllocationRuleService public interface ITaskAllocationRuleService
{ {
//Task<List<TaskAllocationRuleView>> GetTaskAllocationRuleList(TaskAllocationRuleQuery queryTaskAllocationRule); //Task<List<TaskAllocationRuleView>> GetTaskAllocationRuleList(TaskAllocationRuleQuery queryTaskAllocationRule);
Task<IResponseOutput> AddOrUpdateTaskAllocationRule(TaskAllocationRuleAddOrEdit addOrEditTaskAllocationRule); Task<IResponseOutput> AddOrUpdateTaskAllocationRule(TaskAllocationRuleAddOrEdit addOrEditTaskAllocationRule);
Task<IResponseOutput> DeleteTaskAllocationRule(Guid taskAllocationRuleId); Task<IResponseOutput> DeleteTaskAllocationRule(Guid taskAllocationRuleId);
} }

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