Compare commits

..

993 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
hang 7a0e1eda0c 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 11:41:10 +08:00
hang a14472358b 通用包升级 2024-09-04 11:41:08 +08:00
he 51f02e79c1 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:24:48 +08:00
he 0202a61b07 修改 2024-09-04 11:24:47 +08:00
hang 6cc4c32625 修改s3 minio 删除方法
continuous-integration/drone/push Build is passing
2024-09-04 11:14:52 +08:00
hang 3d304961d3 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 11:04:40 +08:00
hang f4426dd280 s3 增加region 2024-09-04 11:04:39 +08:00
he 457544adc3 修改
continuous-integration/drone/push Build is passing
2024-09-04 10:44:58 +08:00
he f426df9d7f 修改
continuous-integration/drone/push Build is passing
2024-09-04 10:36:24 +08:00
he 61780a3fe8 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 09:50:54 +08:00
he 35d7202fc3 代码修改 2024-09-04 09:50:51 +08:00
hang cec6174bb6 方便前端对接返回token
continuous-integration/drone/push Build is passing
2024-09-04 09:41:12 +08:00
hang 52ba183846 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 09:33:36 +08:00
hang b08a0aa4f1 aws 临时凭证授权增加 2024-09-04 09:33:32 +08:00
he 327874d396 修改
continuous-integration/drone/push Build is passing
2024-09-03 17:58:21 +08:00
he eae6be5fb4 修改
continuous-integration/drone/push Build is passing
2024-09-03 17:52:48 +08:00
he d49350a8cd Reapply "修改"
continuous-integration/drone/push Build is passing
This reverts commit 72f0fd3193.
2024-09-03 17:24:17 +08:00
he 72f0fd3193 Revert "修改"
continuous-integration/drone/push Build is passing
This reverts commit 0a581db6d1.
2024-09-03 17:18:41 +08:00
he 0a581db6d1 修改
continuous-integration/drone/push Build is passing
2024-09-03 17:07:31 +08:00
he a2dd550a72 添加配置
continuous-integration/drone/push Build is passing
2024-09-03 16:17:13 +08:00
he 1e91c08ae3 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-03 15:52:01 +08:00
he 96462aa4ba 提示语国际化修改 2024-09-03 15:51:59 +08:00
hang dfba116268 修改驼峰自定义
continuous-integration/drone/push Build is running
2024-09-03 15:51:51 +08:00
hang 1072049741 修改bug
continuous-integration/drone/push Build is passing
2024-09-03 14:20:54 +08:00
hang 16bf3e9cd8 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-03 14:14:18 +08:00
hang 1861374c31 上传下载修改 2024-09-03 14:14:17 +08:00
he 320ede4d7b 清空国际化json
continuous-integration/drone/push Build is passing
2024-09-03 13:39:08 +08:00
he 15414365ec 修改
continuous-integration/drone/push Build is passing
2024-09-03 13:29:47 +08:00
hang a5ef0fc902 修改oss 配置
continuous-integration/drone/push Build is passing
2024-09-03 13:02:40 +08:00
hang 01ee530e38 npgsql 适配临时提交
continuous-integration/drone/push Build is passing
2024-09-02 23:35:42 +08:00
hang e8db8a892c 清理包,移动扩展方法
continuous-integration/drone/push Build is passing
2024-09-02 18:00:34 +08:00
hang 1e0af11110 清理缓存
continuous-integration/drone/push Build is passing
2024-09-02 17:45:16 +08:00
he 5f6b174dd9 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-02 17:30:57 +08:00
he 4d2589c112 缓存修改 2024-09-02 17:30:56 +08:00
hang 47706913ca 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-02 17:27:04 +08:00
hang 1bbd11bbcd 调休计算 2024-09-02 17:27:03 +08:00
he 5d946d820e 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-02 17:13:14 +08:00
he 1e67d97169 代码提交 2024-09-02 17:13:13 +08:00
hang 84f4343791 修改影响归档 seqId 自动生成,不是数据库自动生成
continuous-integration/drone/push Build is passing
2024-09-02 11:05:33 +08:00
hang bd4e4e0072 阅片期替代
continuous-integration/drone/push Build is passing
2024-09-02 10:27:01 +08:00
hang 5afe0be277 增加视图查询
continuous-integration/drone/push Build is passing
2024-09-01 23:38:27 +08:00
hang 71fad05411 升级nuget包
continuous-integration/drone/push Build is passing
2024-08-30 23:47:58 +08:00
hang 8afd215957 视图调整修复
continuous-integration/drone/push Build is passing
2024-08-30 22:40:52 +08:00
hang 42e3b0df45 阅片期视图 改为ef 访视查询ok
continuous-integration/drone/push Build is passing
2024-08-30 18:01:51 +08:00
hang facdb3264d 视图替代初步提交
continuous-integration/drone/push Build is passing
2024-08-30 17:36:23 +08:00
hang 9732b65017 清理dbcontext 用户注入
continuous-integration/drone/push Build is passing
2024-08-30 15:20:59 +08:00
hang 80a60dff38 清理dbcontext 记录稽查代码位置
continuous-integration/drone/push Build is passing
2024-08-30 15:16:50 +08:00
hang 6276e0611a 删除、优化之前的表名、表字段名 调用数据库函数代码
continuous-integration/drone/push Build is passing
2024-08-30 09:15:26 +08:00
hang 5ccfe70f97 预备优化掉存储过程
continuous-integration/drone/push Build is passing
2024-08-29 23:32:21 +08:00
hang 7dc40fbc5c 清理、整理代码
continuous-integration/drone/push Build is passing
2024-08-29 22:32:08 +08:00
hang a340167bfb 合并代码
continuous-integration/drone/push Build is passing
2024-08-29 22:02:12 +08:00
hang 0b7b96dff1 pgsql 测试 2024-08-29 22:01:28 +08:00
he 7b7286c2b3 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-08-29 11:01:11 +08:00
he 5598385a5c 修改 2024-08-29 11:01:10 +08:00
hang d5023c412f 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-08-29 10:59:21 +08:00
hang b1d6d20800 增加影像检查下载 2024-08-29 10:59:18 +08:00
he 4f5006560e 修改
continuous-integration/drone/push Build is passing
2024-08-28 15:25:05 +08:00
he 43b302b727 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-08-28 14:53:33 +08:00
he d3611ef310 修改 2024-08-28 14:53:32 +08:00
hang 0e0cf881be 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-08-28 14:40:26 +08:00
hang a6ccd959fc 增加oss 删除方法 2024-08-28 14:40:25 +08:00
he 4fb7f6818d 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-08-28 13:33:56 +08:00
he f902e44303 修改 2024-08-28 13:33:55 +08:00
hang 2939290915 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-08-28 13:22:15 +08:00
hang a55ba549eb oss增加endpoint 2024-08-28 13:22:14 +08:00
he cdd8250a0c 修改
continuous-integration/drone/push Build is passing
2024-08-28 11:22:51 +08:00
he d56d1142cd 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-08-28 10:54:07 +08:00
he e4b0210981 代码修改 2024-08-28 10:54:06 +08:00
hang 4026a34fcf 修改oss 返回小写 +增加pgsql 测试文件
continuous-integration/drone/push Build is passing
2024-08-28 10:29:59 +08:00
hang 7001639125 参数增加提醒前端不要漏传
continuous-integration/drone/push Build is passing
2024-08-28 10:16:34 +08:00
hang 8fae551cc0 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-08-28 10:05:45 +08:00
hang cd00efe96f 清理阿里云之前代码和包 2024-08-28 10:05:44 +08:00
hang 176f50e836 导表质疑时长 优化
continuous-integration/drone/push Build is passing
2024-08-27 17:04:39 +08:00
hang 2cd78ab94e 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-08-27 16:57:57 +08:00
hang 9f4e43e20a 影像下载和上传入口增加 2024-08-27 16:57:56 +08:00
he 2caa7933ee 修改
continuous-integration/drone/push Build is passing
2024-08-27 16:45:47 +08:00
he 3b6da279f8 修改
continuous-integration/drone/push Build is passing
2024-08-27 16:20:15 +08:00
he e87185a906 修改
continuous-integration/drone/push Build is passing
2024-08-27 16:17:11 +08:00
he 7a496e114b 代码修改
continuous-integration/drone/push Build is passing
2024-08-27 16:09:55 +08:00
he fa2a0e7482 代码修改
continuous-integration/drone/push Build is passing
2024-08-27 15:36:19 +08:00
he 3f88a9df46 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-08-27 15:18:02 +08:00
he 049b14ae97 代码修改 2024-08-27 15:18:01 +08:00
hang f14d4bf373 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-08-27 15:05:48 +08:00
hang a9afb684c9 修改对象存储返回临时toekn 2024-08-27 15:05:46 +08:00
he 9c447dbd68 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-08-27 15:02:04 +08:00
he 0d446e6fcd 代码提交 2024-08-27 15:02:03 +08:00
hang c8f04a878a 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-08-27 14:47:23 +08:00
hang 633abdf0f4 修改时间国际化 2024-08-27 14:47:20 +08:00
he 8bd9f9a772 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-08-27 09:46:24 +08:00
he 7164a53267 稽查加配置 2024-08-27 09:46:20 +08:00
hang f52b09e5e8 修改排序bug
continuous-integration/drone/push Build is passing
2024-08-26 16:24:46 +08:00
hang 0acb7ca987 影像上传增加文件大小
continuous-integration/drone/push Build is passing
2024-08-26 15:35:02 +08:00
hang 1778d45481 修改对话里面时间时区问题
continuous-integration/drone/push Build is passing
2024-08-26 14:05:16 +08:00
hang 952655bf84 修改数据库配置
continuous-integration/drone/push Build is passing
2024-08-26 12:48:03 +08:00
hang c0921942ec 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-08-26 12:43:56 +08:00
hang 7e67f4c7cf 修改生产ae 配置 2024-08-26 12:39:41 +08:00
hang 4d14b31fb5 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-08-26 12:33:42 +08:00
hang 003064429d 统一记录日志增加判断 2024-08-26 12:33:41 +08:00
hang 34934762f0 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-08-26 12:26:22 +08:00
hang d1f542f03d 修改正式环境配置文件 2024-08-26 12:26:21 +08:00
hang fbc7513f19 解决中英文环境时间格式化问题
continuous-integration/drone/push Build is passing
2024-08-26 12:28:09 +09:00
hang e42c7407e3 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-08-23 17:34:15 +08:00
hang cbfae4126c 修改缓存判断逻辑 2024-08-23 17:34:15 +08:00
hang c712bee677 修改导表提示
continuous-integration/drone/push Build is passing
2024-08-23 17:22:06 +08:00
hang f732edfc6f 修改上传缓存判断
continuous-integration/drone/push Build is passing
2024-08-23 15:54:53 +08:00
hang 2898c0380f 清理仓储完成3
continuous-integration/drone/push Build is passing
2024-08-23 15:10:28 +08:00
hang a43ef376c4 整理仓储2
continuous-integration/drone/push Build is passing
2024-08-23 14:54:01 +08:00
hang 7867a82e6e 整理仓储
continuous-integration/drone/push Build is passing
2024-08-23 13:51:58 +08:00
hang e81e270d69 修改仓储
continuous-integration/drone/push Build is passing
2024-08-23 11:19:24 +08:00
hang 45b14abe63 修改注入bug
continuous-integration/drone/push Build is passing
2024-08-23 09:27:36 +08:00
hang 22b1a839ba 构造函数优化
continuous-integration/drone/push Build is passing
2024-08-22 21:37:56 +08:00
hang 47ec4a5e7e 导航属性优化整理
continuous-integration/drone/push Build is passing
2024-08-22 20:10:59 +08:00
hang 4319982be9 精简实体修改
continuous-integration/drone/push Build is passing
2024-08-22 18:10:29 +08:00
hang f0943ca9a4 整理实体
continuous-integration/drone/push Build is passing
2024-08-22 17:05:02 +08:00
hang 8a42ed74bc 修改排序
continuous-integration/drone/push Build is passing
2024-08-22 16:39:07 +08:00
hang d9f60ded4a 增加排序方法说明
continuous-integration/drone/push Build is passing
2024-08-22 16:01:43 +08:00
hang 15fe8db248 维护历史分页列表传递参数
continuous-integration/drone/push Build is passing
2024-08-22 15:57:02 +08:00
hang 7db339d876 增加邮件模板验证
continuous-integration/drone/push Build is passing
2024-08-22 11:40:21 +08:00
hang dd07057ca5 字典和邮件添加增加验证
continuous-integration/drone/push Build is passing
2024-08-22 11:00:43 +08:00
hang a43abebc6e 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-08-22 10:23:00 +08:00
hang 6a535e72d4 构造函数优化 2024-08-22 10:23:00 +08:00
hang 1535f1096f 编译错误
continuous-integration/drone/push Build is passing
2024-08-22 10:03:34 +08:00
hang 88fcddfd8b 发送邮件+pacs接口
continuous-integration/drone/push Build is running
2024-08-22 10:02:46 +08:00
hang d58cd79d28 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-08-22 09:30:58 +08:00
hang e5c35f7fab 既往缓存代码修改,缓存key 整理 2024-08-22 09:30:57 +08:00
he 0f45729c94 修改
continuous-integration/drone/push Build is passing
2024-08-21 17:48:22 +08:00
he a78c4de654 修改
continuous-integration/drone/push Build is passing
2024-08-21 17:39:19 +08:00
he 4dfe5a1dce 参数调整
continuous-integration/drone/push Build is passing
2024-08-21 17:35:32 +08:00
he ecaa72c12b 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-08-21 17:30:41 +08:00
he 95728c668c 修改字段 2024-08-21 17:30:41 +08:00
hang 9356e6ed7e 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 failing
2024-08-21 17:26:18 +08:00
hang 7a6cfc8978 影像预览调用接口错误,增加接口 2024-08-21 17:26:15 +08:00
he f744124f17 添加字段
continuous-integration/drone/push Build is passing
2024-08-21 17:23:31 +08:00
he 30e71b11e8 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-08-21 17:15:01 +08:00
he 2de504005e 一致性分析完全随机自动生效 2024-08-21 17:15:01 +08:00
hang 6a41c33d34 pacs 验证写反了
continuous-integration/drone/push Build is passing
2024-08-21 14:51:57 +08:00
hang 3b48dfae31 项目缓存状态逻辑,全局修改
continuous-integration/drone/push Build is passing
2024-08-21 14:37:33 +08:00
hang c7fd9a6bcb 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-08-21 13:38:21 +08:00
hang 169ef180ff 修改pacs 反馈提示+中心调研bug 2024-08-21 13:38:20 +08:00
he f33d3d474b 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-08-21 13:26:46 +08:00
he 63e1331bd1 验证签名信息 2024-08-21 13:26:43 +08:00
hang 418cc9b4b9 修改pacs 验证
continuous-integration/drone/push Build is passing
2024-08-21 12:24:30 +08:00
hang 71fb1eac6b 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-08-21 12:18:36 +08:00
hang 0804a05925 准备新缓存临时工作 2024-08-21 12:18:36 +08:00
hang de6098013d 导表签名bug
continuous-integration/drone/push Build is passing
2024-08-21 10:46:33 +08:00
hang f8cd361415 添加FusionCache
continuous-integration/drone/push Build is passing
2024-08-21 00:06:36 +08:00
hang 0b1a640c3e 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-08-20 17:58:24 +08:00
hang aa9df5838c 修改添加pacs 影像 2024-08-20 17:58:24 +08:00
he 2edacc9ff5 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-08-20 16:03:18 +08:00
he a9a0a9d307 修改 2024-08-20 16:03:17 +08:00
hang 1937804e47 修改scp bug
continuous-integration/drone/push Build is passing
2024-08-20 15:08:03 +08:00
hang 8e8b55fa46 修改分页列表bug
continuous-integration/drone/push Build is passing
2024-08-20 14:58:35 +08:00
hang 3096671595 数组给默认参数
continuous-integration/drone/push Build is passing
2024-08-20 14:09:01 +08:00
hang a6102490c8 修改项目导表-指定项目导出
continuous-integration/drone/push Build is passing
2024-08-20 14:03:42 +08:00
hang 9e1cc1521f 修改分页参数
continuous-integration/drone/push Build is passing
2024-08-20 13:59:52 +08:00
he a579c26ada 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-08-20 13:50:04 +08:00
he 754da2c7fc 代码修改 2024-08-20 13:50:03 +08:00
hang 995bdee1f6 领域事件添加到测试环境-测试
continuous-integration/drone/push Build is passing
2024-08-20 13:14:06 +08:00
hang a70f661e86 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-08-20 11:17:50 +08:00
hang 8312bfb78b 修改scp 配置文件 2024-08-20 11:17:50 +08:00
he 7194796841 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-08-20 10:56:00 +08:00
he c6918cca46 代码修改 2024-08-20 10:56:00 +08:00
hang be7b38c6ce 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-08-20 10:42:16 +08:00
hang a7ebd50536 修改引用包 2024-08-20 10:42:16 +08:00
he 05f9b81e04 测试发布
continuous-integration/drone/push Build is failing
2024-08-20 10:37:58 +08:00
he 1f9eb9e36b 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-08-20 10:35:39 +08:00
he af46eb2d65 修改 2024-08-20 10:35:37 +08:00
hang d1e54629e7 x
continuous-integration/drone/push Build is failing
2024-08-20 10:25:45 +08:00
hang 78dbe23d0e 修改实体
continuous-integration/drone/push Build is running
2024-08-20 10:25:06 +08:00
hang 4bf93d10b0 暂时屏蔽事件分发
continuous-integration/drone/push Build is failing
2024-08-20 09:39:44 +08:00
hang 00827e9975 增加领域事件定义,增加MassTransit 发布事件
continuous-integration/drone/push Build is failing
2024-08-19 23:32:53 +08:00
hang 021b32587a 修改模板
continuous-integration/drone/push Build is passing
2024-08-19 21:18:28 +08:00
hang 5ffe1675db 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-08-19 17:49:11 +08:00
hang d34eca2cb8 增加 MassTransit 移除 MediatR 2024-08-19 17:49:08 +08:00
hang 12ac7af11e 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-08-19 17:36:45 +08:00
hang a19eb2abca 修改uat scp 数据库配置 2024-08-19 17:36:33 +08:00
hang 4c9a8aadab 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-08-19 16:00:10 +08:00
hang 034058999d 清理后端医生下载接口 2024-08-19 16:00:08 +08:00
he 34ea39e764 修改
continuous-integration/drone/push Build is passing
2024-08-19 15:33:52 +08:00
he 7caf00bd75 修改
continuous-integration/drone/push Build is passing
2024-08-19 15:27:51 +08:00
he aabe604e18 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-08-19 15:22:20 +08:00
he f2bc281e2b 修改 2024-08-19 15:22:19 +08:00
hang 4187a568f8 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-08-19 15:14:38 +08:00
hang 1611554c00 生成全局任务,没有设置VisitTaskNum 2024-08-19 15:14:36 +08:00
he 60fc8f9bce 修改
continuous-integration/drone/push Build is running
2024-08-19 15:14:23 +08:00
he 48eb20fa66 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-08-19 14:22:19 +08:00
he 9e7bc09f84 修改 2024-08-19 14:22:18 +08:00
hang ec9e35180b crc 上传控制pacs
continuous-integration/drone/push Build is passing
2024-08-19 14:03:16 +08:00
hang c757212c07 修改上传配置文件 2024-08-19 14:03:11 +08:00
hang 8415dd2be1 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8 2024-08-19 13:56:02 +08:00
he 17d734ba11 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:24:41 +08:00
he 476387b468 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:19:54 +08:00
he 3a2cb138ab 修改
continuous-integration/drone/push Build is passing
2024-08-19 13:12:04 +08:00
he fa763e6341 修改
continuous-integration/drone/push Build is passing
2024-08-19 11:32:41 +08:00
he c988ca0bca 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-08-19 11:28:05 +08:00
he c257dd4171 字典修改 2024-08-19 11:28:02 +08:00
hang ff026f45fc 优化分页排序和生成模板
continuous-integration/drone/push Build is passing
2024-08-17 20:33:21 +08:00
hang cd2166f11b 数据记录审计方法调整
continuous-integration/drone/push Build is passing
2024-08-17 16:06:35 +08:00
hang 33cfacec84 发布文件 2024-08-16 16:19:58 +08:00
hang 5c2bebf96c 修改验证scp 配置文件
continuous-integration/drone/push Build is passing
2024-08-16 15:56:12 +08:00
hang ef5ae76907 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-08-16 15:42:13 +08:00
hang 7546ba412c dicom ae 提示修改 2024-08-16 15:42:12 +08:00
he 6b536f4a4f 修改IP
continuous-integration/drone/push Build is passing
2024-08-16 15:38:15 +08:00
he a540326031 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-08-16 11:27:52 +08:00
he 45dd2e90c5 修改ip不一样提醒 2024-08-16 11:27:52 +08:00
hang e3188c0419 清理没用的存储代码
continuous-integration/drone/push Build is passing
2024-08-16 10:15:50 +08:00
hang 423fa4001b 修改T4模板
continuous-integration/drone/push Build is passing
2024-08-16 09:54:06 +08:00
hang 3701d8bcd9 精简实体准备
continuous-integration/drone/push Build is passing
2024-08-15 23:53:25 +08:00
hang 0689f731b7 测试修改配置文件拷贝是否生效
continuous-integration/drone/push Build is passing
2024-08-15 17:41:38 +08:00
hang d97025aeca 项目AE修改
continuous-integration/drone/push Build is passing
2024-08-15 17:08:03 +08:00
hang fa929ebde4 邮件配置5s超时
continuous-integration/drone/push Build is passing
2024-08-15 15:29:25 +08:00
hang 32c4d634ed 内部人员 直接pm 可以加pm
continuous-integration/drone/push Build is passing
2024-08-15 14:37:04 +08:00
hang 8d4a791a1c 修改一致性分析增加首次截止全局访视名字
continuous-integration/drone/push Build is passing
2024-08-15 14:02:09 +08:00
hang 59f376e720 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-08-15 11:36:21 +08:00
hang a5017c1571 修改导表文件名处理 2024-08-15 11:36:20 +08:00
he 8767911a16 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-08-15 09:39:27 +08:00
he f1170244da 修改 2024-08-15 09:39:25 +08:00
hang 921c66140f 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-08-15 09:26:49 +08:00
hang 0f2a73cb3c 修改临床数据签名bug 2024-08-15 09:26:46 +08:00
he a16f567ade 修改
continuous-integration/drone/push Build is passing
2024-08-14 17:38:44 +08:00
hang 5e8b5eed9f 取字典的值的时候进行判断
continuous-integration/drone/push Build is passing
2024-08-14 16:52:03 +08:00
hang 682e40febd 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-08-14 16:36:29 +08:00
hang 568ef07438 修改提示错误 2024-08-14 16:36:29 +08:00
he cafdbaac57 修改
continuous-integration/drone/push Build is passing
2024-08-14 16:06:00 +08:00
he 505184b200 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-08-14 15:12:21 +08:00
he 1d7e1be641 修改 2024-08-14 15:12:20 +08:00
hang 8ba22a343a 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-08-14 14:43:51 +08:00
hang ab34c947ca 后端国际化支持,日志记录的信息和返回前端的国际化不一致 2024-08-14 14:43:48 +08:00
he 062387e6a8 修改
continuous-integration/drone/push Build is running
2024-08-14 14:43:25 +08:00
he 161213f2af 修改
continuous-integration/drone/push Build is passing
2024-08-14 13:58:50 +08:00
he c1fcb4f6e3 修改
continuous-integration/drone/push Build is passing
2024-08-14 13:37:22 +08:00
he a9d81f5af5 修改
continuous-integration/drone/push Build is passing
2024-08-14 13:05:35 +08:00
he 2900f2fa7f 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-08-14 11:21:35 +08:00
he 4e44d163f3 修改 2024-08-14 11:21:33 +08:00
hang ffa6d62d3d 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-08-13 17:44:29 +08:00
hang d9ba6a7a89 一致性分析原阅片人修改 2024-08-13 17:44:27 +08:00
he 8e0105b71f 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-08-13 15:26:23 +08:00
he c45461937d 修改 2024-08-13 15:26:23 +08:00
hang b9c9088de2 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-08-13 15:24:18 +08:00
hang a6cfe19139 修改用户类型过滤 2024-08-13 15:24:17 +08:00
he 1f11de4a20 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-08-13 14:53:11 +08:00
he 871333b9e9 修改 2024-08-13 14:53:10 +08:00
hang 47d8ec7576 清理一致性分析任务和配置
continuous-integration/drone/push Build is passing
2024-08-13 09:08:04 +08:00
hang 46a304b5a6 用户 性别可为空
continuous-integration/drone/push Build is passing
2024-08-12 17:42:54 +08:00
hang 098ade3c8a subject 软删除,导致任务列表统计数字问题
continuous-integration/drone/push Build is passing
2024-08-12 16:40:20 +08:00
hang 86489b2117 前端国际化状态修改
continuous-integration/drone/push Build is passing
2024-08-12 15:40:13 +08:00
hang 64b5206f86 项目邮件列表修改
continuous-integration/drone/push Build is passing
2024-08-12 13:35:38 +08:00
hang ea0b7f1eca 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-08-12 13:21:54 +08:00
hang 7e8dd1c6a7 影像质控备注 2024-08-12 13:21:53 +08:00
he d3b8716a66 代码修改
continuous-integration/drone/push Build is passing
2024-08-12 13:01:45 +08:00
hang af77baba60 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-08-09 17:53:40 +08:00
hang 2f1cfc3e67 修改导出逻辑 2024-08-09 17:53:40 +08:00
he 37d15736e2 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-08-09 17:13:07 +08:00
he 5f8045c611 修改全局阅片 2024-08-09 17:13:06 +08:00
hang d62562149c 修改dicomAE 测试状态
continuous-integration/drone/push Build is passing
2024-08-09 15:24:40 +08:00
hang 63e2ca07b5 修改dicomAE 测试
continuous-integration/drone/push Build is passing
2024-08-09 15:01:22 +08:00
he ed94423f32 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-08-09 14:07:57 +08:00
he e705e12656 代码修改 2024-08-09 14:07:56 +08:00
hang 035ce2ae4e 修改邮件
continuous-integration/drone/push Build is pending
2024-08-09 14:07:29 +08:00
hang a1778d836b 设置连接超时时间
continuous-integration/drone/push Build is pending
2024-08-09 13:46:08 +08:00
hang cebcf908f9 修改裁判标价判定
continuous-integration/drone/push Build is passing
2024-08-09 13:12:05 +08:00
hang 202a3c26d1 修改取消分配验证生效的是否开始阅片
continuous-integration/drone/push Build is passing
2024-08-08 14:53:29 +08:00
hang fbbda8c0d1 是否可以取消分配bug
continuous-integration/drone/push Build is passing
2024-08-08 14:49:06 +08:00
hang 7954bdeca8 脑转移 未分配的退回也失效
continuous-integration/drone/push Build is passing
2024-08-08 14:39:53 +08:00
hang d8a0c80ca4 修改模板删除,导表显示名称国际哈
continuous-integration/drone/push Build is passing
2024-08-08 13:49:10 +08:00
hang 100faa3b9f 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-08-08 13:24:18 +08:00
hang 7894a4991c 修改全局导表 2024-08-08 13:24:17 +08:00
he 0405ba4b13 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-08-08 10:31:15 +08:00
he ca6e96929f 修改开始阅片时间 2024-08-08 10:31:14 +08:00
hang b832a66abf 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-08-08 10:14:36 +08:00
hang 168c7447bb 修改bug 2024-08-08 10:14:36 +08:00
he 891c442da4 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-08-07 17:26:03 +08:00
he 74098641f6 休息时间改到配置文件 2024-08-07 17:25:58 +08:00
hang eedfa2add8 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-08-07 16:35:53 +08:00
hang 2838f09268 导表修改 2024-08-07 16:35:52 +08:00
hang ab800d09ca 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-08-07 15:37:52 +08:00
hang 44e4fe3a29 修改中心调研bug 2024-08-07 15:02:20 +08:00
hang d279bad2d0 用户反馈增加查询条件
continuous-integration/drone/push Build is passing
2024-08-07 13:23:50 +08:00
hang a5737073c4 邮件反馈类型错误
continuous-integration/drone/push Build is passing
2024-08-07 10:41:46 +08:00
hang 4a82812b4e 修改导表
continuous-integration/drone/push Build is passing
2024-08-07 10:37:06 +08:00
hang 8ec67d72f1 打开系统反馈
continuous-integration/drone/push Build is passing
2024-08-06 18:04:14 +08:00
hang 405db77dea 修改邮件查询
continuous-integration/drone/push Build is passing
2024-08-06 17:41:40 +08:00
hang 8b8ed1fee3 系统邮件配置修改
continuous-integration/drone/push Build is passing
2024-08-06 16:39:11 +08:00
hang c1e496530d excel 增加英文名字字段
continuous-integration/drone/push Build is passing
2024-08-06 16:07:47 +08:00
hang a43ba04bf3 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-08-06 14:38:31 +08:00
hang 7b78e4b399 20240806 导表修改代码 2024-08-06 14:38:30 +08:00
hang e92ea3ea0c lili 生成任务bug
continuous-integration/drone/push Build is passing
2024-08-06 12:24:19 +08:00
hang 2bb4630351 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-08-05 17:59:27 +08:00
hang ef63c19c93 完成邮件基本逻辑 2024-08-05 17:59:26 +08:00
he cda134e92c 修改
continuous-integration/drone/push Build is passing
2024-08-05 17:09:05 +08:00
he 75d162b353 修改
continuous-integration/drone/push Build is running
2024-08-05 17:08:39 +08:00
he 9cbfb2c7e4 修改
continuous-integration/drone/push Build is running
2024-08-05 17:08:06 +08:00
he a47e20ff74 修改
continuous-integration/drone/push Build is passing
2024-08-05 16:54:59 +08:00
he 36a63d7628 修改
continuous-integration/drone/push Build is passing
2024-08-05 16:20:30 +08:00
he 2217ae0353 修改
continuous-integration/drone/push Build is passing
2024-08-05 15:41:39 +08:00
he 31a444508b 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-08-05 15:35:03 +08:00
he 37c898ea0c 修改 2024-08-05 15:35:02 +08:00
hang 03c2a67fe4 一致性分析任务生成bug
continuous-integration/drone/push Build is passing
2024-08-05 14:55:13 +08:00
hang 795caf19e7 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-08-05 14:41:30 +08:00
hang 99ef28be99 加密方法准备测试 2024-08-05 14:41:30 +08:00
he 97a5eda8f8 一致性分析修改
continuous-integration/drone/push Build is passing
2024-08-05 13:51:20 +08:00
he 2d8cb0c818 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-08-05 13:32:17 +08:00
he 2d1325ca52 代码修改 2024-08-05 13:32:13 +08:00
hang 9f5b8e9858 响应压缩修改压缩级别
continuous-integration/drone/push Build is passing
2024-08-05 10:41:42 +08:00
hang 4eaf070243 撤回 dbcontext 连接池
continuous-integration/drone/push Build is passing
2024-08-02 17:44:45 +08:00
hang c353ae645b dbcontext 上下文池,提高性能测试
continuous-integration/drone/push Build is passing
2024-08-02 17:03:23 +08:00
hang e1038c27f6 修改审核时间修改 2024-08-02 15:41:58 +08:00
hang 994a770fef 用户反馈增加项目过滤
continuous-integration/drone/push Build is passing
2024-08-02 13:58:54 +08:00
hang 1875b56b37 修改用户反馈
continuous-integration/drone/push Build is passing
2024-08-02 13:50:16 +08:00
hang 99eef31202 用户反馈增加数字
continuous-integration/drone/push Build is passing
2024-08-02 13:31:57 +08:00
hang 826f8a670d 邮件模板修改调整
continuous-integration/drone/push Build is passing
2024-08-02 13:25:44 +08:00
hang cb53dbefcf CRC 上传导表
continuous-integration/drone/push Build is passing
2024-08-02 11:48:34 +08:00
hang 9b4e29a812 x
continuous-integration/drone/push Build is passing
2024-08-02 11:28:58 +08:00
hang fa9c9de12c 质控增加字段
continuous-integration/drone/push Build is running
2024-08-02 11:27:51 +08:00
hang c98db93ecb 一致性分析 全局任务 SouceReadModuleId 处理
continuous-integration/drone/push Build is passing
2024-08-02 10:30:33 +08:00
hang eb1dcc9f0a 增加反馈字段
continuous-integration/drone/push Build is passing
2024-08-02 09:54:31 +08:00
hang 63c6c2f67b QCAgreeUpload 才允许修改 2024-08-01 17:24:18 +08:00
hang 62f37a4bb4 crc 重传允许修改部位编辑
continuous-integration/drone/push Build is passing
2024-08-01 17:05:28 +08:00
hang 02a8289ad4 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-08-01 16:57:27 +08:00
hang 7c5f3323de 增加下载信息的接口 2024-08-01 16:57:25 +08:00
he 2149bfa782 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-08-01 16:12:49 +08:00
he 3561df7574 代码修改 2024-08-01 16:12:48 +08:00
hang 9cd4e272c7 遗漏await
continuous-integration/drone/push Build is passing
2024-08-01 13:36:46 +08:00
hang 7069a17d8e 修改参数必传
continuous-integration/drone/push Build is passing
2024-08-01 13:31:53 +08:00
hang 3e5d0b650d 截图给默认值
continuous-integration/drone/push Build is passing
2024-08-01 13:17:23 +08:00
hang a6b8db30c3 scp 传输增加备注
continuous-integration/drone/push Build is passing
2024-08-01 11:48:24 +08:00
hang 613f2d8c6c 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-08-01 10:50:12 +08:00
hang b8e0c74d45 用户反馈增加字段 2024-08-01 10:50:11 +08:00
he 13acd950ad 代码修改
continuous-integration/drone/push Build is failing
2024-08-01 10:39:21 +08:00
he 8ec86017f0 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-08-01 10:35:59 +08:00
he ee43a5dc9d 代码修改 2024-08-01 10:35:57 +08:00
hang e3ee1a42fb 修改dicom 获取tag值 patientId为空
continuous-integration/drone/push Build is passing
2024-08-01 10:12:09 +08:00
hang 9fa24a35ef 记录传输日志
continuous-integration/drone/push Build is passing
2024-07-31 17:42:40 +08:00
hang 0e631e6f29 传递logger
continuous-integration/drone/push Build is passing
2024-07-31 17:36:46 +08:00
hang 622d598392 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-07-31 17:35:03 +08:00
hang 3ab411578e 日志写入到文件 2024-07-31 17:35:03 +08:00
he d1e21a9f4b 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-07-31 16:49:24 +08:00
he cd2ebe700b 代码修改 2024-07-31 16:49:23 +08:00
hang 7f5a3bffd1 完成机构名称默认值
continuous-integration/drone/push Build is passing
2024-07-31 16:11:55 +08:00
hang cdbe74f1d9 根据配置设置用户的机构名称
continuous-integration/drone/push Build is passing
2024-07-31 15:51:38 +08:00
hang de01da975e CalledAE 名字错误
continuous-integration/drone/push Build is passing
2024-07-31 15:13:00 +08:00
hang aae243e36e 项目dicom ae 修改
continuous-integration/drone/push Build is passing
2024-07-31 15:08:28 +08:00
hang d3f7c199c7 防止前端重复上传
continuous-integration/drone/push Build is passing
2024-07-31 14:05:38 +08:00
hang ca41fac53d 有问题,撤回修改
continuous-integration/drone/push Build is passing
2024-07-31 13:44:50 +08:00
hang 6ccbfc466f 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-07-31 13:42:50 +08:00
hang 81aa7fb8ef 上传再次增加判断 2024-07-31 13:42:49 +08:00
he da102dfed2 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-07-31 10:40:44 +08:00
he 63c225fb9b 代码修改 2024-07-31 10:40:40 +08:00
hang f0f6f0bd23 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-07-31 10:01:48 +08:00
hang 52b60338c3 修改隐藏邮箱的算法 2024-07-31 10:01:48 +08:00
hang d3e7b3a8d8 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-07-31 09:35:34 +08:00
hang 48cba94995 邮件称呼修改 2024-07-31 09:35:33 +08:00
hang a2ca3a8245 修改邮件
continuous-integration/drone/push Build is passing
2024-07-31 09:25:54 +08:00
hang d602238f82 hangfire 任务调度隐患排除
continuous-integration/drone/push Build is passing
2024-07-30 16:03:35 +08:00
hang 5f141212f4 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-07-30 15:12:12 +08:00
hang 8b05c01e42 通过配置api 接口,自动将Result 进行加密返回,同时code返回12标注 目前使用base64 2024-07-30 15:12:11 +08:00
he 307ed2ca7f 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-07-30 14:15:51 +08:00
he e9a90a4c3a 修改 2024-07-30 14:15:50 +08:00
hang a9407c3290 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-07-30 11:50:34 +08:00
hang f9fc79d3aa 用户反馈接口初步完成 2024-07-30 11:50:33 +08:00
he ee4b4a62ac 修改
continuous-integration/drone/push Build is passing
2024-07-30 11:30:16 +08:00
he 7d7027a753 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-07-30 11:19:19 +08:00
he e36dd04d3e 修改 2024-07-30 11:19:17 +08:00
hang fd9af47606 验证码修改
continuous-integration/drone/push Build is passing
2024-07-30 09:51:48 +08:00
hang 633507d4cd k8s docker 挂载配置文件热更新问题解决
continuous-integration/drone/push Build is passing
2024-07-29 17:59:01 +08:00
hang 8c94e17c14 删除提示语
continuous-integration/drone/push Build is passing
2024-07-29 16:33:35 +08:00
hang 942f3adfe0 修改scp 上传bug
continuous-integration/drone/push Build is running
2024-07-29 16:33:00 +08:00
hang 3b92aaf61c 修改国际化 和 scp 缩略图日志
continuous-integration/drone/push Build is passing
2024-07-29 16:24:34 +08:00
he 4f5d89732d 代码提交
continuous-integration/drone/push Build is passing
2024-07-29 15:13:15 +08:00
he 55bb70179c 代码修改
continuous-integration/drone/push Build is passing
2024-07-29 14:19:03 +08:00
he 6c9c8ee5dc 修改
continuous-integration/drone/push Build is passing
2024-07-29 14:00:40 +08:00
hang 73e9e3239a 修改us配置文件
continuous-integration/drone/push Build is passing
2024-07-29 11:47:32 +08:00
he 8d67a3be5f 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-07-29 10:43:26 +08:00
he 5175c857ec 代码提交 2024-07-29 10:43:24 +08:00
hang d2a9f478e4 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-07-26 15:26:29 +08:00
hang 9f32b92af3 邮件上线到系统配置 2024-07-26 15:26:28 +08:00
he 880525b015 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-07-26 10:16:11 +08:00
he 0536a57075 代码修改 2024-07-26 10:16:08 +08:00
hang abb3b02e74 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-07-26 09:04:34 +08:00
hang cad7132b0a 通过相对路径获取授权签名 2024-07-26 09:04:34 +08:00
hang c6e5d31244 重阅自动失效,错误消息位置改变
continuous-integration/drone/push Build is passing
2024-07-25 17:05:52 +08:00
hang b0302d0e6d 同意重阅,成功,但是给出自动失效的提示 2024-07-25 17:05:49 +08:00
hang 9a958276db 修改项目部位bug
continuous-integration/drone/push Build is passing
2024-07-25 16:41:42 +08:00
hang 44bcdf7973 系统邮件上线到配置预修改
continuous-integration/drone/push Build is passing
2024-07-25 14:46:13 +08:00
hang 6311884a5c dicom AE 浏览器推荐 发布记录 国际化
continuous-integration/drone/push Build is passing
2024-07-25 12:22:56 +08:00
hang de5fc7c277 修改,无序重阅 和审批
continuous-integration/drone/push Build is passing
2024-07-25 10:12:09 +08:00
he 3414c50975 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-07-24 16:05:29 +08:00
he 39736c3ce4 修改 2024-07-24 16:05:27 +08:00
hang 14fb158e13 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-07-24 15:05:09 +08:00
hang 81f55a9e07 医学审核列表,查询优化 2024-07-24 15:05:07 +08:00
he 94e942e344 代码修改
continuous-integration/drone/push Build is passing
2024-07-24 14:46:49 +08:00
he 95fbe6085a 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-07-24 13:33:49 +08:00
he 4f4dda7a09 格式化 2024-07-24 13:33:48 +08:00
hang 8021d6a860 防止生成sql生成GETDATE() 时区导致的问题
continuous-integration/drone/push Build is passing
2024-07-24 09:54:43 +08:00
hang 3cdfd3a771 修改dicom ae 接口
continuous-integration/drone/push Build is passing
2024-07-23 15:35:49 +08:00
hang 76792a127f 整体肿瘤评估导表修改
continuous-integration/drone/push Build is passing
2024-07-23 14:58:40 +08:00
hang fc36cbcb75 修改Dicom 推送
continuous-integration/drone/push Build is passing
2024-07-23 10:35:38 +08:00
hang 3fab377454 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-07-22 15:41:17 +08:00
hang 5246c10e32 处理检查删除、添加、维护绑定关系 2024-07-22 15:41:16 +08:00
he 63530b7847 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-07-22 15:20:21 +08:00
he 99be08dc20 修改 2024-07-22 15:20:18 +08:00
hang 9898673dbf 修改study查询bug
continuous-integration/drone/push Build is passing
2024-07-22 14:04:56 +08:00
hang d7f0fdd0e7 oss 下载走内网地址
continuous-integration/drone/push Build is passing
2024-07-19 16:12:59 +08:00
hang 795cb0aba2 修改非dicom 监控上传 2024-07-19 13:17:54 +08:00
hang 32ba46206b 增加ACC number
continuous-integration/drone/push Build is passing
2024-07-18 15:18:40 +08:00
hang 22c9386101 修改测试AE
continuous-integration/drone/push Build is passing
2024-07-18 10:55:47 +08:00
hang ff4136e02d 修改AE 配置文件
continuous-integration/drone/push Build is passing
2024-07-18 10:32:27 +08:00
hang 04cccf1174 Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8 2024-07-18 10:10:13 +08:00
he ab9203eef0 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-07-18 10:05:29 +08:00
he 924ba90384 添加高亮 2024-07-18 10:05:26 +08:00
hang 353b2c99cb url 解码下载修改 2024-07-17 18:00:39 +08:00
hang 0b3542e9c3 自动计算患者年龄
continuous-integration/drone/push Build is passing
2024-07-17 14:52:53 +08:00
hang 425bd7bf9a 修改查询列表
continuous-integration/drone/push Build is passing
2024-07-17 14:44:37 +08:00
hang e0aa9fb1d9 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-07-17 14:20:38 +08:00
hang c65a484b13 增加患者信息查询,和Modality查询 2024-07-17 14:20:36 +08:00
he d9fc5e3646 添加上一次任务的答案
continuous-integration/drone/push Build is passing
2024-07-17 13:37:01 +08:00
he d72f3e89a2 代码修改
continuous-integration/drone/push Build is passing
2024-07-17 11:06:47 +08:00
he 85a303171c 修改
continuous-integration/drone/push Build is passing
2024-07-17 10:52:54 +08:00
he 4026eca656 修改 2024-07-17 10:52:20 +08:00
he 74aec46a94 返回值修改 2024-07-17 10:52:02 +08:00
he 49e21a6342 加返回参数 2024-07-17 10:51:58 +08:00
he 0e0dd0c7d3 跳过阅片修改 2024-07-17 10:51:26 +08:00
hang 8fedcdaf00 检查列表增加查询 区分是否来自Pacs
continuous-integration/drone/push Build is passing
2024-07-16 17:30:01 +08:00
hang 9924375f82 下拉框增加参数
continuous-integration/drone/push Build is passing
2024-07-16 16:13:57 +08:00
hang a60661aaa5 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-07-16 16:09:23 +08:00
hang 5041ebd58b 增加项目Id 查询条件 2024-07-16 16:09:22 +08:00
he 594574c846 添加基线的长径短径
continuous-integration/drone/push Build is passing
2024-07-16 15:43:04 +08:00
hang 6e7545be65 返回配置字段
continuous-integration/drone/push Build is passing
2024-07-16 15:28:04 +08:00
hang b77d2d9160 减少压缩包访视层级,同时处理单个非dicom 特殊情况压缩包处理
continuous-integration/drone/push Build is passing
2024-07-15 17:12:01 +08:00
hang 0c94ef86b0 增加打包下载验证
continuous-integration/drone/push Build is passing
2024-07-15 16:27:06 +08:00
hang e0c6e9aabf 修改ivus影像下载功能
continuous-integration/drone/push Build is passing
2024-07-15 15:52:52 +08:00
hang 814f1e576a 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-07-12 13:52:46 +08:00
hang d62d2770f4 修改scp 配置文件 2024-07-12 13:52:45 +08:00
he cec678a24b 提示语修改
continuous-integration/drone/push Build is failing
2024-07-12 10:31:53 +08:00
he 7baf301785 配置文件修改 2024-07-12 10:31:51 +08:00
he ded0dbaa2d 阅片时间修改到配置文件 2024-07-12 10:31:47 +08:00
hang 8c16bc2ac5 修改管道名字
continuous-integration/drone/push Build is passing
2024-07-11 17:01:50 +08:00
hang 0827ede4b6 增加irc-scp发布配置 2024-07-11 16:59:58 +08:00
hang 239e0b84c2 study net8 自动打包配置 2024-07-11 16:12:19 +08:00
hang 73b77a477a 修改发布文件 2024-07-11 15:29:40 +08:00
hang c032c42321 增加用户机构默认值修改
continuous-integration/drone/push Build is passing
2024-07-11 10:16:02 +08:00
hang cb7140ad38 修改国际化查询
continuous-integration/drone/push Build is passing
2024-07-11 09:20:15 +08:00
hang 29ea2a0ef1 增加国际化
continuous-integration/drone/push Build is passing
2024-07-10 17:42:39 +08:00
hang 46af71e3df 增加uat irc 自动打包成镜像
continuous-integration/drone/push Build is passing
2024-07-10 16:47:25 +08:00
hang 67819fc85d 组件一致性分析筛选条件修改
continuous-integration/drone/push Build is passing
2024-07-10 14:00:04 +08:00
hang 4b15bcdc55 打开后端正式环境验证
continuous-integration/drone/push Build is passing
2024-07-10 10:48:20 +08:00
hang 0ba439e5bd 修改发件箱配置
continuous-integration/drone/push Build is passing
2024-07-10 09:10:10 +08:00
hang c25c855b46 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-07-10 09:08:42 +08:00
hang 003b227f7d 修改发送邮件提示 2024-07-10 09:08:41 +08:00
he 461976f6d3 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-07-09 17:21:17 +08:00
he 7636c82b11 代码修改 2024-07-09 17:21:16 +08:00
hang d1e4863e01 修改签名bug
continuous-integration/drone/push Build is passing
2024-07-09 17:03:20 +08:00
hang d483aca73b 增加映射
continuous-integration/drone/push Build is passing
2024-07-09 16:27:07 +08:00
hang cf45169de2 修改返回
continuous-integration/drone/push Build is passing
2024-07-09 16:16:10 +08:00
hang 0075c18cd8 修改返回的信息
continuous-integration/drone/push Build is passing
2024-07-09 14:56:47 +08:00
hang e55bc5fe7a 增加查询映射
continuous-integration/drone/push Build is passing
2024-07-09 14:25:34 +08:00
hang e6bd7ad0ea 修改pacs 配置
continuous-integration/drone/push Build is passing
2024-07-09 14:20:00 +08:00
hang a98bc37045 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-07-09 13:14:13 +08:00
hang 06209a945d 修改发送邮件配置 2024-07-09 13:13:50 +08:00
hang d5c628d916 修改发件箱 2024-07-09 13:13:46 +08:00
hang 905fdd9861 修改美国irc uat 数据库名称 2024-07-09 13:13:41 +08:00
he 3ff95ede2c 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-07-08 16:21:59 +08:00
he f9734dc5cc 修改 2024-07-08 16:21:58 +08:00
hang c32ec2f132 美国验证增加配置文件
continuous-integration/drone/push Build is passing
2024-07-08 11:38:47 +08:00
hang 28c3adaf64 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-07-05 10:24:11 +08:00
hang 6435746660 修改配置文件 2024-07-05 10:24:11 +08:00
he c6531e9249 代码修改
continuous-integration/drone/push Build is passing
2024-07-05 10:00:35 +08:00
hang b1be0e2a98 修改配置文件 2024-07-05 09:19:00 +08:00
hang 31d22e2b4f 增加美国生产环境配置文件 2024-07-05 09:18:56 +08:00
he 1e5f01fdeb 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-07-05 09:09:08 +08:00
he 213787bbcf 代码修改 2024-07-05 09:08:54 +08:00
hang 933a43f4ea 返回推荐的版本
continuous-integration/drone/push Build is passing
2024-07-04 17:24:29 +08:00
hang 6264d105ab 浏览器推荐修改
continuous-integration/drone/push Build is passing
2024-07-04 17:22:54 +08:00
hang 0c7495870b pacs 直连 增加修改
continuous-integration/drone/push Build is passing
2024-07-04 13:12:10 +08:00
hang a615b5cefd site dicomAE 提交
continuous-integration/drone/push Build is passing
2024-07-03 14:45:24 +08:00
hang 9f66a932fc 增加pacs 直连 scp项目
continuous-integration/drone/push Build is passing
2024-07-03 14:00:29 +08:00
hang d094f22ab2 pacs 直连修改
continuous-integration/drone/push Build is passing
2024-07-02 17:20:32 +08:00
hang 5cc41b3b0f 修改一致性核查颜色 2024-07-02 17:20:05 +08:00
hang 27b99eb3be 增加接口返回路径信息
continuous-integration/drone/push Build is passing
2024-07-02 11:08:11 +08:00
hang e324850811 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-07-02 09:45:19 +08:00
hang 7c3b0e9e72 浏览器版本推荐 --迁移 2024-07-02 09:45:18 +08:00
he 709529da87 关键序列修改
continuous-integration/drone/push Build is passing
2024-07-02 09:36:15 +08:00
hang 2354ee9174 修改一致性分析和临床数据
continuous-integration/drone/push Build is passing
2024-07-01 15:40:13 +08:00
hang f158f092ce 修改一致性分析 以及项目部位编辑
continuous-integration/drone/push Build is passing
2024-07-01 14:54:15 +08:00
he f446d400a1 修改
continuous-integration/drone/push Build is passing
2024-07-01 13:46:54 +08:00
he 5b0026f30f 修改
continuous-integration/drone/push Build is passing
2024-07-01 13:41:55 +08:00
he 1efd41e7ac 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-07-01 11:50:24 +08:00
he 76c6e8442a 修改 2024-07-01 11:50:23 +08:00
hang f92ace1894 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-06-28 11:30:22 +08:00
hang 4585b7b732 一致性分析筛选+ 退回和重阅增加APM角色 2024-06-28 11:30:20 +08:00
he ae2907ad5d 修改
continuous-integration/drone/push Build is passing
2024-06-28 10:19:34 +08:00
he 1a3ad4f602 修改
continuous-integration/drone/push Build is passing
2024-06-28 09:35:54 +08:00
he 9c95928add 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-06-27 16:02:31 +08:00
he 10380994a4 修改 2024-06-27 16:02:29 +08:00
hang 49993edb37 修改国际化查询
continuous-integration/drone/push Build is passing
2024-06-27 15:38:00 +08:00
hang 3efc40e9ae 修改发布版本降序排
continuous-integration/drone/push Build is passing
2024-06-27 15:33:18 +08:00
hang 4922ffa5c3 国际化增加 版本字段展示
continuous-integration/drone/push Build is passing
2024-06-27 15:31:03 +08:00
hang c7935ee90f 修改限制当前版本
continuous-integration/drone/push Build is passing
2024-06-27 15:25:48 +08:00
hang a91a706e0b 修改数据库模型
continuous-integration/drone/push Build is passing
2024-06-27 15:17:32 +08:00
hang a16fbc187a 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-06-27 14:34:09 +08:00
hang 4a314f2070 修改BM 统计 2024-06-27 14:34:09 +08:00
he 27d9104607 修改
continuous-integration/drone/push Build is passing
2024-06-27 14:25:20 +08:00
he acad258319 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-06-27 14:21:33 +08:00
he ba8f22f260 修改 2024-06-27 14:21:32 +08:00
hang f524aa5e57 发布测试环境对接
continuous-integration/drone/push Build is passing
2024-06-27 13:18:41 +08:00
he 5c9664ec7d 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-06-26 09:10:21 +08:00
he be27376dde 添加 Lugano 2014 Without PET 2024-06-26 09:10:20 +08:00
hang 452535b561 中心调研修改
continuous-integration/drone/push Build is passing
2024-06-25 10:52:16 +08:00
hang 9048963ea5 修改字段名
continuous-integration/drone/push Build is passing
2024-06-25 10:28:18 +08:00
hang d3ab051a39 spm cpm 返回增加字段
continuous-integration/drone/push Build is passing
2024-06-25 10:26:30 +08:00
hang 73edbe8fd3 删掉邮件日志组件
continuous-integration/drone/push Build is passing
2024-06-25 09:17:48 +08:00
hang de70f68640 发送邮件版本退回
continuous-integration/drone/push Build is passing
2024-06-24 17:46:37 +08:00
hang 97b97a164d 修改发送邮件版本
continuous-integration/drone/push Build is passing
2024-06-24 17:37:35 +08:00
hang fb87f4d06a 版本退回
continuous-integration/drone/push Build is passing
2024-06-24 17:26:20 +08:00
hang 20092d6757 升级邮件发送包
continuous-integration/drone/push Build is passing
2024-06-24 17:21:15 +08:00
hang 96c4165cda 修改 界面控制bug
continuous-integration/drone/push Build is passing
2024-06-24 16:54:11 +08:00
hang a4226d4e2f 修改筛选条件
continuous-integration/drone/push Build is passing
2024-06-24 16:28:20 +08:00
hang f97565d9d8 医生入组,没有spm修改逻辑
continuous-integration/drone/push Build is passing
2024-06-24 16:07:41 +08:00
hang ab84e66fe4 国际化修改,增加批量更新接口
continuous-integration/drone/push Build is passing
2024-06-24 10:51:23 +08:00
hang 1f9d29e005 版本历史功能增加
continuous-integration/drone/push Build is passing
2024-06-24 10:13:03 +08:00
hang 8521b0c28c 增加清理跟踪的方法
continuous-integration/drone/push Build is passing
2024-06-20 17:50:17 +08:00
hang 26a62426f0 修改发布方式
continuous-integration/drone/push Build is passing
2024-06-20 15:08:47 +08:00
hang 1246413e30 修改nonedicom过滤
continuous-integration/drone/push Build is passing
2024-06-19 19:38:16 +08:00
hang f50b5819c0 修改过滤规则
continuous-integration/drone/push Build is passing
2024-06-19 18:40:32 +08:00
hang 6db8d61b7c 修改 非dicom 检查过滤
continuous-integration/drone/push Build is passing
2024-06-19 17:57:40 +08:00
hang 58250fe993 非dicom zip过滤
continuous-integration/drone/push Build is passing
2024-06-19 16:57:08 +08:00
hang 6cae7a1ae4 修改非dicom 文件上传 增加文件类型
continuous-integration/drone/push Build is passing
2024-06-19 15:17:55 +08:00
hang 73541efbf4 uat 截图修改配置文件
continuous-integration/drone/push Build is passing
2024-06-19 14:17:35 +08:00
hang f4bd891deb 记录最新登录时间
continuous-integration/drone/push Build is passing
2024-06-19 13:48:59 +08:00
hang a9831657cc 修改Uat IRC 配置
continuous-integration/drone/push Build is passing
2024-06-19 13:11:20 +08:00
hang 500a9fbaca 修改配置文件
continuous-integration/drone/push Build is passing
2024-06-19 09:08:17 +08:00
hang 5f11c3a602 修改site 启用时间逻辑
continuous-integration/drone/push Build is passing
2024-06-18 19:36:57 +08:00
hang 7680e90d65 修改添加trialSite逻辑
continuous-integration/drone/push Build is passing
2024-06-18 19:28:26 +08:00
hang 06a57cd056 修改中心调样cpm bug
continuous-integration/drone/push Build is passing
2024-06-18 15:09:52 +08:00
hang 7626d17540 记录邮件异常
continuous-integration/drone/push Build is passing
2024-06-18 13:28:40 +08:00
hang 344b92c427 修改配置文件
continuous-integration/drone/push Build is passing
2024-06-18 13:16:26 +08:00
hang 4719177009 时间环境配置修改
continuous-integration/drone/push Build is passing
2024-06-18 11:53:17 +08:00
hang c1461633ce 修改中心调研国际化
continuous-integration/drone/push Build is passing
2024-06-18 11:10:18 +08:00
hang 6be7aa1ad9 修改默认值
continuous-integration/drone/push Build is passing
2024-06-18 10:28:10 +08:00
hang 4da7c2f960 irc minio 修改配置文件
continuous-integration/drone/push Build is passing
2024-06-17 11:48:09 +08:00
hang 47a45df610 修改mfa 配置
continuous-integration/drone/push Build is passing
2024-06-17 10:38:42 +08:00
hang 1a44e48b2d 删除备注
continuous-integration/drone/push Build is passing
2024-06-17 08:59:53 +08:00
hang c566a703eb 修改trialSitte Id 问题
continuous-integration/drone/push Build is passing
2024-06-14 16:04:12 +08:00
hang 001c248cb8 中心调研返回项目modality
continuous-integration/drone/push Build is passing
2024-06-14 15:35:08 +08:00
hang 654462fe6b 插入字符串efbug
continuous-integration/drone/push Build is passing
2024-06-14 14:34:18 +08:00
hang ab6642ce33 过滤检查
continuous-integration/drone/push Build is passing
2024-06-14 14:29:55 +08:00
hang 946386ad43 检查技术修改
continuous-integration/drone/push Build is passing
2024-06-14 13:46:30 +08:00
hang cf9c79a928 过滤失效的任务
continuous-integration/drone/push Build is passing
2024-06-14 13:28:42 +08:00
hang 493e4e8dca 枚举不能识别
continuous-integration/drone/push Build is passing
2024-06-14 11:05:07 +08:00
hang ecbe8434f3 修改编译问题
continuous-integration/drone/push Build is passing
2024-06-14 10:55:52 +08:00
he 644fe1bd3c 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-06-14 10:52:02 +08:00
he 870fca2e93 修改 2024-06-14 10:52:01 +08:00
hang 6207fb5006 修改MFA 接口
continuous-integration/drone/push Build is failing
2024-06-14 10:38:58 +08:00
hang ae913d8213 修改中心调研国际化
continuous-integration/drone/push Build is passing
2024-06-14 09:18:06 +08:00
hang ce969822a0 字段名错误
continuous-integration/drone/push Build is passing
2024-06-13 17:42:49 +08:00
hang 4fc311d4a5 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-06-13 17:42:05 +08:00
hang 2b424ff45c site 调研增加配置字段 2024-06-13 17:42:04 +08:00
he e5d9cfc50e 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-06-13 17:35:19 +08:00
he ac3552818b 修改 2024-06-13 17:35:18 +08:00
hang c004741f95 上传下载 改为不为空
continuous-integration/drone/push Build is passing
2024-06-13 17:08:09 +08:00
hang 2bdc0c7704 修改siteName 国际化
continuous-integration/drone/push Build is passing
2024-06-13 14:57:38 +08:00
hang 35d90d56dd 修改过滤
continuous-integration/drone/push Build is passing
2024-06-13 09:25:26 +08:00
hang f14525ea95 减少赋值字段
continuous-integration/drone/push Build is failing
2024-06-12 17:24:51 +08:00
hang c2350f1418 影像筛选逻辑增加
continuous-integration/drone/push Build is passing
2024-06-12 17:10:22 +08:00
hang 4b8b02fa55 重构检查列表
continuous-integration/drone/push Build is passing
2024-06-12 16:14:14 +08:00
hang 62102b8b03 重构检查列表
continuous-integration/drone/push Build is failing
2024-06-12 16:10:49 +08:00
hang 0655318d2d 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-06-12 15:44:00 +08:00
hang 0bd2a10091 修改受试者无序阅片 2024-06-12 15:44:00 +08:00
he ce11788878 修改
continuous-integration/drone/push Build is passing
2024-06-12 15:32:17 +08:00
he 0cb74296c3 修改
continuous-integration/drone/push Build is passing
2024-06-12 15:01:23 +08:00
hang def08b72ca 修改返回列表
continuous-integration/drone/push Build is passing
2024-06-12 14:22:01 +08:00
hang 1ef8d2913b 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 failing
2024-06-12 14:11:12 +08:00
hang 7e18b1287e 优化代码 2024-06-12 14:11:11 +08:00
he fdcb6ad12f 修改
continuous-integration/drone/push Build is failing
2024-06-12 14:08:18 +08:00
hang 988bf0e92c 修改任务查询
continuous-integration/drone/push Build is passing
2024-06-12 14:03:38 +08:00
he f6612286d9 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-06-12 13:45:18 +08:00
he c21845c60d 修改 2024-06-12 13:45:17 +08:00
805 changed files with 117628 additions and 45304 deletions
+4
View File
@@ -0,0 +1,4 @@
FROM registry.cn-shanghai.aliyuncs.com/extimaging/aspnetcore:v8.2
WORKDIR /app
COPY publish .
ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]
@@ -0,0 +1,37 @@
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
namespace IRaCIS.Core.SCP.Filter
{
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
{
public IStringLocalizer _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)));
}
}
}
}
@@ -0,0 +1,28 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace IRaCIS.Core.SCP.Filter
{
#region snippet_DisableFormValueModelBindingAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
//factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
#endregion
}
@@ -0,0 +1,61 @@
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.SCP.Filter
{
public class ProjectExceptionFilter : Attribute, IExceptionFilter
{
private readonly ILogger<ProjectExceptionFilter> _logger;
public IStringLocalizer _localizer;
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
{
_logger = logger;
_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;
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code));
}
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));
}
else
{
//继续
}
context.ExceptionHandled = true;//标记当前异常已经被处理过了
}
}
}
@@ -0,0 +1,120 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
namespace IRaCIS.Core.Application.Service.BusinessFilter
{
/// <summary>
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
/// by zhouhang 2021.09.12 周末
/// </summary>
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{
/// <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)
{
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
//是200 并且没有包装 那么包装结果
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
{
//if (objectResult.Value == null)
//{
// var apiResponse = ResponseOutput.DBNotExist();
// objectResult.Value = apiResponse;
// objectResult.DeclaredType = apiResponse.GetType();
//}
//else
//{
var type = objectResult.Value?.GetType();
if ( type!=null&& type.IsGenericType&&(type.GetGenericTypeDefinition()==typeof(ValueTuple<,>)|| type.GetGenericTypeDefinition()==typeof(Tuple<,>)))
{
//报错
//var tuple = (object, object))objectResult.Value;
//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();
}
//}
}
//如果不是200 是IResponseOutput 不处理
else if (statusCode != 200 && (objectResult.Value is IResponseOutput))
{
}
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;
}
}
}
+62
View File
@@ -0,0 +1,62 @@
using FellowOakDicom.Imaging;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System.Security.Cryptography;
using System.Text;
namespace IRaCIS.Core.Application.Helper;
public static class ImageHelper
{
// 采用ImageSharp组件 跨平台,不依赖windows 平台图像处理组件,这里大坑(net 6 下,之前由于Dicom处理最新组件 依赖了这个库的一个旧版本,导致缩略图bug,单独升级依赖组件才解决)
public static void ResizeSave(string filePath, string? fileStorePath)
{
fileStorePath = fileStorePath ?? filePath + ".preview.jpeg";
using (var image = SixLabors.ImageSharp.Image.Load(filePath))
{
image.Mutate(x => x.Resize(500, 500));
image.Save(fileStorePath);
}
}
public static Stream RenderPreviewJpeg(string filePath)
{
string jpegPath = filePath + ".preview.jpg";
if (!File.Exists(jpegPath))
{
using (Stream stream = new FileStream(jpegPath, FileMode.Create))
{
DicomImage image = new DicomImage(filePath);
var sharpimage = image.RenderImage().AsSharpImage();
sharpimage.Save(stream, new JpegEncoder());
}
}
return new FileStream(jpegPath, FileMode.Open);
}
public static void RemovePreviewJpeg(string filePath)
{
string jpegPath = filePath + ".preview.jpg";
if (File.Exists(jpegPath)) File.Delete(jpegPath);
}
}
@@ -0,0 +1,57 @@
using Autofac;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Http;
using Panda.DynamicWebApi;
using System;
using System.Linq;
using System.Reflection;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Application.Service;
using AutoMapper;
using IRaCIS.Core.SCP.Service;
namespace IRaCIS.Core.SCP
{
// ReSharper disable once IdentifierTypo
public class AutofacModuleSetup : Autofac.Module
{
protected override void Load(ContainerBuilder containerBuilder)
{
#region byzhouhang 20210917 Domain层 Infra.EFcore
containerBuilder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>)).InstancePerLifetimeScope();//注册泛型仓储
containerBuilder.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
#endregion
#region autofac https://www.cnblogs.com/xwhqwer/p/15320838.html
//获取所有控制器类型并使用属性注入
containerBuilder.RegisterAssemblyTypes(typeof(BaseService).Assembly)
.Where(type => typeof(IDynamicWebApi).IsAssignableFrom(type))
.PropertiesAutowired();
#endregion
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + typeof(BaseService).Assembly.GetName().Name+".dll");
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
.PropertiesAutowired().AsImplementedInterfaces();
//containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
//containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
}
}
}
+64
View File
@@ -0,0 +1,64 @@
using EntityFramework.Exceptions.SqlServer;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading;
using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.SCP
{
public static class EFSetup
{
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
{
services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>();
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
services.AddDbContext<IRaCISDBContext>((sp, options) =>
{
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
options.UseLoggerFactory(logFactory);
options.UseExceptionProcessor();
options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
options.UseProjectables();
});
//// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
//services.AddScoped<IRaCISDBScopedFactory>();
//// Finally, arrange for a context to get injected from our Scoped factory:
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
//注意区分 easy caching 也有 IDistributedLockProvider
services.AddSingleton<IDistributedLockProvider>(sp =>
{
//var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
});
}
}
}
@@ -0,0 +1,59 @@
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
namespace IRaCIS.Core.SCP
{
public static class NewtonsoftJsonSetup
{
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddScoped<IOSSService,OSSService>();
builder.AddNewtonsoftJson(options =>
{
//options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
//处理返回给前端 可空类型 给出默认值 比如in? 为null 设置 默认值0
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); //new DefaultContractResolver();// new NullToEmptyStringResolver();
// 设置时间格式
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
//options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
})
.AddControllersAsServices()//动态webApi属性注入需要
.ConfigureApiBehaviorOptions(o =>
{
o.SuppressModelStateInvalidFilter = true; //自己写验证
});
Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
//日期类型默认格式化处理
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return setting;
});
}
}
}
@@ -0,0 +1,36 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
namespace IRaCIS.Core.SCP
{
public class NullToEmptyStringResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
var list= type.GetProperties()
.Select(p =>
{
var jp = base.CreateProperty(p, memberSerialization);
jp.ValueProvider = new NullToEmptyStringValueProvider(p);
return jp;
}).ToList();
var uu = list.Select(t => t.PropertyName).ToList();
//获取复杂对象属性
properties = properties.TakeWhile(t => !uu.Contains(t.PropertyName)).ToList();
list.AddRange(properties);
return list;
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Reflection;
using Newtonsoft.Json.Serialization;
namespace IRaCIS.Core.SCP
{
public class NullToEmptyStringValueProvider : IValueProvider
{
PropertyInfo _MemberInfo;
public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
{
_MemberInfo = memberInfo;
}
public object GetValue(object target)
{
object result = _MemberInfo.GetValue(target);
if (_MemberInfo.PropertyType == typeof(string) && result == null) result = "";
else if (_MemberInfo.PropertyType == typeof(String[]) && result == null) result = new string[] { };
//else if (_MemberInfo.PropertyType == typeof(Nullable<Int32>) && result == null) result = 0;
else if (_MemberInfo.PropertyType == typeof(Nullable<Decimal>) && result == null) result = 0.00M;
return result;
}
public void SetValue(object target, object value)
{
if(_MemberInfo.PropertyType == typeof(string))
{
//去掉前后空格
_MemberInfo.SetValue(target, value==null?string.Empty: value.ToString()==string.Empty? value:value.ToString().Trim());
}
else
{
_MemberInfo.SetValue(target, value);
}
}
}
}
+39
View File
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
<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.SqlServer" Version="1.0.5" />
<PackageReference Include="fo-dicom" Version="5.1.3" />
<PackageReference Include="fo-dicom.Codecs" Version="5.14.5" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Minio" Version="6.0.3" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Domain\IRaCIS.Core.Domain.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
</Project>
+219
View File
@@ -0,0 +1,219 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using AutoMapper.EquivalencyExpression;
using FellowOakDicom;
using FellowOakDicom.Imaging;
using FellowOakDicom.Imaging.NativeCodec;
using FellowOakDicom.Network;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.SCP;
using IRaCIS.Core.SCP.Filter;
using IRaCIS.Core.SCP.Service;
using MassTransit;
using MassTransit.NewIdProviders;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using Panda.DynamicWebApi;
using Serilog;
using Serilog.Events;
using System.Runtime.InteropServices;
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
var config = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
EnvironmentName = enviromentName
});
#region windows
int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--port"));
if (urlsIndex > -1)
{
var port = args[urlsIndex].Substring("--port=".Length);
Console.WriteLine(port);
builder.WebHost.UseUrls($"http://0.0.0.0:{port}");
}
#endregion
#region
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
builder.Configuration.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterModule<AutofacModuleSetup>();
})
.UseSerilog();
#endregion
#region
var _configuration = builder.Configuration;
//健康检查
builder.Services.AddHealthChecks();
//本地化
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
builder.Services.AddControllers(options =>
{
options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>();
})
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
builder.Services.AddOptions().Configure<DicomSCPServiceOption>(_configuration.GetSection("DicomSCPServiceConfig"));
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
//动态webApi 目前存在的唯一小坑是生成api上服务上的动态代理AOP失效 间接掉用不影响
builder.Services
.AddDynamicWebApi(dynamicWebApiOption =>
{
//默认是 api
dynamicWebApiOption.DefaultApiPrefix = "";
//首字母小写
dynamicWebApiOption.GetRestFulActionName = (actionName) => char.ToLower(actionName[0]) + actionName.Substring(1);
//删除 Service后缀
dynamicWebApiOption.RemoveControllerPostfixes.Add("Service");
});
//AutoMapper
builder.Services.AddAutoMapper(automapper =>
{
automapper.AddCollectionMappers();
}, typeof(BaseService).Assembly);
//EF ORM QueryWithNoLock
builder.Services.AddEFSetup(_configuration);
builder.Services.AddMediator(cfg =>
{
});
//转发头设置 获取真实IP
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
//Dicom影像渲染图片 跨平台
//builder.Services.AddDicomSetup();
new DicomSetupBuilder()
.RegisterServices(s =>
s.AddFellowOakDicom()
.AddTranscoderManager<NativeTranscoderManager>()
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
.AddImageManager<ImageSharpImageManager>())
.SkipValidation()
.Build();
#endregion
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
//{
app.UseSwagger();
app.UseSwaggerUI();
//}
app.UseAuthorization();
app.MapControllers();
#region
//Log.Logger = new LoggerConfiguration()
// .MinimumLevel.Information()
// .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
// // Filter out ASP.NET Core infrastructre logs that are Information and below 日志太多了 一个请求 记录好几条
// .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
// .MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
// .MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
// .Enrich.WithClientIp()
// .Enrich.FromLogContext()
// //控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型
// .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning,
// outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
// .WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day,
// outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
// .CreateLogger();
Log.Logger = new LoggerConfiguration()
//.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.WriteTo.Console()
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
#endregion
#region
Log.Logger.Warning($"当前环境:{enviromentName}");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Log.Logger.Warning($"当前部署平台环境:windows");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Log.Logger.Warning($"当前部署平台环境:linux");
}
else
{
Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD");
}
#endregion
var logger = app.Services.GetService<Microsoft.Extensions.Logging.ILogger<Program>>();
var server = DicomServerFactory.Create<CStoreSCPService>(_configuration.GetSection("DicomSCPServiceConfig").GetValue<int>("ServerPort"), userState: app.Services,logger: logger);
app.Run();
@@ -0,0 +1,25 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"Test_IRC_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
}
},
"Uat_IRC_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Uat_IRC_SCP"
}
}
}
}
+111
View File
@@ -0,0 +1,111 @@
using AutoMapper;
using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Localization;
using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.Domain.Models;
namespace IRaCIS.Core.SCP.Service
{
#pragma warning disable CS8618
#region
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
public class BaseService : IBaseService, IDynamicWebApi
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
public IStringLocalizer _localizer { get; set; }
public IWebHostEnvironment _hostEnvironment { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{
return new ResponseOutput<string>()
.NotOk($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused", code: ApiResponseCodeEnum.DataNotExist);
}
}
public interface IBaseService
{
[MemberNotNull(nameof(_mapper))]
public IMapper _mapper { get; set; }
[MemberNotNull(nameof(_userInfo))]
public IUserInfo _userInfo { get; set; }
[MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; }
[MemberNotNull(nameof(_hostEnvironment))]
public IWebHostEnvironment _hostEnvironment { get; set; }
}
#endregion
#region
public interface IBaseServiceTest<T> where T : Entity
{
[MemberNotNull(nameof(_mapper))]
public IMapper _mapper { get; set; }
[MemberNotNull(nameof(_userInfo))]
public IUserInfo _userInfo { get; set; }
[MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; }
}
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
public class BaseServiceTest<T> : IBaseServiceTest<T>, IDynamicWebApi where T : Entity
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
public IStringLocalizer _localizer { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{
return new ResponseOutput<string>()
.NotOk($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused", code: ApiResponseCodeEnum.DataNotExist);
}
}
#endregion
}
+377
View File
@@ -0,0 +1,377 @@
using FellowOakDicom.Network;
using FellowOakDicom;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using IRaCIS.Core.SCP.Service;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading;
using IRaCIS.Core.Domain.Share;
using Serilog;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.Options;
using System.Data;
using FellowOakDicom.Imaging;
using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using IRaCIS.Core.Infrastructure;
namespace IRaCIS.Core.SCP.Service
{
public class DicomSCPServiceOption
{
public List<string> CalledAEList { get; set; }
public string ServerPort { get; set; }
}
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
{
private IServiceProvider _serviceProvider { get; set; }
private List<Guid> _SCPStudyIdList { get; set; } = new List<Guid>();
private SCPImageUpload _upload { get; set; }
private Guid _trialId { get; set; }
private Guid _trialSiteId { get; set; }
private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
{
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
{
// Lossless
DicomTransferSyntax.JPEGLSLossless, //1.2.840.10008.1.2.4.80
DicomTransferSyntax.JPEG2000Lossless, //1.2.840.10008.1.2.4.90
DicomTransferSyntax.JPEGProcess14SV1, //1.2.840.10008.1.2.4.70
DicomTransferSyntax.JPEGProcess14, //1.2.840.10008.1.2.4.57 JPEG Lossless, Non-Hierarchical (Process 14)
DicomTransferSyntax.RLELossless, //1.2.840.10008.1.2.5
// Lossy
DicomTransferSyntax.JPEGLSNearLossless,//1.2.840.10008.1.2.4.81"
DicomTransferSyntax.JPEG2000Lossy, //1.2.840.10008.1.2.4.91
DicomTransferSyntax.JPEGProcess1, //1.2.840.10008.1.2.4.50
DicomTransferSyntax.JPEGProcess2_4, //1.2.840.10008.1.2.4.51
// Uncompressed
DicomTransferSyntax.ExplicitVRLittleEndian, //1.2.840.10008.1.2.1
DicomTransferSyntax.ExplicitVRBigEndian, //1.2.840.10008.1.2.2
DicomTransferSyntax.ImplicitVRLittleEndian //1.2.840.10008.1.2
};
public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies)
: base(stream, fallbackEncoding, log, dependencies)
{
}
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
{
_upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
_serviceProvider = (IServiceProvider)this.UserState;
var _trialDicomAERepository = _serviceProvider.GetService<IRepository<TrialDicomAE>>();
var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList();
var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList();
Log.Logger.Information("当前系统配置:", string.Join('|', trialDicomAEList));
var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault();
var isCanReceiveIamge = false;
if (findCalledAE != null)
{
_trialId = findCalledAE.TrialId;
var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault();
if (findTrialSiteAE != null)
{
_trialSiteId = findTrialSiteAE.TrialSiteId;
isCanReceiveIamge = true;
}
}
if (association.CallingAE == "test-callingAE")
{
isCanReceiveIamge = true;
}
if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge == false)
{
Log.Logger.Warning($"拒绝CallingAE:{association.CallingAE} CalledAE:{association.CalledAE}的连接");
return SendAssociationRejectAsync(
DicomRejectResult.Permanent,
DicomRejectSource.ServiceUser,
DicomRejectReason.CalledAENotRecognized);
}
foreach (var pc in association.PresentationContexts)
{
if (pc.AbstractSyntax == DicomUID.Verification)
{
pc.AcceptTransferSyntaxes(_acceptedTransferSyntaxes);
}
else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
{
pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
}
}
return SendAssociationAcceptAsync(association);
}
public async Task OnReceiveAssociationReleaseRequestAsync()
{
await DataMaintenanceAsaync();
//记录监控
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
_upload.EndTime = DateTime.Now;
_upload.StudyCount = _SCPStudyIdList.Count;
_upload.TrialId = _trialId;
_upload.TrialSiteId = _trialSiteId;
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();
}
private async Task DataMaintenanceAsaync()
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality");
//处理检查Modality
var _dictionaryRepository = _serviceProvider.GetService<IRepository<Dictionary>>();
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
var seriesModalityList = _seriesRepository.Where(t => _SCPStudyIdList.Contains(t.StudyId)).Select(t => new { SCPStudyId = t.StudyId, t.Modality }).ToList();
foreach (var g in seriesModalityList.GroupBy(t => t.SCPStudyId))
{
var modality = string.Join('、', g.Select(t => t.Modality).Distinct().ToList());
//特殊逻辑
var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
if (modality == "MR")
{
modalityForEdit = "MRI";
}
if (modality == "PT")
{
modalityForEdit = "PET";
}
if (modality == "PT、CT" || modality == "CT、PT")
{
modalityForEdit = "PET-CT";
}
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == g.Key, u => new SCPStudy() { Modalities = modality, ModalityForEdit = modalityForEdit });
}
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}维护数据结束");
}
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}接收中断,中断原因:{source.ToString() + reason.ToString()}");
/* nothing to do here */
}
public async void OnConnectionClosed(Exception exception)
{
/* nothing to do here */
//奇怪的bug 上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
if (exception == null)
{
//var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
////将检查设置为传输结束
//await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
//await _studyRepository.SaveChangesAndClearAllTrackingAsync();
}
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
}
public async Task<DicomCStoreResponse> OnCStoreRequestAsync(DicomCStoreRequest request)
{
string studyInstanceUid = request.Dataset.GetString(DicomTag.StudyInstanceUID);
string seriesInstanceUid = request.Dataset.GetString(DicomTag.SeriesInstanceUID);
string sopInstanceUid = request.Dataset.GetString(DicomTag.SOPInstanceUID);
//Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid, trialId.ToString());
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, _trialId.ToString());
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, _trialId.ToString());
var ossService = _serviceProvider.GetService<IOSSService>();
var dicomArchiveService = _serviceProvider.GetService<IDicomArchiveService>();
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var storeRelativePath = string.Empty;
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}{studyInstanceUid}";
long fileSize = 0;
try
{
using (MemoryStream ms = new MemoryStream())
{
await request.File.SaveAsync(ms);
//irc 从路径最后一截取Guid
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
fileSize = ms.Length;
}
Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 ");
}
catch (Exception ec)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 上传异常 {ec.Message}");
}
var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
using (await @lock.AcquireAsync())
{
try
{
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE,fileSize);
if (!_SCPStudyIdList.Contains(scpStudyId))
{
_SCPStudyIdList.Add(scpStudyId);
}
var series = await _seriesRepository.FindAsync(seriesId);
//没有缩略图
if (series != null && string.IsNullOrEmpty(series.ImageResizePath))
{
// 生成缩略图
using (var memoryStream = new MemoryStream())
{
DicomImage image = new DicomImage(request.Dataset);
var sharpimage = image.RenderImage().AsSharpImage();
sharpimage.Save(memoryStream, new JpegEncoder());
// 上传缩略图到 OSS
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, seriesId.ToString() + ".preview.jpg", false);
Console.WriteLine(seriesPath + " Id: " + seriesId);
series.ImageResizePath = seriesPath;
}
}
await _seriesRepository.SaveChangesAsync();
}
catch (Exception ex)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 传输处理异常:{ex.ToString()}");
}
}
//监控信息设置
_upload.FileCount++;
_upload.FileSize = _upload.FileSize + fileSize;
return new DicomCStoreResponse(request, DicomStatus.Success);
}
public Task OnCStoreRequestExceptionAsync(string tempFileName, Exception e)
{
// let library handle logging and error response
return Task.CompletedTask;
}
public Task<DicomCEchoResponse> OnCEchoRequestAsync(DicomCEchoRequest request)
{
return Task.FromResult(new DicomCEchoResponse(request, DicomStatus.Success));
}
}
}
+356
View File
@@ -0,0 +1,356 @@
using IRaCIS.Core.Domain.Share;
using System.Text;
using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Infrastructure;
using Medallion.Threading;
using FellowOakDicom;
using FellowOakDicom.Imaging.Codec;
using System.Data;
using IRaCIS.Core.Domain.Models;
using FellowOakDicom.Network;
using IRaCIS.Core.SCP.Service;
using IRaCIS.Core.Infra.EFCore;
using MassTransit;
using System.Runtime.Intrinsics.X86;
using Serilog.Sinks.File;
namespace IRaCIS.Core.SCP.Service
{
public class DicomArchiveService : BaseService, IDicomArchiveService
{
private readonly IRepository<SCPPatient> _patientRepository;
private readonly IRepository<SCPStudy> _studyRepository;
private readonly IRepository<SCPSeries> _seriesRepository;
private readonly IRepository<SCPInstance> _instanceRepository;
private readonly IRepository<Dictionary> _dictionaryRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
private List<Guid> _instanceIdList = new List<Guid>();
public DicomArchiveService(IRepository<SCPPatient> patientRepository, IRepository<SCPStudy> studyRepository,
IRepository<SCPSeries> seriesRepository,
IRepository<SCPInstance> instanceRepository,
IRepository<Dictionary> dictionaryRepository,
IDistributedLockProvider distributedLockProvider)
{
_distributedLockProvider = distributedLockProvider;
_studyRepository = studyRepository;
_patientRepository = patientRepository;
_seriesRepository = seriesRepository;
_instanceRepository = instanceRepository;
_dictionaryRepository = dictionaryRepository;
}
/// <summary>
/// 单个文件接收 归档
/// </summary>
/// <param name="dataset"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Guid> ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE,long fileSize)
{
string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID);
string patientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID,string.Empty);
//Guid patientId= IdentifierHelper.CreateGuid(patientIdStr);
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString());
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString());
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString());
var isStudyNeedAdd = false;
var isSeriesNeedAdd = false;
var isInstanceNeedAdd = false;
var isPatientNeedAdd = false;
//var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
//using (@lock.Acquire())
{
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId );
var findStudy = await _studyRepository.FindAsync(studyId);
var findSerice = await _seriesRepository.FindAsync(seriesId);
var findInstance = await _instanceRepository.FindAsync(instanceId);
DateTime? studyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.StudyDate).Add(dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.StudyTime).TimeOfDay);
//先传输了修改了患者编号的,又传输了没有修改患者编号的,导致后传输的没有修改患者编号的下面的检查为0
if (findPatient == null && findStudy==null)
{
isPatientNeedAdd = true;
findPatient = new SCPPatient()
{
Id = NewId.NextSequentialGuid(),
TrialId=trialId,
TrialSiteId=trialSiteId,
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
EarliestStudyTime = studyTime,
LatestStudyTime = studyTime,
LatestPushTime = DateTime.Now,
};
if (findPatient.PatientBirthDate.Length == 8)
{
var birthDateStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}-{findPatient.PatientBirthDate[4]}{findPatient.PatientBirthDate[5]}-{findPatient.PatientBirthDate[6]}{findPatient.PatientBirthDate[7]}";
var yearStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}";
int year = 0;
var canParse = int.TryParse(yearStr, out year);
if (canParse && year > 1900)
{
findPatient.PatientBirthDate = birthDateStr;
DateTime birthDate;
if (findPatient.PatientAge == string.Empty && studyTime.HasValue && DateTime.TryParse(findPatient.PatientBirthDate,out birthDate))
{
var patientAge = studyTime.Value.Year - birthDate.Year;
// 如果生日还未到,年龄减去一岁
if (studyTime.Value < birthDate.AddYears(patientAge))
{
patientAge--;
}
findPatient.PatientAge = patientAge.ToString();
}
}
else
{
findPatient.PatientBirthDate = string.Empty;
}
}
}
else
{
if (studyTime < findPatient.EarliestStudyTime)
{
findPatient.EarliestStudyTime = studyTime;
}
if (studyTime > findPatient.LatestStudyTime)
{
findPatient.LatestStudyTime = studyTime;
}
findPatient.LatestPushTime = DateTime.Now;
}
if (findStudy == null)
{
isStudyNeedAdd = true;
findStudy = new SCPStudy
{
CalledAE = calledAE,
CallingAE = callingAE,
PatientId = findPatient.Id,
Id = studyId,
TrialId = trialId,
TrialSiteId = trialSiteId,
StudyInstanceUid = studyInstanceUid,
StudyTime = studyTime,
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
//ModalityForEdit = modalityForEdit,
Description = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
InstitutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty),
PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
StudyId = dataset.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty),
AccessionNumber = dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty),
//需要特殊处理
PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
//IsDoubleReview = addtionalInfo.IsDoubleReview,
SeriesCount = 0,
InstanceCount = 0
};
if (findStudy.PatientBirthDate.Length == 8)
{
findStudy.PatientBirthDate = $"{findStudy.PatientBirthDate[0]}{findStudy.PatientBirthDate[1]}{findStudy.PatientBirthDate[2]}{findStudy.PatientBirthDate[3]}-{findStudy.PatientBirthDate[4]}{findStudy.PatientBirthDate[5]}-{findStudy.PatientBirthDate[6]}{findStudy.PatientBirthDate[7]}";
}
}
if (findSerice == null)
{
isSeriesNeedAdd = true;
findSerice = new SCPSeries
{
Id = seriesId,
StudyId = findStudy.Id,
StudyInstanceUid = findStudy.StudyInstanceUid,
SeriesInstanceUid = seriesInstanceUid,
SeriesNumber = dataset.GetSingleValueOrDefault(DicomTag.SeriesNumber, 1),
//SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, DateTime.Now).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, DateTime.Now).TimeOfDay),
//SeriesTime = DateTime.TryParse(dataset.GetSingleValue<string>(DicomTag.SeriesDate) + dataset.GetSingleValue<string>(DicomTag.SeriesTime), out DateTime dt) ? dt : null,
SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.SeriesDate).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.SeriesTime).TimeOfDay),
Modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
Description = dataset.GetSingleValueOrDefault(DicomTag.SeriesDescription, string.Empty),
SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
ImagePositionPatient = dataset.GetSingleValueOrDefault(DicomTag.ImagePositionPatient, string.Empty),
ImageOrientationPatient = dataset.GetSingleValueOrDefault(DicomTag.ImageOrientationPatient, string.Empty),
BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
SequenceName = dataset.GetSingleValueOrDefault(DicomTag.SequenceName, string.Empty),
ProtocolName = dataset.GetSingleValueOrDefault(DicomTag.ProtocolName, string.Empty),
ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
InstanceCount = 0
};
++findStudy.SeriesCount;
}
if (findInstance == null)
{
isInstanceNeedAdd = true;
findInstance = new SCPInstance
{
Id = instanceId,
StudyId = findStudy.Id,
SeriesId = findSerice.Id,
StudyInstanceUid = findStudy.StudyInstanceUid,
SeriesInstanceUid = findSerice.SeriesInstanceUid,
SopInstanceUid = sopInstanceUid,
InstanceNumber = dataset.GetSingleValueOrDefault(DicomTag.InstanceNumber, 1),
InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue<DateTime>(DicomTag.ContentDate).Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue<DateTime>(DicomTag.ContentTime).TimeOfDay),
//InstanceTime = DateTime.TryParse(dataset.GetSingleValue<string>(DicomTag.ContentDate) + dataset.GetSingleValue<string>(DicomTag.ContentTime), out DateTime dt) ? dt : null,
//InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate,(DateTime?)null)?.Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, TimeSpan.Zero)),
//dataset.GetSingleValueOrDefault(DicomTag.ContentDate,DateTime.Now);//, DicomTag.ContentTime)
CPIStatus = false,
ImageRows = dataset.GetSingleValueOrDefault(DicomTag.Rows, 0),
ImageColumns = dataset.GetSingleValueOrDefault(DicomTag.Columns, 0),
SliceLocation = dataset.GetSingleValueOrDefault(DicomTag.SliceLocation, 0),
SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
NumberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 0),
PixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.PixelSpacing, string.Empty),
ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
FrameOfReferenceUID = dataset.GetSingleValueOrDefault(DicomTag.FrameOfReferenceUID, string.Empty),
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
Path = fileRelativePath,
FileSize= fileSize,
};
++findStudy.InstanceCount;
++findSerice.InstanceCount;
}
if (isPatientNeedAdd)
{
var ss = await _patientRepository.AddAsync(findPatient);
}
if (isStudyNeedAdd)
{
var dd = await _studyRepository.AddAsync(findStudy);
}
else
{
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == findStudy.Id, t => new SCPStudy() { IsUploadFinished = false });
}
if (isSeriesNeedAdd)
{
await _seriesRepository.AddAsync(findSerice);
}
if (isInstanceNeedAdd)
{
await _instanceRepository.AddAsync(findInstance);
}
else
{
await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath,FileSize=fileSize });
}
//await _studyRepository.SaveChangesAsync();
return findStudy.Id;
}
}
// 从DICOM文件中获取使用的字符集
private string GetEncodingVaulueFromDicomFile(DicomDataset dataset, DicomTag dicomTag)
{
// 获取DICOM文件的特定元素,通常用于指示使用的字符集
var charset = dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty);
var dicomEncoding = DicomEncoding.GetEncoding(charset);
var dicomStringElement = dataset.GetDicomItem<DicomStringElement>(dicomTag);
var bytes = dicomStringElement.Buffer.Data;
return dicomEncoding.GetString(bytes);
//// 从DICOM文件中获取使用的字符集
//string filePath = "C:\\Users\\hang\\Documents\\WeChat Files\\wxid_r2imdzb7j3q922\\FileStorage\\File\\2024-05\\1.2.840.113619.2.80.169103990.5390.1271401378.4.dcm";
//DicomFile dicomFile = DicomFile.Open(filePath);
//// 获取DICOM文件的特定元素,通常用于指示使用的字符集
//var charset = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty);
//var dicomEncoding = DicomEncoding.GetEncoding(charset);
//var value = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
//var dicomStringElement = dicomFile.Dataset.GetDicomItem<DicomStringElement>(DicomTag.PatientName);
//var bytes = dicomStringElement.Buffer.Data;
//var aa= dicomEncoding.GetString(bytes);
}
}
}
@@ -0,0 +1,11 @@
using FellowOakDicom;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
namespace IRaCIS.Core.SCP.Service
{
public interface IDicomArchiveService
{
Task<Guid> ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE,long fileSize);
}
}
+770
View File
@@ -0,0 +1,770 @@
using AlibabaCloud.SDK.Sts20150401;
using Aliyun.OSS;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
using MassTransit;
using Microsoft.Extensions.Options;
using Minio;
using Minio.DataModel.Args;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.SCP;
#region
[LowerCamelCaseJson]
public class MinIOOptions : AWSOptions
{
public int Port { get; set; }
}
public class AWSOptions
{
public string EndPoint { get; set; }
public bool UseSSL { get; set; }
public string AccessKeyId { get; set; }
public string RoleArn { get; set; }
public string SecretAccessKey { get; set; }
public string BucketName { get; set; }
public string ViewEndpoint { get; set; }
public int DurationSeconds { get; set; }
public string Region { get; set; }
}
public class AliyunOSSOptions
{
public string RegionId { get; set; }
public string AccessKeyId { get; set; }
public string AccessKeySecret { get; set; }
public string InternalEndpoint { get; set; }
public string EndPoint { get; set; }
public string BucketName { get; set; }
public string RoleArn { get; set; }
public string Region { get; set; }
public string ViewEndpoint { get; set; }
public int DurationSeconds { get; set; }
}
public class ObjectStoreServiceOptions
{
public string ObjectStoreUse { get; set; }
public AliyunOSSOptions AliyunOSS { get; set; }
public MinIOOptions MinIO { get; set; }
public AWSOptions AWS { get; set; }
}
public class ObjectStoreDTO
{
public string ObjectStoreUse { get; set; }
public AliyunOSSTempToken AliyunOSS { get; set; }
public MinIOOptions MinIO { get; set; }
public AWSTempToken AWS { get; set; }
}
[LowerCamelCaseJson]
public class AliyunOSSTempToken
{
public string AccessKeyId { get; set; }
public string AccessKeySecret { get; set; }
public string EndPoint { get; set; }
public string BucketName { get; set; }
public string Region { get; set; }
public string ViewEndpoint { get; set; }
public string SecurityToken { get; set; }
public DateTime Expiration { get; set; }
}
[LowerCamelCaseJson]
public class AWSTempToken
{
public string Region { get; set; }
public string SessionToken { get; set; }
public string EndPoint { get; set; }
public string AccessKeyId { get; set; }
public string SecretAccessKey { get; set; }
public string BucketName { get; set; }
public string ViewEndpoint { get; set; }
public DateTime Expiration { get; set; }
}
public enum ObjectStoreUse
{
AliyunOSS = 0,
MinIO = 1,
AWS = 2,
}
#endregion
// aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
public interface IOSSService
{
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
public Task<string> GetSignedUrl(string ossRelativePath);
public Task DeleteFromPrefix(string prefix);
public ObjectStoreDTO GetObjectStoreTempToken();
}
public class OSSService : IOSSService
{
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
private AWSTempToken AWSTempToken { get; set; }
public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
{
ObjectStoreServiceOptions = options.CurrentValue;
}
/// <summary>
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
/// </summary>
/// <param name="fileStream"></param>
/// <param name="oosFolderPath"></param>
/// <param name="fileRealName"></param>
/// <param name="isFileNameAddGuid"></param>
/// <returns></returns>
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
{
GetObjectStoreTempToken();
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
try
{
using (var memoryStream = new MemoryStream())
{
fileStream.Seek(0, SeekOrigin.Begin);
fileStream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
// 上传文件
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
var putObjectArgs = new PutObjectArgs()
.WithBucket(minIOConfig.BucketName)
.WithObject(ossRelativePath)
.WithStreamData(memoryStream)
.WithObjectSize(memoryStream.Length);
await minioClient.PutObjectAsync(putObjectArgs);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
{
BucketName = awsConfig.BucketName,
InputStream = memoryStream,
Key = ossRelativePath,
};
await amazonS3Client.PutObjectAsync(putObjectRequest);
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
}
catch (Exception ex)
{
throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
}
return "/" + ossRelativePath;
}
/// <summary>
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
/// </summary>
/// <param name="localFilePath"></param>
/// <param name="oosFolderPath"></param>
/// <param name="isFileNameAddGuid"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
{
GetObjectStoreTempToken();
var localFileName = Path.GetFileName(localFilePath);
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
// 上传文件
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
var putObjectArgs = new PutObjectArgs()
.WithBucket(minIOConfig.BucketName)
.WithObject(ossRelativePath)
.WithFileName(localFilePath);
await minioClient.PutObjectAsync(putObjectArgs);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
// 提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
{
BucketName = awsConfig.BucketName,
FilePath = localFilePath,
Key = ossRelativePath,
};
await amazonS3Client.PutObjectAsync(putObjectRequest);
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
return "/" + ossRelativePath;
}
public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
{
GetObjectStoreTempToken();
ossRelativePath = ossRelativePath.TrimStart('/');
try
{
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
// 上传文件
var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
// 将下载的文件流保存到本地文件
using (var fs = File.OpenWrite(localFilePath))
{
result.Content.CopyTo(fs);
fs.Close();
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
var getObjectArgs = new GetObjectArgs()
.WithBucket(minIOConfig.BucketName)
.WithObject(ossRelativePath)
.WithFile(localFilePath);
await minioClient.GetObjectAsync(getObjectArgs);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
// 提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
var getObjectArgs = new Amazon.S3.Model.GetObjectRequest()
{
BucketName = awsConfig.BucketName,
Key = ossRelativePath,
};
await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None);
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
catch (Exception ex)
{
throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
}
}
public async Task<string> GetSignedUrl(string ossRelativePath)
{
GetObjectStoreTempToken();
ossRelativePath = ossRelativePath.TrimStart('/');
try
{
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
// 生成签名URL。
var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get)
{
// 设置签名URL过期时间,默认值为3600秒。
Expiration = DateTime.Now.AddHours(1),
};
var uri = _ossClient.GeneratePresignedUri(req);
return uri.PathAndQuery;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
var args = new PresignedGetObjectArgs()
.WithBucket(minIOConfig.BucketName)
.WithObject(ossRelativePath)
.WithExpiry(3600)
/*.WithHeaders(reqParams)*/;
var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
Uri uri = new Uri(presignedUrl);
string relativePath = uri.PathAndQuery;
return relativePath;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
// 提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
{
BucketName = awsConfig.BucketName,
Key = ossRelativePath,
Expires = DateTime.UtcNow.AddMinutes(120)
});
Uri uri = new Uri(presignedUrl);
string relativePath = uri.PathAndQuery;
return relativePath;
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
catch (Exception ex)
{
throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
}
}
/// <summary>
/// 删除某个目录的文件
/// </summary>
/// <param name="prefix"></param>
/// <returns></returns>
public async Task DeleteFromPrefix(string prefix)
{
GetObjectStoreTempToken();
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
try
{
ObjectListing objectListing = null;
string nextMarker = null;
do
{
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
{
Prefix = prefix,
MaxKeys = 1000,
Marker = nextMarker
});
List<string> keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList();
// 删除获取到的文件
if (keys.Count > 0)
{
_ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false));
}
// 设置 NextMarker 以获取下一页的数据
nextMarker = objectListing.NextMarker;
} while (objectListing.IsTruncated);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true);
// 创建一个空列表用于存储对象键
var objects = new List<string>();
// 使用 await foreach 来异步迭代对象列表
await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs))
{
objects.Add(item.Key);
}
if (objects.Count > 0)
{
var objArgs = new RemoveObjectsArgs()
.WithBucket(minIOConfig.BucketName)
.WithObjects(objects);
// 删除对象
await minioClient.RemoveObjectsAsync(objArgs);
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
// 提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
// 列出指定前缀下的所有对象
var listObjectsRequest = new ListObjectsV2Request
{
BucketName = awsConfig.BucketName,
Prefix = prefix
};
var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest);
if (listObjectsResponse.S3Objects.Count > 0)
{
// 准备删除请求
var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
{
BucketName = awsConfig.BucketName,
Objects = new List<KeyVersion>()
};
foreach (var s3Object in listObjectsResponse.S3Objects)
{
deleteObjectsRequest.Objects.Add(new KeyVersion
{
Key = s3Object.Key
});
}
// 批量删除对象
var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
}
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
public ObjectStoreDTO GetObjectStoreTempToken()
{
var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
{
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 = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
SecurityToken = credentials.SecurityToken,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
EndPoint = ossOptions.EndPoint,
ViewEndpoint = ossOptions.ViewEndpoint,
};
AliyunOSSTempToken = tempToken;
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken };
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO };
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsOptions = ObjectStoreServiceOptions.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 = stsClient.AssumeRoleAsync(assumeRoleRequest).Result;
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,
};
AWSTempToken = tempToken;
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken };
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
}
@@ -0,0 +1,37 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "zy-irc-store",
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
@@ -0,0 +1,48 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-test-store",
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "106.14.89.110",
"port": "9001",
"useSSL": false,
"accessKey": "fbStsVYCIPKHQneeqMwD",
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"bucketName": "hir-test",
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
}
},
"ConnectionStrings": {
"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"
},
"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/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
}
}
+35
View File
@@ -0,0 +1,35 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-uat-store",
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"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"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
+6
View File
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,10 @@ Global
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.Build.0 = Release|Any CPU
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
-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; }
}
}
}
+123 -117
View File
@@ -1,6 +1,5 @@
using System;
using System.Net.Http;
using EasyCaching.Core;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Auth;
@@ -15,7 +14,7 @@ using System.Text;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Application.Interfaces;
using System.Threading.Tasks;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure;
@@ -23,15 +22,22 @@ using System.Linq;
using Microsoft.Extensions.Logging;
using MassTransit;
using Microsoft.AspNetCore.Hosting;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.Core.Auth.Sts;
using Aliyun.Acs.Core;
using IRaCIS.Core.Application.Helper;
using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Contracts;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
using DocumentFormat.OpenXml.Spreadsheet;
using AutoMapper.QueryableExtensions;
using NetTopologySuite.Algorithm;
using ZiggyCreatures.Caching.Fusion;
using AlibabaCloud.SDK.Sts20150401;
using AlibabaCloud.SDK.Sts20150401.Models;
using Org.BouncyCastle.Tls;
using Amazon.SecurityToken.Model;
using Amazon.SecurityToken;
using Amazon;
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
using AutoMapper;
namespace IRaCIS.Api.Controllers
{
@@ -99,16 +105,20 @@ namespace IRaCIS.Api.Controllers
[HttpPost, Route("user/login")]
[AllowAnonymous]
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
[FromServices] IEasyCachingProvider provider,
[FromServices] IFusionCache _fusionCache,
[FromServices] IUserService _userService,
[FromServices] ITokenService _tokenService,
[FromServices] IReadingImageTaskService readingImageTaskService,
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
IMailVerificationService _mailVerificationService)
[FromServices] ITokenService _tokenService,
[FromServices] IReadingImageTaskService readingImageTaskService,
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
[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
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
{
Guid userId = (Guid)loginUser.UserId;
@@ -138,10 +148,11 @@ namespace IRaCIS.Api.Controllers
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(userId);
await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), loginReturn.JWTStr, TimeSpan.FromDays(7));
await provider.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);
}
@@ -216,9 +227,9 @@ namespace IRaCIS.Api.Controllers
if (_verifyConfig.CurrentValue.OpenLoginMFA)
{
//发版屏蔽
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
//MFA 发送邮件
@@ -226,27 +237,21 @@ namespace IRaCIS.Api.Controllers
var email = returnModel.Data.BasicInfo.EMail;
#region Email
// 找到 "@" 符号的位置
int atIndex = email.IndexOf('@');
// 替换 "@" 符号前的中间两位为星号
string visiblePart = email.Substring(0, atIndex);
int startIndex = (visiblePart.Length - 2) / 2;
// 替换中间两位字符为星号
string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
string afterAt = email.Substring(atIndex + 1);
// 组合隐藏和可见部分
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
#endregion
var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
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
@@ -269,12 +274,14 @@ namespace IRaCIS.Api.Controllers
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
await _fusionCache.SetAsync(CacheKeys.UserToken(userId), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
await provider.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));
}
}
returnModel.Data.CompanyInfo = companyInfo;
return returnModel;
}
@@ -284,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")]
@@ -308,107 +321,100 @@ namespace IRaCIS.Api.Controllers
}
[HttpGet("user/GetObjectStoreToken")]
public IResponseOutput GetObjectStoreToken([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);
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS });
#region token
//IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
//DefaultAcsClient client = new DefaultAcsClient(profile);
//// 创建一个STS请求
//AssumeRoleRequest request = new AssumeRoleRequest
//{
// RoleArn = ossOptions.RoleArn, // 角色ARN,需要替换为你的角色ARN
// RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
// DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
//};
//AssumeRoleResponse response = client.GetAcsResponse(request);
//// 返回STS令牌信息给前端
//var stsToken = new ObjectStoreDTO()
//{
// ObjectStoreUse = serviceOption.ObjectStoreUse,
// AliyunOSS = new AliyunOSSTempToken()
// {
// AccessKeyId = response.Credentials.AccessKeyId,
// AccessKeySecret = response.Credentials.AccessKeySecret,
// SecurityToken = response.Credentials.SecurityToken,
// Expiration = response.Credentials.Expiration,
// Region = ossOptions.Region,
// BucketName = ossOptions.BucketName,
// ViewEndpoint = ossOptions.ViewEndpoint,
// },
// MinIO = serviceOption.MinIO
//};
//return ResponseOutput.Ok(stsToken);
#endregion
}
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
{
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
}
else
{
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
}
return ResponseOutput.Ok(result);
}
[HttpGet("user/GenerateSTS")]
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
private async Task<AWSTempToken> GetAWSTemToken(ObjectStoreServiceOptions serviceOption)
{
var ossOptions = options.CurrentValue;
var awsOptions = serviceOption.AWS;
//aws 临时凭证
// 创建 STS 客户端
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
// 创建一个STS请求
AssumeRoleRequest request = new AssumeRoleRequest
// 使用 AssumeRole 请求临时凭证
var assumeRoleRequest = new AssumeRoleRequest
{
RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
RoleArn = awsOptions.RoleArn, // 角色 ARN
RoleSessionName = $"session-name-{NewId.NextGuid()}",
DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
};
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
AssumeRoleResponse response = client.GetAcsResponse(request);
var credentials = assumeRoleResponse.Credentials;
// 返回STS令牌信息给前端
var stsToken = new
var tempToken = new AWSTempToken()
{
AccessKeyId = response.Credentials.AccessKeyId,
AccessKeySecret = response.Credentials.AccessKeySecret,
SecurityToken = response.Credentials.SecurityToken,
Expiration = response.Credentials.Expiration,
Region = ossOptions.region,
BucketName = ossOptions.bucketName,
ViewEndpoint = ossOptions.viewEndpoint,
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(stsToken);
return tempToken;
}
#region aliyun-net-sdk-sts
//[HttpGet("user/GenerateSTS")]
//public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
//{
// var ossOptions = options.CurrentValue;
// IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
// DefaultAcsClient client = new DefaultAcsClient(profile);
// // 创建一个STS请求
// AssumeRoleRequest request = new AssumeRoleRequest
// {
// RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
// RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
// DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
// };
// AssumeRoleResponse response = client.GetAcsResponse(request);
// // 返回STS令牌信息给前端
// var stsToken = new
// {
// AccessKeyId = response.Credentials.AccessKeyId,
// AccessKeySecret = response.Credentials.AccessKeySecret,
// SecurityToken = response.Credentials.SecurityToken,
// Expiration = response.Credentials.Expiration,
// Region = ossOptions.region,
// BucketName = ossOptions.bucketName,
// ViewEndpoint = ossOptions.viewEndpoint,
// };
// return ResponseOutput.Ok(stsToken);
//}
#endregion
[HttpGet("User/UserRedirect")]
[AllowAnonymous]
@@ -442,7 +448,7 @@ namespace IRaCIS.Api.Controllers
[HttpGet, Route("ip")]
[AllowAnonymous]
public IResponseOutput Get([FromServices] IHttpContextAccessor _context/*, [FromServices] IUserService _userService*/)
public IResponseOutput Get([FromServices] IHttpContextAccessor _context)
{
StringBuilder sb = new StringBuilder();
@@ -463,7 +469,7 @@ namespace IRaCIS.Api.Controllers
[HttpGet, Route("ip2")]
[AllowAnonymous]
public IResponseOutput Get2([FromServices] IHttpContextAccessor _context, [FromServices] IRepository _userService)
public IResponseOutput Get2([FromServices] IHttpContextAccessor _context)
{
StringBuilder sb = new StringBuilder();
@@ -7,7 +7,7 @@ using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Models;
@@ -19,18 +19,12 @@ namespace IRaCIS.Core.API.Controllers.Special
//谨慎修改 涉及到财务模块
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class FinancialChangeController : ControllerBase
public class FinancialChangeController(
ITrialService _trialService,
ICalculateService _calculateService,
IStringLocalizer _localizer) : ControllerBase
{
private readonly ITrialService _trialService;
private readonly ICalculateService _calculateService;
private IStringLocalizer _localizer { get; set; }
public FinancialChangeController(ITrialService trialService, ICalculateService calculateService, IStringLocalizer localizer
)
{
_localizer = localizer;
_trialService = trialService;
_calculateService = calculateService;
}
//[TrialAudit(AuditType.TrialAudit, AuditOptType.AddOrUpdateTrial)]
@@ -26,78 +26,19 @@ namespace IRaCIS.Core.API.Controllers
[ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
[UnitOfWork]
public class InspectionController : ControllerBase
public class InspectionController(
ITrialDocumentService _trialDocumentService,
IReadingImageTaskService _iReadingImageTaskService,
ITrialConfigService _trialConfigService,
IClinicalAnswerService _clinicalAnswerService,
IReadingClinicalDataService _readingClinicalDataService,
IQCOperationService _qCOperationService,
IInspectionService _inspectionService,
IReadingMedicalReviewService _readingMedicalReviewService,
IReadingMedicineQuestionService _readingMedicineQuestionService
) : ControllerBase
{
private readonly IRepository _repository;
private readonly IMapper _mapper;
private readonly IUserInfo _userInfo;
private readonly ITrialDocumentService _trialDocumentService;
private readonly IQCListService _qCListService;
private readonly IReadingImageTaskService _iReadingImageTaskService;
private readonly IHttpContextAccessor _httpContext;
private readonly ITrialConfigService _trialConfigService;
private readonly INoneDicomStudyService _noneDicomStudyService;
private readonly IClinicalAnswerService _clinicalAnswerService;
private readonly ISubjectService _subjectService;
private readonly IReadingClinicalDataService _readingClinicalDataService;
private readonly ISubjectVisitService _subjectVisitService;
private readonly IQCOperationService _qCOperationService;
private readonly IClinicalDataService _clinicalDataService;
private readonly IVisitPlanService _visitPlanService;
private readonly IInspectionService _inspectionService;
private readonly IReadingMedicalReviewService _readingMedicalReviewService;
private readonly IReadingMedicineQuestionService _readingMedicineQuestionService;
private readonly IRepository<DataInspection> _dataInspectionRepository;
private delegate Task<IResponseOutput> executionFun(dynamic data);
public InspectionController(IRepository repository,
IRepository<DataInspection> _repositoryDataInspection,
IMapper mapper, IUserInfo userInfo,
ITrialDocumentService trialDocumentService,
IRepository<DataInspection> dataInspectionRepository,
IQCListService _qCListService,
IReadingImageTaskService _iReadingImageTaskService,
IHttpContextAccessor httpContext,
IInspectionService sinspectionService,
IReadingMedicalReviewService readingMedicalReviewService,
IReadingMedicineQuestionService readingMedicineQuestionService,
ITrialConfigService _trialConfigService,
INoneDicomStudyService noneDicomStudyService,
IClinicalAnswerService clinicalAnswerService,
ISubjectService _subjectService,
IReadingClinicalDataService _readingClinicalDataService,
ISubjectVisitService subjectVisitService,
IQCOperationService qCOperationService,
IClinicalDataService clinicalDataService,
IVisitPlanService visitPlanService
)
{
this._repository = repository;
this._mapper = mapper;
this._userInfo = userInfo;
this._inspectionService = sinspectionService;
this._readingMedicalReviewService = readingMedicalReviewService;
this._readingMedicineQuestionService = readingMedicineQuestionService;
this._trialDocumentService = trialDocumentService;
this._qCListService = _qCListService;
this._iReadingImageTaskService = _iReadingImageTaskService;
this._httpContext = httpContext;
this._trialConfigService = _trialConfigService;
this._noneDicomStudyService = noneDicomStudyService;
this._clinicalAnswerService = clinicalAnswerService;
this._subjectService = _subjectService;
this._readingClinicalDataService = _readingClinicalDataService;
this._subjectVisitService = subjectVisitService;
this._qCOperationService = qCOperationService;
this._clinicalDataService = clinicalDataService;
this._visitPlanService = visitPlanService;
this._dataInspectionRepository = dataInspectionRepository;
}
#region
/// <summary>
/// 获取稽查数据
@@ -308,11 +249,28 @@ namespace IRaCIS.Core.API.Controllers
}
/// <summary>
/// 提交结构化录入并签名
/// </summary>
/// <param name="opt"></param>
/// <returns></returns>
/// <summary>
/// PM签名一致性分析临床数据
/// </summary>
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
[UnitOfWork]
public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt)
{
var singid = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _readingClinicalDataService.SignConsistencyAnalysisReadingClinicalData(opt.Data);
await _inspectionService.CompletedSign(singid, result);
return result;
}
/// <summary>
/// 提交结构化录入并签名
/// </summary>
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
@@ -402,6 +360,19 @@ namespace IRaCIS.Core.API.Controllers
return result;
}
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")]
[UnitOfWork]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt" })]
public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt)
{
opt.Data.IsTrialPACSConfirmed = true;
var singid = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _trialConfigService.ConfigTrialPACSInfo(opt.Data);
await _inspectionService.CompletedSign(singid, result);
return result;
}
/// <summary>
/// 签名确认
/// </summary>
@@ -1,6 +1,5 @@
using AutoMapper;
using DocumentFormat.OpenXml.Drawing;
using EasyCaching.Core;
using ExcelDataReader;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
@@ -10,8 +9,7 @@ using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Application.MediatR.Handlers;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.ImageAndDoc;
using IRaCIS.Core.Application.Service.Reading.Dto;
@@ -21,7 +19,7 @@ using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit;
using MediatR;
using MassTransit.Mediator;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Hosting;
@@ -40,12 +38,14 @@ using Newtonsoft.Json;
using SharpCompress.Archives;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZiggyCreatures.Caching.Fusion;
using Path = System.IO.Path;
namespace IRaCIS.Core.API.Controllers
@@ -228,69 +228,17 @@ namespace IRaCIS.Core.API.Controllers
[ApiExplorerSettings(GroupName = "Image")]
[ApiController]
public class StudyController : UploadBaseController
public class StudyController(
IMediator _mediator,
QCCommon _qCCommon,
IUserInfo _userInfo,
IRepository<SubjectVisit> _subjectVisitRepository,
IStringLocalizer _localizer) : UploadBaseController
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
private readonly IMediator _mediator;
public IStringLocalizer _localizer { get; set; }
private readonly IWebHostEnvironment _hostEnvironment;
private readonly IRepository _repository;
private readonly IEasyCachingProvider _provider;
private readonly QCCommon _qCCommon;
public StudyController(IMapper mapper, IStringLocalizer localizer, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator, IEasyCachingProvider provider,
QCCommon qCCommon,
IRepository repository)
{
_qCCommon = qCCommon;
_provider = provider;
_hostEnvironment = hostEnvironment;
_mediator = mediator;
_localizer = localizer;
_mapper = mapper;
_userInfo = userInfo;
_repository = repository;
}
[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)
{
if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value == null)
{
await _mediator.Send(new AnonymizeCacheRequest());
}
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>
@@ -298,9 +246,8 @@ namespace IRaCIS.Core.API.Controllers
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> ArchiveStudyNew(/*[FromForm] ArchiveStudyCommand archiveStudyCommand,*/ 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] IEasyCachingProvider _provider,
[FromServices] IStudyService _studyService,
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
[FromServices] IDicomArchiveService _dicomArchiveService,
@@ -325,22 +272,6 @@ namespace IRaCIS.Core.API.Controllers
var startTime = DateTime.Now;
if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}") && _provider.Get<Guid>($"StudyUid_{trialId}_{studyInstanceUid}").Value == _userInfo.Id)
{
_provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
}
//if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}"))
//{
// //---当前已有人正在上传和归档该检查!
// return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress"));
//}
//else
//{
// _provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
//}
//到了接口,代表上传结束了
@@ -406,13 +337,12 @@ namespace IRaCIS.Core.API.Controllers
}
catch (Exception)
{
_provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
//---请求异常,请重试!
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_RequestError"]);
}
studyMonitor.FileSize = (decimal)HttpContext.Request.ContentLength;
studyMonitor.FileSize = (long)HttpContext.Request.ContentLength;
studyMonitor.FileCount = archiveResult.ReceivedFileCount;
studyMonitor.FailedFileCount = archiveResult.ErrorFiles.Count;
studyMonitor.IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null;
@@ -445,7 +375,6 @@ namespace IRaCIS.Core.API.Controllers
}
finally
{
_provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
studyMonitor.StudyId = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.Id ?? Guid.Empty;
studyMonitor.StudyCode = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.StudyCode;
@@ -465,12 +394,26 @@ namespace IRaCIS.Core.API.Controllers
public class UploadNoneDicomFileCommand
{
public Guid TrialId { get; set; }
[NotDefault]
public Guid SubjectVisitId { get; set; }
public Guid NoneDicomStudyId { get; set; }
[NotDefault]
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>();
@@ -479,21 +422,61 @@ namespace IRaCIS.Core.API.Controllers
public string FilePath { get; set; }
public string FileName { get; set; }
public int FileFize { get; set; }
public string FileType { get; set; }
}
}
/// <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>
/// 上传非Dicom 文件 支持压缩包 多文件上传
/// </summary>
/// <param name="incommand"></param>
/// <param name="_noneDicomStudyRepository"></param>
/// <param name="_studyMonitorRepository"></param>
/// <param name="_noneDicomStudyFileRepository"></param>
/// <returns></returns>
[HttpPost("NoneDicomStudy/UploadNoneDicomFile")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> UploadNoneDicomFile(UploadNoneDicomFileCommand incommand,
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository, [FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository,
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository,
[FromServices] IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository)
{
var subjectVisitId = incommand.SubjectVisitId;
@@ -501,9 +484,9 @@ namespace IRaCIS.Core.API.Controllers
var noneDicomStudyId = incommand.NoneDicomStudyId;
await _qCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
await _qCCommon.VerifyIsCRCSubmmitAsync(_subjectVisitRepository, _userInfo, subjectVisitId);
var sv = (await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.TrialSiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
var sv = (await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.TrialSiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == studyMonitorId);
@@ -511,25 +494,39 @@ namespace IRaCIS.Core.API.Controllers
foreach (var item in incommand.UploadedFileList)
{
await _repository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId });
//如果是跟任务绑,那么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 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.IsDicom = false;
studyMonitor.IsDicomReUpload = false;
studyMonitor.StudyId = noneDicomStudyId;
studyMonitor.StudyId = noneDicomStudyId.Value;
studyMonitor.StudyCode = noneDicomStudy.StudyCode;
studyMonitor.ArchiveFinishedTime = DateTime.Now;
studyMonitor.IP = _userInfo.IP;
await _repository.SaveChangesAsync();
await _noneDicomStudyRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
@@ -543,12 +540,13 @@ namespace IRaCIS.Core.API.Controllers
/// </summary>
/// <param name="trialId"></param>
/// <param name="oSSService"></param>
/// <param name="_inspectionFileRepository"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService)
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
{
var fileName = string.Empty;
@@ -558,9 +556,9 @@ namespace IRaCIS.Core.API.Controllers
{
fileName = realFileName;
if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls"))
if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".xls"))
{
//---支持.xlsx、.xls、.csv格式的文件上传。
//---支持.xlsx、.xls格式的文件上传。
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_SupportedFormats"]);
}
@@ -570,7 +568,7 @@ namespace IRaCIS.Core.API.Controllers
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/Check", realFileName);
await _repository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId });
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId });
return ossRelativePath;
@@ -740,11 +738,16 @@ namespace IRaCIS.Core.API.Controllers
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
}
}
await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
// 适合获取结果的
//var client = _mediator.CreateRequestClient<ConsistenCheckCommand>();
//await client.GetResponse<ConsistenCheckResult>(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
//不获取结果,不用定义返回类型
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
return ResponseOutput.Ok();
@@ -886,89 +889,6 @@ namespace IRaCIS.Core.API.Controllers
#region
/// <summary>
/// 下载多个医生的所有附件
/// </summary>
/// <param name="doctorIds"></param>
/// <returns></returns>
[Obsolete]
[HttpPost, Route("file/downloadDoctorAttachments")]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachment(Guid[] doctorIds)
{
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = path,
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 下载指定医生的指定附件
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="attachmentIds">要下载的附件Id</param>
/// <returns></returns>
[HttpPost, Route("file/downloadByAttachmentId/{doctorId}")]
[Obsolete]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
{
var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds),
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 下载医生官方简历 首页 区分 中文和英文
/// </summary>
/// <param name="language"></param>
/// <param name="doctorIds"></param>
/// <returns></returns>
[HttpPost, Route("file/downloadOfficialCV/{language}")]
[Obsolete]
public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadOfficialResume(int language, Guid[] doctorIds)
{
var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds),
FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
});
}
/// <summary>
/// 入组 项目下载简历
/// </summary>
/// <param name="language"></param>
/// <param name="trialId"></param>
/// <param name="doctorIdArray"></param>
/// <returns></returns>
[HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
[AllowAnonymous]
[Obsolete]
public async Task<IResponseOutput<string>> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray)
{
var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);
return ResponseOutput.Ok(zipPath);
}
#endregion
}
#endregion
@@ -1061,18 +981,18 @@ namespace IRaCIS.Core.API.Controllers
}
var generateUserTypeList = new List<string>() { "CRC", "CRA" };
if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper())))
{
//用户类型仅能为 CRC,SR,CRA 请核查Excel数据
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidUserType"]);
}
//if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper())))
//{
// //用户类型仅能为 CRC,SR,CRA 请核查Excel数据
// throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidUserType"]);
//}
if (excelList.Count == 0)
{
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_NoValiddata"]);
}
//处理好 用户类型 和用户类型枚举
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)
{
@@ -1096,9 +1016,9 @@ namespace IRaCIS.Core.API.Controllers
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, excelList.ToList());
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, list);
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 -142
View File
@@ -1,160 +1,112 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<SignAssembly>false</SignAssembly>
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
<LangVersion>default</LangVersion>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Version>1.0.1.001</Version>
<Company>上海展影医疗科技有限公司</Company>
<Product>IRC影像系统 (EICS)</Product>
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<SignAssembly>false</SignAssembly>
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
<LangVersion>default</LangVersion>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Version>1.0.1.001</Version>
<Company>上海展影医疗科技有限公司</Company>
<Product>IRC影像系统 (EICS)</Product>
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
<NoWarn>1701;1702;1591;1570;</NoWarn>
<OutputPath>..\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
<NoWarn>1701;1702;1591;1570;</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>
<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>
<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>
<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>
<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">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\GrpcToken.proto">
<GrpcServices>Client</GrpcServices>
</Protobuf>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="GrpcToken.proto" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\abp.swagger.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="wwwroot\swagger\ui\Index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\GrpcToken.proto">
<GrpcServices>Client</GrpcServices>
</Protobuf>
</ItemGroup>
<ItemGroup>
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.12" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.12" />
<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.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
<PackageReference Include="Serilog.Sinks.Email" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</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>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</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>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\PublishProfiles\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\PublishProfiles\" />
</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>
+28 -49
View File
@@ -29,7 +29,7 @@
<param name="doctorId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,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>
</member>
<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>
<returns>新记录Id</returns>
</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>
添加或更新工作量[AUTH]
</summary>
@@ -167,6 +167,13 @@
<param name="opt"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SignConsistencyAnalysisReadingClinicalData(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SignConsistencyAnalysisReadingClinicalDataInDto})">
<summary>
PM签名一致性分析临床数据
</summary>
<param name="opt"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitClinicalFormAndSign(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SubmitClinicalFormInDto})">
<summary>
提交结构化录入并签名
@@ -271,24 +278,35 @@
<member name="M:IRaCIS.Core.API.Controllers.UploadBaseController.DicomFileUploadAsync(System.Func{System.String,System.IO.Stream,System.Int32,System.Threading.Tasks.Task},System.String)">
<summary> 流式上传 Dicom上传 </summary>
</member>
<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},EasyCaching.Core.IEasyCachingProvider,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>
</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})">
<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})">
<summary>
上传非Dicom 文件 支持压缩包 多文件上传
</summary>
<param name="incommand"></param>
<param name="_noneDicomStudyRepository"></param>
<param name="_studyMonitorRepository"></param>
<param name="_noneDicomStudyFileRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService)">
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.InspectionFile})">
<summary>
一致性核查 excel上传 支持三种格式
</summary>
<param name="trialId"></param>
<param name="oSSService"></param>
<param name="_inspectionFileRepository"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
@@ -319,38 +337,6 @@
<param name="_attachmentrepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachment(System.Guid[])">
<summary>
下载多个医生的所有附件
</summary>
<param name="doctorIds"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachmentById(System.Guid,System.Guid[])">
<summary>
下载指定医生的指定附件
</summary>
<param name="doctorId">医生Id</param>
<param name="attachmentIds">要下载的附件Id</param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadOfficialResume(System.Int32,System.Guid[])">
<summary>
下载医生官方简历 首页 区分 中文和英文
</summary>
<param name="language"></param>
<param name="doctorIds"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadResume(System.Int32,System.Guid,System.Guid[])">
<summary>
入组 项目下载简历
</summary>
<param name="language"></param>
<param name="trialId"></param>
<param name="doctorIdArray"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})">
<summary> 通用文件下载 </summary>
</member>
@@ -376,6 +362,11 @@
序列化,反序列化的时候,处理时间 时区转换
</summary>
</member>
<member name="M:IRaCIS.Core.API.JSONTimeZoneConverter.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)">
<summary>
序列化,反序列化的时候,处理时间 时区转换
</summary>
</member>
<member name="M:IRaCIS.Core.API.NullToEmptyStringResolver.CreateProperties(System.Type,Newtonsoft.Json.MemberSerialization)">
<summary>
创建属性
@@ -384,18 +375,6 @@
<param name="memberSerialization">序列化成员</param>
<returns></returns>
</member>
<member name="M:IRaCIS.WX.CoreApi.Auth.AuthMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)">
<summary>
为了前端 一段时间无操作,需要重新登陆
</summary>
<param name="httpContext"></param>
<returns></returns>
</member>
<member name="T:TimeZoneAdjustmentMiddleware">
<summary>
废弃,没用
</summary>
</member>
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
<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);
}
}
+126 -29
View File
@@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Serilog;
using MediatR;
using IRaCIS.Core.Application.MediatR.Handlers;
using System.Threading.Tasks;
using MassTransit;
using MassTransit.NewIdProviders;
@@ -22,14 +20,24 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using IRaCIS.Core.Application.Filter;
using Microsoft.AspNetCore.HttpOverrides;
using IRaCIS.Application.Services.BackGroundJob;
using IRaCIS.Core.Application.Service.BackGroundJob;
using LogDashboard;
using FellowOakDicom.Network;
using IRaCIS.Core.Application.Service.ImageAndDoc;
using IP2Region.Net.Abstractions;
using IP2Region.Net.XDB;
using IRaCIS.Core.Application.BusinessFilter;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Infrastructure.Extention;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Diagnostics;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MassTransit.Consumer;
using DocumentFormat.OpenXml.InkML;
using IRaCIS.Core.Domain;
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
#region
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
var config = new ConfigurationBuilder()
@@ -76,8 +84,8 @@ if (urlsIndex > -1)
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
builder.Configuration.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
builder.Configuration.AddJsonFile(ConfigMapFileProvider.FromRelativePath(""), "appsettings.json", false, true)
.AddJsonFile(ConfigMapFileProvider.FromRelativePath(""), $"appsettings.{enviromentName}.json", false, true);
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
@@ -104,11 +112,9 @@ builder.Services.AddControllers(options =>
options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>();
//options.Filters.Add<EncreptApiResultFilter>(10);
options.Filters.Add<LimitUserRequestAuthorization>();
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
{
options.Filters.Add<LimitUserRequestAuthorization>();
}
})
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
@@ -117,6 +123,10 @@ builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.Ge
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
builder.Services.AddOptions().Configure<IRCEncreptOption>(_configuration.GetSection("EncrypteResponseConfig"));
builder.Services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
builder.Services.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
@@ -124,7 +134,7 @@ builder.Services.AddDynamicWebApiSetup();
//AutoMapper
builder.Services.AddAutoMapperSetup();
//EF ORM QueryWithNoLock
builder.Services.AddEFSetup(_configuration);
builder.Services.AddEFSetup(_configuration, enviromentName);
//Http 响应压缩
builder.Services.AddResponseCompressionSetup();
//Swagger Api 文档
@@ -133,9 +143,45 @@ builder.Services.AddSwaggerSetup();
builder.Services.AddJWTAuthSetup(_configuration);
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
#region MassTransit
//masstransit组件 也支持MediatR 中介者模式,但是支持分布式,考虑后续,所以在次替代MediatR
//参考链接:https://masstransit.io/documentation/concepts/mediator#scoped-mediator
builder.Services.AddMediator(cfg =>
{
cfg.AddConsumer<ConsistencyCheckConsumer>();
cfg.AddConsumer<AddSubjectTriggerConsumer>();
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
//cfg.ConfigureMediator((context, cfg) => cfg.UseHttpContextScopeFilter(context));
});
//添加 MassTransit 和 InMemory 传输
builder.Services.AddMassTransit(cfg =>
{
// 注册消费者
cfg.AddConsumer<AddSubjectTriggerConsumer>(); // 替换为你的消费者类
cfg.AddConsumer<AddSubjectTriggerConsumer2>();
// 使用 InMemory 作为消息传递机制
cfg.UsingInMemory((context, cfg) =>
{
// 这里可以进行额外的配置
cfg.ConfigureEndpoints(context); // 自动配置所有消费者的端点
});
});
#endregion
#region FusionCache
builder.Services.AddFusionCache();
#endregion
// EasyCaching 缓存
builder.Services.AddEasyCachingSetup(_configuration);
//builder.Services.AddEasyCachingSetup(_configuration);
// hangfire 定时任务框架 有界面,更友好~
builder.Services.AddhangfireSetup(_configuration);
@@ -163,6 +209,9 @@ builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
//builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
//builder.Services.AddProblemDetails();
#region
//builder.Services.AddMemoryCache();
@@ -186,9 +235,60 @@ var env = app.Environment;
#region
app.UseMiddleware<EncryptionRequestMiddleware>();
// Configure the HTTP request pipeline.
#region 400 -500
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseStatusCodePages(async context =>
{
var code = context.HttpContext.Response.StatusCode;
context.HttpContext.Response.ContentType = "application/json";
if (code < 500)
{
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"Client error, actual request error status code({code})")));
}
else
{
//ResultFilter 里面的异常并不会到这里
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject((ResponseOutput.NotOk($"Server error , actual request error status code({code})"))));
}
});
//app.UseExceptionHandler(o => { });
//这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug
//app.UseExceptionHandler(configure =>
//{
// configure.Run(async context =>
// {
// var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
//var ex = exceptionHandlerPathFeature?.Error;
//context.Response.ContentType = "application/json";
//if (ex != null)
//{
// var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
// await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk($"{ex?.Message}")));
// Log.Logger.Error(errorInfo);
//}
// });
//});
#endregion
//本地化
app.UseLocalization();
@@ -197,12 +297,11 @@ app.UseForwardedHeaders();
//响应压缩
app.UseResponseCompression();
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
app.UseStaticFiles();
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
//LogDashboard
app.UseLogDashboard("/LogDashboard");
@@ -210,22 +309,24 @@ app.UseLogDashboard("/LogDashboard");
//hangfire
app.UseHangfireConfig(env);
#region
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
////限流 中间件
//app.UseIpRateLimiting();
//if (env.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
//else
//{
// //app.UseHsts();
//}
#endregion
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//app.UseHsts();
}
// 特殊异常处理 比如 404
app.UseStatusCodePagesWithReExecute("/Error/{0}");
SwaggerSetup.Configure(app, env);
@@ -295,10 +396,6 @@ try
//Log.Logger.Warning($"ContentRootPath——xx{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
var server = DicomServerFactory.Create<CStoreSCPService>(11112,userState: app.Services);
app.Run();
}
+11 -3
View File
@@ -24,13 +24,21 @@
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.Test_IRC_PGSQL": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC_PGSQL"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.Event_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
},
"applicationUrl": "http://localhost:6101"
"applicationUrl": "http://localhost:6100"
},
"Docker": {
"commandName": "Docker",
@@ -54,11 +62,11 @@
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.US_IRC": {
"IRaCIS.US_Uat_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "US_IRC"
"ASPNETCORE_ENVIRONMENT": "US_Uat_IRC"
},
"applicationUrl": "http://localhost:6100"
}
+1 -2
View File
@@ -1,5 +1,4 @@
using EasyCaching.Core;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.SignalR;
@@ -1,66 +0,0 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Threading.Tasks;
using EasyCaching.Core;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
namespace IRaCIS.WX.CoreApi.Auth
{
public class AuthMiddleware
{
private readonly RequestDelegate _next;
private readonly IEasyCachingProvider _provider;
public AuthMiddleware(RequestDelegate next, IEasyCachingProvider provider)
{
_next = next;
_provider = provider;
}
/// <summary>
///为了前端 一段时间无操作,需要重新登陆
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public async Task Invoke(HttpContext httpContext)
{
var isLogin = httpContext.Request.Path.ToString().ToLower().Contains("login");
var result = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
if (!isLogin)
{
if (!result.Succeeded)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized");
}
else
{
var toekn = result.Properties.Items[".Token.access_token"];
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(toekn);
object userId;
jwtToken.Payload.TryGetValue("id", out userId);
var cacheValueExist = await _provider.ExistsAsync(userId.ToString()); //Get<string>(userId.ToString()).ToString();
if (!cacheValueExist)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized");
}
else
{
await _provider.SetAsync(userId.ToString(), userId.ToString(), TimeSpan.FromMinutes(15));
httpContext.User = result.Principal;
await _next.Invoke(httpContext);
}
}
}
else await _next.Invoke(httpContext);
}
}
}
@@ -1,7 +1,7 @@
using Hangfire;
using Hangfire.Dashboard;
using Hangfire.Dashboard.BasicAuthorization;
using IRaCIS.Application.Services.BackGroundJob;
using IRaCIS.Core.Application.Service.BackGroundJob;
using IRaCIS.Core.API.Filter;
using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Builder;
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Builder;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using System.Collections.Generic;
using System.Globalization;
@@ -12,8 +13,9 @@ namespace IRaCIS.Core.API
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
new CultureInfo(StaticData.CultureInfo.en_US),
new CultureInfo(StaticData.CultureInfo.zh_CN)
};
var options = new RequestLocalizationOptions
@@ -20,18 +20,20 @@ namespace IRaCIS.Core.API
// Set all the common properties available for every request
diagnosticContext.Set("Host", request.Host);
diagnosticContext.Set("Protocol", request.Protocol);
diagnosticContext.Set("Scheme", request.Scheme);
#region old
//这种获取的Ip不准 配置服务才行
//diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
//这种方式可以,但是serilog提供了 就不用了
//diagnosticContext.Set("TestIP", httpContext.GetUserIp());
diagnosticContext.Set("Protocol", request.Protocol);
diagnosticContext.Set("Scheme", request.Scheme);
//这种方式不行 读取的body为空字符串 必须在中间件中读取
//diagnosticContext.Set("RequestBody", await ReadRequestBody(httpContext.Request));
//diagnosticContext.Set("RequestBody", RequestPayload);
#endregion
// Only set it if available. You're not sending sensitive data in a querystring right?!
if (request.QueryString.HasValue)
@@ -1,5 +1,6 @@
using AutoMapper.EquivalencyExpression;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Models;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
@@ -14,11 +15,16 @@ namespace IRaCIS.Core.API
//AutoMapper.Collection.EntityFrameworkCore
automapper.AddCollectionMappers();
// 全局忽略 DomainEvents 属性
automapper.AddGlobalIgnore(nameof(Entity.DomainEvents));
automapper.AddGlobalIgnore(nameof(Entity.DomainCommands));
#region 使 IncludeMembers 使
//mapping an EntityFramework Core DbContext-object.
//automapper.UseEntityFrameworkCoreModel<IRaCISDBContext>(services);
//automapper.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, srcMember, desMenber) =>
//{
// //// Can test When Guid? -> Guid if source is null will change to Guid.Empty
@@ -27,7 +33,7 @@ namespace IRaCIS.Core.API
// // not want to map a null Guid? value to db Guid value
//})));
#endregion
}, typeof(QCConfig).Assembly);
@@ -1,5 +1,4 @@
using Autofac;
using Autofac.Extras.DynamicProxy;
using IRaCIS.Core.Application;
using IRaCIS.Core.Application.BackGroundJob;
using IRaCIS.Core.Infra.EFCore;
@@ -10,8 +9,7 @@ using System.Linq;
using System.Reflection;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MediatR;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Service;
using IRaCIS.Application.Interfaces;
using AutoMapper;
@@ -51,12 +49,12 @@ namespace IRaCIS.Core.API
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "IRaCIS.Core.Application.dll");
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
.PropertiesAutowired().AsImplementedInterfaces().EnableClassInterceptors();
.PropertiesAutowired().AsImplementedInterfaces();
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
//containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
//containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
//注册hangfire任务 依赖注入
+53 -13
View File
@@ -1,31 +1,68 @@
using Hangfire.SqlServer;
using EntityFramework.Exceptions.SqlServer;
using Hangfire.SqlServer;
using IRaCIS.Core.Application.Triggers;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infra.EFCore.Interceptor;
using Medallion.Threading;
using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
namespace IRaCIS.Core.API
{
public static class EFSetup
{
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration)
public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration,string envName)
{
//services.AddScoped<DbContext, IRaCISDBContext>();
services.AddHttpContextAccessor();
services.AddScoped<IUserInfo, UserInfo>();
services.AddScoped<ISaveChangesInterceptor, AuditEntityInterceptor>();
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
// First, register a pooling context factory as a Singleton service, as usual:
//这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext
//Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点
services.AddDbContext<IRaCISDBContext>(options =>
services.AddDbContext<IRaCISDBContext>((sp, options) =>
{
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,
contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
var dbType = configuration.GetSection("ConnectionStrings:Db_Type").Value ;
if (!string.IsNullOrWhiteSpace(dbType) && dbType == "pgsql")
{
options.UseNpgsql(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
}
else
{
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
}
//迁移的时候,不生成外键
options.ReplaceService<IMigrationsSqlGenerator, NoForeignKeyMigrationsSqlGenerator>();
options.UseLoggerFactory(logFactory);
options.UseExceptionProcessor();
options.EnableSensitiveDataLogging();
options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor());
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
options.UseProjectables();
@@ -38,18 +75,15 @@ namespace IRaCIS.Core.API
options.UseTriggers(triggerOptions =>
{
triggerOptions.AddTrigger<AddSubjectTrigger>();
triggerOptions.AddTrigger<ChallengeStateTrigger>();
triggerOptions.AddTrigger<SubjectStateTrigger>();
triggerOptions.AddTrigger<AddCRCCliniaclDataTrigger>();
triggerOptions.AddTrigger<SubjectVisitCheckPassedTrigger>();
triggerOptions.AddTrigger<SubjectVisitFinalVisitTrigger>();
triggerOptions.AddTrigger<SubjectTrigger>();
triggerOptions.AddTrigger<ChallengeStateTrigger>();
triggerOptions.AddTrigger<SubjectVisitTrigger>();
triggerOptions.AddTrigger<SubjectVisitScanDateTrigger>();
triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
triggerOptions.AddTrigger<VisitTaskIbeforeTrigger>();
triggerOptions.AddTrigger<JudgeVisitTaskTrigger>();
triggerOptions.AddTrigger<UserLogTrigger>();
@@ -62,6 +96,12 @@ namespace IRaCIS.Core.API
});
// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above,
//services.AddScoped<IRaCISDBScopedFactory>();
//// Finally, arrange for a context to get injected from our Scoped factory:
//services.AddScoped(sp => sp.GetRequiredService<IRaCISDBScopedFactory>().CreateDbContext());
//注意区分 easy caching 也有 IDistributedLockProvider
services.AddSingleton<IDistributedLockProvider>(sp =>
{
@@ -1,7 +1,4 @@
using EasyCaching.Core;
using EasyCaching.Core.Configurations;
using EasyCaching.Interceptor.Castle;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
@@ -10,18 +7,18 @@ namespace IRaCIS.Core.API
{
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
{
services.AddEasyCaching(options =>
{
options.UseInMemory();
//services.AddEasyCaching(options =>
//{
// options.UseInMemory();
//options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
// //options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
});
//});
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
////services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
}
}
}
@@ -11,19 +11,41 @@ namespace IRaCIS.Core.API
/// <summary>
/// 序列化,反序列化的时候,处理时间 时区转换
/// </summary>
public class JSONTimeZoneConverter : DateTimeConverterBase
public class JSONTimeZoneConverter(IHttpContextAccessor _httpContextAccessor) : DateTimeConverterBase
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly TimeZoneInfo _clientTimeZone;
public JSONTimeZoneConverter(IHttpContextAccessor httpContextAccessor)
private TimeZoneInfo _clientTimeZone;
private string _dateFormat;
public override bool CanConvert(Type objectType)
{
_httpContextAccessor = httpContextAccessor;
#region
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
if (!isEn_US)
{
// Chinese date format
_dateFormat = "yyyy-MM-dd HH:mm:ss";
}
else
{
// Default or English date format
//_dateFormat = "MM/dd/yyyy HH:mm:ss";
_dateFormat = "yyyy-MM-dd HH:mm:ss";
}
#endregion
#region
//默认是UTC
//var timeZoneId = "Etc/UTC";
var timeZoneId = "Asia/Shanghai";
var timeZoneIdHeader = _httpContextAccessor?.HttpContext?.Request?.Headers["TimeZoneId"];
if (timeZoneIdHeader is not null && !string.IsNullOrEmpty(timeZoneIdHeader.Value))
@@ -33,12 +55,12 @@ namespace IRaCIS.Core.API
_clientTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
}
#endregion
public override bool CanConvert(Type objectType)
{
// 仅支持 DateTime 类型的转换
return objectType == typeof(DateTime)|| objectType == typeof(DateTime?);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
@@ -91,7 +113,10 @@ namespace IRaCIS.Core.API
{
//第一个参数默认使用系统本地时区 也就是应用服务器的时区
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
writer.WriteValue(clientZoneTime);
//writer.WriteValue(clientZoneTime);
writer.WriteValue(clientZoneTime.ToString(_dateFormat));
}
else
{
@@ -0,0 +1,99 @@
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Globalization;
using System.Reflection;
namespace IRaCIS.Core.API
{
//public class CustomContractResolver : DefaultContractResolver
//{
// protected override JsonContract CreateContract(Type objectType)
// {
// var contract = base.CreateContract(objectType);
// // 检查类是否有 LowercaseJsonAttribute 标记
// if (objectType.GetCustomAttribute<LowerCamelCaseJsonAttribute>() != null)
// {
// contract.NamingStrategy = new IRCCamelCaseNamingStrategy();
// }
// return contract;
// }
//}
#region
public class MyDateTimeConverter : JsonConverter<DateTime>
{
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return reader.ReadAsDateTime().Value;
}
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
string dateFormat;
if (!isEn_US)
{
// Chinese date format
dateFormat = "yyyy-MM-dd HH:mm:ss";
}
else
{
// Default or English date format
dateFormat = "MM/dd/yyyy HH:mm:ss";
}
writer.WriteValue(value.ToString(dateFormat));
}
}
public class MyNullableDateTimeConverter : JsonConverter<DateTime?>
{
public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var val = reader.ReadAsDateTime();
return val;
}
public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
string dateFormat;
if (!isEn_US)
{
// Chinese date format
dateFormat = "yyyy-MM-dd HH:mm:ss";
}
else
{
// Default or English date format
dateFormat = "MM/dd/yyyy HH:mm:ss";
}
if (value.HasValue)
{
writer.WriteValue(value.Value.ToString(dateFormat));
}
else
{
writer.WriteValue(default(DateTime?));
}
}
}
#endregion
}
@@ -1,10 +1,16 @@
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Globalization;
using System.Text.Json;
using Newtonsoft.Json.Serialization;
namespace IRaCIS.Core.API
{
@@ -12,34 +18,43 @@ namespace IRaCIS.Core.API
{
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddScoped<JSONTimeZoneConverter>();
services.AddScoped<CustomStringConverter>();
services.AddScoped<IOSSService,OSSService>();
services.AddScoped<ObjectStorePathConvert>();
services.AddScoped<IOSSService, OSSService>();
builder.AddNewtonsoftJson(options =>
{
//options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
//大驼峰
//options.SerializerSettings.ContractResolver = new DefaultContractResolver();
//小驼峰
//options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
//处理返回给前端 可空类型 给出默认值 比如in? 为null 设置 默认值0
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); //new DefaultContractResolver();// new NullToEmptyStringResolver();
// 设置时间格式
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();
// 设置时间格式 isEn_US? "MM/dd/yyyy HH:mm:ss" :
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
//二者只能取其一
//options.SerializerSettings.Converters.Add(new MyDateTimeConverter());
//options.SerializerSettings.Converters.Add(new MyNullableDateTimeConverter());
//必须放在后面
options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
//options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<CustomStringConverter>());
//IsoDateTimeConverter
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
})
.AddControllersAsServices()//动态webApi属性注入需要
@@ -1,8 +1,10 @@
using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace IRaCIS.Core.API
{
@@ -30,8 +32,20 @@ namespace IRaCIS.Core.API
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
// 检查类是否有 LowerCamelCaseJsonAttribute 标记 有的话,属性名小写
if (type.GetCustomAttribute<LowerCamelCaseJsonAttribute>() != null)
{
base.NamingStrategy= new LowerCamelCaseNamingStrategy();
}
else
{
base.NamingStrategy = null;
}
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
var list= type.GetProperties()
.Select(p =>
{
@@ -9,15 +9,13 @@ using System.Text.RegularExpressions;
namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson
{
public class CustomStringConverter : JsonConverter<string>
public class ObjectStorePathConvert : JsonConverter<string>
{
//private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IOSSService _oSSService;
// 构造函数
public CustomStringConverter(/*IHttpContextAccessor httpContextAccessor*/ IOSSService oSSService)
public ObjectStorePathConvert( IOSSService oSSService)
{
//_httpContextAccessor = httpContextAccessor;
_oSSService = oSSService;
}
@@ -1,18 +1,30 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using System.IO.Compression;
namespace IRaCIS.Core.API
{
public static class ResponseCompressionSetup
public static class ResponseCompressionSetup
{
public static void AddResponseCompressionSetup(this IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
});
services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
}
}
}
@@ -31,13 +31,13 @@ namespace IRaCIS.Core.API
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("LocalIP", httpContext.Connection.LocalIpAddress.MapToIPv4().ToString()));
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserRealName", httpContext?.User?.FindFirst(ClaimAttributes.RealName)?.Value));
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserType", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value));
//这样读取没用
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestBody", await ReadRequestBody(httpContext.Request)));
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", IPHelper.GetIP(httpContext.Request) ));
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserRealName", httpContext?.User?.FindFirst(ClaimAttributes.RealName)?.Value));
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TokenUserType", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value));
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"].ToString()));
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_path", httpContext.Request.Path));
//logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("request_method", httpContext.Request.Method));
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Email;
//using Serilog.Sinks.Email;
using System;
using System.Net;
@@ -3,6 +3,7 @@ using Hangfire.SqlServer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.API
{
@@ -14,19 +15,29 @@ namespace IRaCIS.Core.API
services.AddHangfire(hangFireConfig =>
{
//hangFireConfig.UseInMemoryStorage();
//指定存储介质
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
//本地window 调试 使用内存,服务器部署使用数据库,防止服务器任务调度到本地
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
SchemaName = "dbo",
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
});
hangFireConfig.UseInMemoryStorage();
}
else
{
//指定存储介质
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
{
SchemaName = "dbo",
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
});
}
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
//.UseHangfireHttpJob();
+24 -10
View File
@@ -13,14 +13,16 @@
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "zy-irc-store",
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endpoint": "http://192.168.3.68",
@@ -42,8 +44,15 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
"Port": 465,
@@ -51,7 +60,12 @@
"FromEmail": "uat@extimaging.com",
"FromName": "UAT_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.event.extimaging.com/login"
"SiteUrl": "http://irc.event.extimaging.com/login",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
}
+32 -14
View File
@@ -7,22 +7,24 @@
}
},
"ConnectionStrings": {
// "RemoteNew": "Server=47.117.165.18,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
// "Hangfire": "Server=47.117.165.18,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
//"RemoteNew": "Server=101.132.193.237,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
//"Hangfire": "Server=101.132.193.237,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
"BucketName": "zy-irc-store",
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endpoint": "http://192.168.3.68",
@@ -36,14 +38,22 @@
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"AutoLoginOutMinutes": 360,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
@@ -53,9 +63,17 @@
"FromName": "IRC",
"AuthorizationCode": "ExtImg@2022",
"SiteUrl": "http://irc.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗"
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.193.237"
}
}
+43 -28
View File
@@ -9,7 +9,6 @@
"ConnectionStrings": {
"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"
},
"ObjectStoreService": {
@@ -17,33 +16,36 @@
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"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"
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-test-store",
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "192.168.3.68",
"port": "8001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test",
"viewEndpoint": "http://192.168.3.68:8001/test/"
"EndPoint": "hir-oss.test.extimaging.com",
"Port": "443",
"UseSSL": true,
"AccessKey": "fbStsVYCIPKHQneeqMwD",
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"BucketName": "irc-test",
"ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
},
"AWS": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": true,
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
"secretKey": "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",
"bucketName": "ei-irc-test-store",
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
"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
}
},
@@ -63,7 +65,14 @@
"AutoLoginOutMinutes": 1,
"OpenLoginMFA": false
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
@@ -72,13 +81,19 @@
"FromEmail": "test@extimaging.com",
"FromName": "Test_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.test.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗"
}
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "106.14.89.110"
}
}
@@ -7,19 +7,18 @@
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-mssql-service,1433;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-service,1433;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=44.218.11.19,1435;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=44.218.11.19,1435;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
"Db_Type": "pgsql",
"RemoteNew": "Host=106.14.89.110;Port=5432;Username=sa;Password=pgsql_pwd;Database=Test2_PG",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
@@ -28,17 +27,15 @@
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": {
"endPoint": "192.168.3.68",
"port": "8001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test",
"viewEndpoint": "http://192.168.3.68:8001/test/"
"endPoint": "hir-oss.test.extimaging.com",
"port": "443",
"useSSL": true,
"accessKey": "fbStsVYCIPKHQneeqMwD",
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"bucketName": "irc-test",
"viewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
},
"AWS": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": true,
@@ -48,6 +45,7 @@
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
@@ -60,8 +58,18 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"LoginFailLockMinutes": 1,
"AutoLoginOutMinutes": 1,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
@@ -70,10 +78,18 @@
"FromEmail": "test@extimaging.com",
"FromName": "Test_IRC",
"AuthorizationCode": "SHzyyl2021",
"CompanyName": "Elevate Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗"
}
"SiteUrl": "http://irc.test.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "106.14.89.110"
}
}
@@ -0,0 +1,85 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"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"
//"RemoteNew": "Server=44.210.231.169,1435;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=44.210.231.169,1435;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"MinIO": {
"endPoint": "44.210.231.169",
"port": "9001",
"useSSL": false,
"accessKey": "e9bT1isTOqSAUxb6wd4n",
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i",
"bucketName": "prod-irc-us",
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/"
},
"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
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login",
"IsEnv_US": true
},
"SystemPacsConfig": {
"Port": "104",
"IP": "44.210.231.169"
}
}
@@ -0,0 +1,93 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"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"
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"MinIO": {
//"endPoint": "hir-oss.uat.extimaging.com",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat",
"endPoint": "47.117.164.182",
"port": "9001",
"useSSL": false,
"viewEndpoint": "http://47.117.164.182:9001/test-irc-us",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "test-irc-us"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
"OpenLoginMFA": true
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
"IsEnv_US": true
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
}
}
@@ -0,0 +1,97 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"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"
"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"
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"MinIO": {
//"endPoint": "hir-minio.uat.elevateimaging.ai",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-minio.uat.elevateimaging.ai/uat-irc-us",
"endPoint": "3.226.182.187",
"port": "9001",
"useSSL": false,
"viewEndpoint": "http://44.218.11.19:9001/uat-irc-us",
"accessKey": "lH8DkKskLuDqPaiubuSQ",
"secretKey": "pdPdicvvLeH7xAC5yFUrI7odMyBfOXxvVWMvKYV4",
"bucketName": "uat-irc-us"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
"SecretAccessKey": "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",
"BucketName": "ei-med-s3-lili-uat-store",
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
"DurationSeconds": 7200
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
"OpenLoginMFA": false
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
"IsEnv_US": true
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
}
}
+49 -16
View File
@@ -15,23 +15,41 @@
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-uat-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-uat-store",
"ViewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endpoint": "http://192.168.3.68",
"port": "8001",
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test"
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/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
}
},
@@ -45,7 +63,15 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"AutoLoginOutMinutes": 60,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
@@ -55,11 +81,18 @@
"FromName": "UAT_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.uat.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗"
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "47.117.164.182"
}
}
+9 -35
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": {
"SwitchingMode": "RemainingDiskCapacity",
"SwitchingRatio": 80,
@@ -88,9 +54,17 @@
"QCChallengeCodePrefix": "Q",
"NoneDicomStudyCodePrefix": "NST",
"DicomStudyCodePrefix": "ST",
"TaskStudyCodePrefix": "P-ST",
"SystemSiteCodePrefix": "S",
"DefaultPassword": "123456",
"DefaultInternalOrganizationName": "ExtImaging",
"ImageShareExpireDays": 10
},
"EncrypteResponseConfig": {
"Base64RSAPublicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBaHp3T1hYTWYyaEFkS1ZoWHczYUYNCmNaT3QycE1lcmdEaFVrOUdQK2s4VDBrUjFTRVlGVGtzNlkzaEVvL0dRTExqMHZFYVV3bTNhSFNuTTl5NmdLRWoNCmY5cTN6dkoyZzRSQjE4Z0UrTnNWWi9DMkVRZ3k5OWFiWGc5TitGREVlT0NmSjlSRTJPV3JBQ2s0V0RPbFFUdXYNCnhvR2JmcnkwVElSaFBrOGtuYkFmVkZ1and1VXJGblpJZ0ExYXhKZVZ6aDhwcmV1SEgreW1jdHp6NVo4V1pSV3kNCi9ISURHUy90dkg2NUMra2l6cUxRYUpKNHYwODMrRGpaVTBmNzNCdkk5eWt1dW1saXFzY1pvU2preDFOUFJwSkUNCkFtMVFNQ0hMRCtFdzlHT2Vsc2Mwa1ZxdjdaeEF1TkFrMkZuUURNRk1BUmZuUFd0aGVhOGZYVTJsMW9ROWs3WDcNCmN3SURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==",
"Base64RSAPrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRW9nSUJBQUtDQVFFQWh6d09YWE1mMmhBZEtWaFh3M2FGY1pPdDJwTWVyZ0RoVWs5R1ArazhUMGtSMVNFWQ0KRlRrczZZM2hFby9HUUxMajB2RWFVd20zYUhTbk05eTZnS0VqZjlxM3p2SjJnNFJCMThnRStOc1ZaL0MyRVFneQ0KOTlhYlhnOU4rRkRFZU9DZko5UkUyT1dyQUNrNFdET2xRVHV2eG9HYmZyeTBUSVJoUGs4a25iQWZWRnVqd3VVcg0KRm5aSWdBMWF4SmVWemg4cHJldUhIK3ltY3R6ejVaOFdaUld5L0hJREdTL3R2SDY1QytraXpxTFFhSko0djA4Mw0KK0RqWlUwZjczQnZJOXlrdXVtbGlxc2Nab1Nqa3gxTlBScEpFQW0xUU1DSExEK0V3OUdPZWxzYzBrVnF2N1p4QQ0KdU5BazJGblFETUZNQVJmblBXdGhlYThmWFUybDFvUTlrN1g3Y3dJREFRQUJBb0lCQUNDRFoxNi9XWWFYZmpOZA0KQ29pemU2VFJZU2llVzI5eFJic0ExVDV6YUcwVmY4U1NsdFF2Y1dWYmw2UGJUa3BxMkF4MHJDUVB2M2xOSm8vNA0KL3h3QzRlS1E1c1ZLRlFWTXJIbmhISlRxTTJ6UWVpMkJINlBuaEdZcVh0QVhOdzFxejhrSEoyQlFZM3IvN2d5Qw0KcWpZVFVCRDFRem5HeThCanlXOXVIcnNNeDVPRHRRZWxBM3B1TFd1bXZNb3Z1L2JhaDZvTGtOSHY4b0VTdzhGSQ0KTllyTUtscHhFTjZaWUdwSTl2VTZnYUhuTmhEa2ExTHlvUnZ5NnA2dTRLR0FsRTc1VXk4T0dsdncydU5uay9sdg0KSEMyYnY5TnlCRGJpSFNDY0MyK1JXUXMrN0tNWFlwYnBvTVFCR0hqV01GRHVBODFaUCs1TWYxUm9yQUpRNGxrRw0KQnRDQThva0NnWUVBeWY4alBjcFIvQ3dJNU5MYnlwb3ZUWEFHVkFKMmtWRlJVUC9HT2ZOMkFyYWMvL20wdDJ5NA0KemNYVkJZc0pJeHkvVWYxRTFJNFg3VFg3V3NBNGxVNGlPTkwzTnN4dDBEbk1PV2tKUlBPZlF1bW1JaWw5QVRiYQ0KTnRVWFNlTmRoUFFGMGlCb21acFFJYWpSN1RmUnVBbzR6dmpTLzkzeXZZY0lIWU1zM0tjR00ya0NnWUVBcTJPbg0KZlp0RmhLTElGanVlRzRrNklGTWdjbytEUUh5TTFWSUp5Tk05K1o2TEgybzI5eDJCaSs2Qm82M2NKUjQ2STZncQ0KNWUrSTBvdzZRYmNQeTZUNHFSQ0o3Ujd6MllkdEw4eXdJTkNYS3U0cC9qaFNqNWJ1TzFJWlI3ZStSV29CakNtUQ0KWFd0ZVBCbldqWVlLdVRCazROc2FXV09GTXg1QndKdUp2MjBnQ0hzQ2dZQlV4QnFYM1lWV0cyeUlDZXh1TXhIUw0KbjBZb2p2Z090MTgyYkg5VTVsUUpnM1NTL3NqVmlHeHMvYTROSzNGa0tMWW93KzNVZk9TUmlPdTRBNTQ3R1pURw0KMzlFYVQrTnRWRFBkaTdSMkdQNG1hRUp0WjVlcm9NY2w1M3BrYVdOZlhiL3JrK29STzI2UkVYVTI1UXUrL1pzbA0KVDhuTDBlb0JtdDdPODdNcHpYV09zUUtCZ0ZxVGFQSGx2RUNUY3FEbFV2S0VmRmFXOTkvelhrOFhRNnA5RjdTdA0KaHVSRDJJeDZxcC9BVlRWcGo5Tzd6MHRDaFVGUTM1THpHMkVDUU10My9uNEdLbS9XMEwyakRRWWFIeWNTeXNZYw0KMXJjV2ROVG9XU0dQaDBtTVl0WFhFbFJHNkpoMVl0a3NJL29wUVkwN21MRTBGU3dNUHdtY29jbFpKVEN3UW9VTA0KRzlHL0FvR0FWM25kcWcydnUyR0x4TlRUbm1UTWRJNFB3UzBmN0V4VnVNUnRicGZyOWhKNzlDakVNTGFXQ1FsNg0KeE43TElMTnArNVQwQW1DZVBqcitkbnJkRUNidFZPTDFybDc3Z0krRkwzaVVqYmZmMVZqa0N3M0x6K3cyb1FFdA0KbGE4aTZrL1NRK01iYkRPaWRJOVczdlN6MmlJRlZobWJiK1Q2SlZwakxqNjlkblM3eUxZPQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg==",
"IsResponseEncreptEnable": true,
"ApiPathList": [
"/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>
+4 -4
View File
@@ -31,9 +31,9 @@ namespace IRaCIS.Core.Application.Auth
Id = user.Id,
FullName = user.UserName,
RealName = user.RealName,
UserTypeEnum=user.UserTypeEnum,
UserTypeId=user.UserTypeId,
IsTestUser=user.IsTestUser,
UserTypeEnum = user.UserTypeEnum,
UserTypeId = user.UserTypeId,
IsTestUser = user.IsTestUser,
Code = user.Code,
PermissionStr = user.PermissionStr,
@@ -46,7 +46,7 @@ namespace IRaCIS.Core.Application.Auth
{
Id = doctor.Id,
FullName = doctor.FirstName + doctor.LastName,
Phone = doctor.Phone,
Phone = doctor.Phone,
};
}
}
+2 -8
View File
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Auth
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";
+1 -2
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace IRaCIS.Core.Application.Auth
{
+4 -4
View File
@@ -1,7 +1,7 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Domain.Share;
using Microsoft.Extensions.Options;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
namespace IRaCIS.Core.Application.Auth
{
@@ -56,5 +56,5 @@ namespace IRaCIS.Core.Application.Auth
}
}
}
@@ -1,187 +1,59 @@
using EasyCaching.Core;
using Hangfire;
using Hangfire;
using Hangfire.Storage;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SharpCompress.Common;
namespace IRaCIS.Application.Services.BackGroundJob
namespace IRaCIS.Core.Application.Service.BackGroundJob
{
public interface IIRaCISHangfireJob
{
Task MemoryCacheTrialStatusAsync();
//Task MemoryCacheTrialStatusAsync();
Task InitHangfireJobTaskAsync();
}
public class IRaCISCHangfireJob : IIRaCISHangfireJob
public class IRaCISCHangfireJob(ILogger<IRaCISCHangfireJob> _logger,
IRepository<Internationalization> _internationalizationRepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository
) : IIRaCISHangfireJob
{
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 readonly IRepository<Trial> _trialRepository;
private readonly IEasyCachingProvider _provider;
private readonly ILogger<IRaCISCHangfireJob> _logger;
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
private readonly IRepository<Internationalization> _internationalizationRepository;
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
{
_trialRepository = trialRepository;
_provider = provider;
_logger = logger;
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
_internationalizationRepository = internationalizationRepository;
_systemAnonymizationRepository = systemAnonymizationRepository;
}
public async Task InitHangfireJobTaskAsync()
{
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
//初始化国际化
//项目状态 立即加载到缓存中
await MemoryCacheTrialStatusAsync();
await MemoryCacheAnonymizeData();
//创建项目缓存 定时任务
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
//初始化
await InitInternationlizationDataAndWatchJsonFileAsync();
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
//创建邮件定时任务
await InitSysAndTrialCronJobAsync();
#region
////项目状态 立即加载到缓存中
//await MemoryCacheTrialStatusAsync();
////await MemoryCacheAnonymizeData();
////创建项目缓存 定时任务
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
#endregion
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
}
/// <summary>
/// 缓存项目状态
/// </summary>
/// <returns></returns>
public async Task MemoryCacheTrialStatusAsync()
{
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToListAsync();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
public async Task MemoryCacheAnonymizeData()
{
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
}
#region
public async Task InitInternationlizationDataAndWatchJsonFileAsync()
{
//查询数据库的数据
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
{
t.Code,
t.Value,
t.ValueCN
}).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;
}
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"));
}
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(usJsonPath);
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(cnJsonPath);
}
private void LoadJsonFile(string filePath)
{
Console.WriteLine("刷新json内存数据");
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath,false,true);
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;
}
}
}
#endregion
public async Task InitSysAndTrialCronJobAsync()
{
@@ -223,6 +95,9 @@ namespace IRaCIS.Application.Services.BackGroundJob
}
}
@@ -1,11 +1,10 @@
using IRaCIS.Core.Infra.EFCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.Application.BackGroundJob
{
public interface IObtainTaskAutoCancelJob
{
Task CancelQCObtaion(Guid subjectVisitId,DateTime startTime);
Task CancelQCObtaion(Guid subjectVisitId, DateTime startTime);
}
public class ObtainTaskAutoCancelJob : IObtainTaskAutoCancelJob
@@ -13,7 +12,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly ILogger<ObtainTaskAutoCancelJob> _logger;
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
public ObtainTaskAutoCancelJob(IRepository<SubjectVisit> subjectVisitRepository, ILogger<ObtainTaskAutoCancelJob> logger)
{
_subjectVisitRepository = subjectVisitRepository;
_logger = logger;
@@ -30,7 +29,7 @@ namespace IRaCIS.Core.Application.BackGroundJob
var success = await _subjectVisitRepository.SaveChangesAsync();
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{ subjectVisitId }success:{success}");
_logger.LogWarning($"任务建立时间:{startTime} 取消时间:{DateTime.Now} 取消 受试者访视:{subjectVisitId}success:{success}");
}
catch (Exception e)
{
+18 -17
View File
@@ -1,15 +1,16 @@
using AutoMapper;
using IRaCIS.Application.Services.BusinessFilter;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application
namespace IRaCIS.Core.Application.Service
{
#pragma warning disable CS8618
@@ -17,20 +18,21 @@ namespace IRaCIS.Core.Application
#region
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
[TypeFilter(typeof(UnifiedApiResultFilter))]
[Authorize, DynamicWebApi]
public class BaseService : IBaseService, IDynamicWebApi
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
public IRepository _repository { get; set; }
public IStringLocalizer _localizer { get; set; }
public IWebHostEnvironment _hostEnvironment { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
@@ -49,8 +51,6 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_userInfo))]
public IUserInfo _userInfo { get; set; }
[MemberNotNull(nameof(_repository))]
public IRepository _repository { get; set; }
[MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; }
@@ -58,6 +58,9 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_hostEnvironment))]
public IWebHostEnvironment _hostEnvironment { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
}
#endregion
@@ -73,28 +76,26 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_userInfo))]
public IUserInfo _userInfo { get; set; }
[MemberNotNull(nameof(_repository))]
public IRepository _repository { get; set; }
[MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
}
[Authorize, DynamicWebApi, UnifiedApiResultFilter]
[TypeFilter(typeof(UnifiedApiResultFilter))]
[Authorize, DynamicWebApi]
public class BaseServiceTest<T> : IBaseServiceTest<T>, IDynamicWebApi where T : Entity
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
public IRepository _repository { get; set; }
public IStringLocalizer _localizer { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{
return new ResponseOutput<string>()
@@ -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);
}
}
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.Application.BusinessFilter;
/// <summary>
/// 不生效,不知道为啥
/// </summary>
public class GlobalExceptionHandler : IExceptionHandler
{
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";
var ex = exception;
var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
_logger.LogError(errorInfo);
// return true to signal that this exception is handled
return ValueTask.FromResult(false);
}
}
@@ -1,13 +1,12 @@
using EasyCaching.Core;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application.Filter;
@@ -18,15 +17,15 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
{
public IStringLocalizer _localizer { get; set; }
private readonly IEasyCachingProvider _provider;
private readonly IFusionCache _fusionCache;
private readonly IUserInfo _userInfo;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo, IStringLocalizer localizer ,IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
public LimitUserRequestAuthorization(IFusionCache fusionCache, IUserInfo userInfo, IStringLocalizer localizer, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
{
_provider = provider;
_fusionCache = fusionCache;
_userInfo = userInfo;
_verifyConfig = verifyConfig;
_localizer = localizer;
@@ -54,7 +53,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
{
context.HttpContext.Response.ContentType = "application/json";
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
//---当前请求未从Header/Url取到用户Token,请联系开发者
//---当前请求未从Header/Url取到用户Token,请联系开发者
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
@@ -63,7 +62,7 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
//2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉
var cacheUserToken = (await _provider.GetAsync<string>(_userInfo.Id.ToString())).Value;
var cacheUserToken = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserToken(_userInfo.Id));
@@ -73,17 +72,17 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
cacheUserToken = _userInfo.UserToken;
//设置当前用户最新Token
await _provider.SetAsync(_userInfo.Id.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7));
await _fusionCache.SetAsync(CacheKeys.UserToken(_userInfo.Id), _userInfo.UserToken, TimeSpan.FromDays(7));
//重启应用程序,所有人续期,不一下子踢出所有人
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
}
//是同一个人
else if (cacheUserToken == _userInfo.UserToken)
{
var cacheTime = (await _provider.GetAsync<string>($"{_userInfo.Id.ToString()}_Online")).Value;
var cacheTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserAutoLoginOut(_userInfo.Id));
//过期了 需要自动退出
if (string.IsNullOrEmpty(cacheTime))
@@ -92,32 +91,22 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
}
else
{
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.Id), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
}
}
else
{
context.HttpContext.Response.ContentType = "application/json";
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
//---您的账户在其他地方已登陆,您被迫下线。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace)));
}
}
}
@@ -125,52 +114,3 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
}
}
//public class UserTypeRequirement : IAuthorizationRequirement
//{
//}
//public class UserTypeHandler : AuthorizationHandler<UserTypeRequirement>
//{
// private IUserInfo _userInfo;
// public UserTypeHandler(IUserInfo userInfo)
// {
// _userInfo = userInfo;
// }
// protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserTypeRequirement requirement)
// {
// //if (context.User.Claims.Count() == 0)
// //{
// // return Task.CompletedTask;
// //}
// //string userId = context.User.Claims.First(c => c.Type == "Userid").Value;
// //string qq = context.User.Claims.First(c => c.Type == "QQ").Value;
// //if (_UserService.Validata(userId, qq))
// //{
// // context.Succeed(requirement); //验证通过了
// //}
// ////在这里就可以做验证
// return Task.CompletedTask;
// }
//}
@@ -1,37 +1,34 @@
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
namespace IRaCIS.Core.Application.Filter
namespace IRaCIS.Core.Application.Filter;
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
{
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
public IStringLocalizer _localizer;
public ModelActionFilter(IStringLocalizer localizer)
{
public IStringLocalizer _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)));
}
}
_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)));
}
}
}
@@ -1,28 +1,26 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
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
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
public void OnResourceExecuting(ResourceExecutingContext context)
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
//factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
var factories = context.ValueProviderFactories;
//factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
#endregion
}
#endregion
@@ -1,61 +1,75 @@
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
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;
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
if (!context.ExceptionHandled)
{
_logger = logger;
_localizer = localizer;
}
public void OnException(ExceptionContext context)
{
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
if (!context.ExceptionHandled)
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
{
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
{
//---并发更新,当前不允许该操作
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
}
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
}
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
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))
{
var error = context.Exception as BusinessValidationFailedException;
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code));
}
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));
info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
}
_logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
//warning 级别记录
//_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
}
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
{
//继续
}
}
}
@@ -1,215 +1,196 @@
using EasyCaching.Core;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using System.Text.RegularExpressions;
using ZiggyCreatures.Caching.Fusion;
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>
/// 主要为了 处理项目结束 锁库,不允许操作
/// </summary>
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
private readonly IUserInfo _userInfo;
private readonly IFusionCache _fusionCache;
public IStringLocalizer _localizer;
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 IEasyCachingProvider _provider;
private readonly IUserInfo _userInfo;
_fusionCache = fusionCache;
_userInfo = userInfo;
_localizer = localizer;
_trialRepository = trialRepository;
public IStringLocalizer _localizer;
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(IEasyCachingProvider provider, 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))
{
_provider = provider;
_userInfo = userInfo;
_localizer = localizer;
//_trialOpt = trialOpt;
await next.Invoke();
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 TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
//{
// _provider = provider;
// _userInfo = userInfo;
//}
//优先选择异步的方法
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;
}
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower())
#endregion
//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)
{
//---对不起,您的账户没有操作权限。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
return;
trialIdStr = matchResult.Value;
}
else
{
//---正则取请求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
var trialIdStr = string.Empty;
if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
if (trialIdIndex > -1)
{
trialIdStr = context.HttpContext.Request.Query["trialId"];
}
// (?<="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();
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
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}");
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;
}
else
{
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
}
}
else
{
#region body
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
//设置可以多次读
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)
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
if (!string.IsNullOrWhiteSpace(trialStatusStr))
{
trialIdStr = matchResult.Value;
}
}
else
{
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
//数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
return;
}
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
}
#endregion
}
//通过path 或者body 找到trialId 了
if ( !string.IsNullOrWhiteSpace(trialIdStr))
{
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
if (_provider.GetCount() == 0)
{
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToList();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
var trialStatusStr = cacheResultDic[trialIdStr].Value;
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
}
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,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"]));
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
return;
}
}
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId))
{
await next.Invoke();
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
}
#endregion
}
//通过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))
{
await next.Invoke();
}
// 项目停止、或者完成 不允许操作
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,119 +1,122 @@
using Microsoft.AspNetCore.Mvc.Filters;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc.Filters;
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
{
private readonly ILogger _logger;
public UnifiedApiResultFilter(ILogger<UnifiedApiResultFilter> logger)
{
_logger = logger;
}
/// <summary>
/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
/// by zhouhang 2021.09.12 周末
/// 异步版本
/// </summary>
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{
/// <summary>
/// 异步版本
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
/// <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;
if (context.Result is ObjectResult objectResult)
//是200 并且没有包装 那么包装结果
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
{
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
//是200 并且没有包装 那么包装结果
if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
var type = objectResult.Value?.GetType();
if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
{
//if (objectResult.Value == null)
//{
// var apiResponse = ResponseOutput.DBNotExist();
// objectResult.Value = apiResponse;
// objectResult.DeclaredType = apiResponse.GetType();
//}
//else
//{
//报错
//var tuple = (object, object))objectResult.Value;
//var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
//var apiResponse = ResponseOutput.Ok(val1, val2);
var type = objectResult.Value?.GetType();
//OK
var tuple = (dynamic)objectResult.Value;
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
if ( type!=null&& type.IsGenericType&&(type.GetGenericTypeDefinition()==typeof(ValueTuple<,>)|| type.GetGenericTypeDefinition()==typeof(Tuple<,>)))
{
//报错
//var tuple = (object, object))objectResult.Value;
//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 if (statusCode != 200 && (objectResult.Value is IResponseOutput))
else
{
}
else if(statusCode != 200&&!(objectResult.Value is IResponseOutput))
{
//---程序错误,请联系开发人员。
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
var apiResponse = ResponseOutput.Ok(objectResult.Value);
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)
//如果是200 是IResponseOutput 记录下日志
else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
{
if (type.IsGenericType)
var result = objectResult.Value as IResponseOutput;
if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(Tuple<>)
|| genType == typeof(Tuple<,>)
|| genType == typeof(Tuple<,>))
return true;
//统一在这里记录国际化的日志信息
_logger.LogWarning($"{result.LocalizedInfo}");
}
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;

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