Compare commits

..

611 Commits

Author SHA1 Message Date
hang 1033ff665c 修改美国配置文件
continuous-integration/drone/push Build is passing Details
2025-11-28 16:56:51 +08:00
hang f8478887ce 修改uat 配置文件
continuous-integration/drone/push Build is passing Details
2025-11-26 13:33:08 +08:00
hang 763984ca62 增加检查数量字段
continuous-integration/drone/push Build is passing Details
2025-11-24 16:23:55 +08:00
hang efbaae2a97 修改影像下载检查过滤2
continuous-integration/drone/push Build is passing Details
2025-11-24 15:57:13 +08:00
hang 49e4980fd0 修改影像下载检查过滤
continuous-integration/drone/push Build is passing Details
2025-11-24 15:48:07 +08:00
hang b2bcc37dab 修改配置文件
continuous-integration/drone/push Build is passing Details
2025-11-24 10:48:40 +08:00
hang 32ee818be8 修改配置文件
continuous-integration/drone/push Build is passing Details
2025-11-24 10:35:52 +08:00
hang d042be7828 修改DIR 验证
continuous-integration/drone/push Build is passing Details
2025-11-21 17:16:29 +08:00
hang 2017d781bf 修改下载列表
continuous-integration/drone/push Build is passing Details
2025-11-21 16:00:01 +08:00
hang fccf6686eb 修改返回名称
continuous-integration/drone/push Build is passing Details
2025-11-21 15:08:42 +08:00
hang 88f40125e1 修改请求方式
continuous-integration/drone/push Build is passing Details
2025-11-21 14:50:00 +08:00
hang facb318180 修改维护脚本
continuous-integration/drone/push Build is passing Details
2025-11-21 13:44:33 +08:00
hang 62352738e8 修改下载
continuous-integration/drone/push Build is passing Details
2025-11-21 11:44:43 +08:00
hang a22b7802b7 修改邮件配置文件
continuous-integration/drone/push Build is passing Details
2025-11-21 09:36:58 +08:00
hang 6aaeeeaeb9 修改下限制
continuous-integration/drone/push Build is passing Details
2025-11-11 17:24:27 +08:00
hang 7b606aee05 修改scp 服务bug
continuous-integration/drone/push Build is passing Details
2025-11-11 17:19:28 +08:00
hang 841f1892d4 修改接收转发多线程配置
continuous-integration/drone/push Build is passing Details
2025-11-03 13:12:11 +08:00
hang 106916f7ad 转发时传递目标AE
continuous-integration/drone/push Build is passing Details
2025-10-30 11:27:29 +08:00
hang 46ab1fc7bc 配置从数据库取,同时返回控制开关
continuous-integration/drone/push Build is passing Details
2025-10-30 11:18:06 +08:00
hang 3328c18279 限制不能空条件查询
continuous-integration/drone/push Build is passing Details
2025-10-28 18:03:15 +08:00
hang aed778bbc6 HIR 对接第三方初步测试完毕
continuous-integration/drone/push Build is passing Details
2025-10-28 15:08:23 +08:00
hang 064e3836ca 修改配置文件
continuous-integration/drone/push Build is passing Details
2025-10-28 11:21:36 +08:00
hang 3407f2f00d HIR服务注册遗漏
continuous-integration/drone/push Build is passing Details
2025-10-28 09:46:27 +08:00
hang e496cf1117 对接联影,转发c-find c-move请求,并且发送c-store 请求
continuous-integration/drone/push Build is passing Details
2025-10-27 15:26:49 +08:00
he e5f6685719 PCWG LastTaskState 取值修改
continuous-integration/drone/push Build is passing Details
2025-10-09 15:30:38 +08:00
he 837a3f66d5 修改
continuous-integration/drone/push Build is passing Details
2025-09-28 13:48:00 +08:00
he 0201c2f50f 修改
continuous-integration/drone/push Build is running Details
2025-09-28 13:44:48 +08:00
he a7ed38f03b 数据库可插入null
continuous-integration/drone/push Build is passing Details
2025-09-28 12:46:35 +08:00
he a436571364 修改
continuous-integration/drone/push Build is passing Details
2025-09-28 12:18:47 +08:00
he 34e6e1583e 修改
continuous-integration/drone/push Build is passing Details
2025-09-28 12:13:18 +08:00
he 400504db74 代码修改
continuous-integration/drone/push Build is passing Details
2025-09-28 09:09:09 +08:00
he 88e7febec5 修改
continuous-integration/drone/push Build is passing Details
2025-09-26 17:46:54 +08:00
he 02a49b2239 修改
continuous-integration/drone/push Build is passing Details
2025-09-26 17:17:56 +08:00
he d72b28afc2 修改
continuous-integration/drone/push Build is passing Details
2025-09-26 15:53:02 +08:00
he 2ba9e6e2d4 修改
continuous-integration/drone/push Build is passing Details
2025-09-26 14:59:43 +08:00
he 1d38ee3f49 代码修改
continuous-integration/drone/push Build is passing Details
2025-09-26 10:49:49 +08:00
he 9879625781 修改
continuous-integration/drone/push Build is passing Details
2025-09-26 09:17:48 +08:00
he a0f5e7b7e5 计算修改
continuous-integration/drone/push Build is passing Details
2025-09-25 18:01:10 +08:00
he 337d0fa05f 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-25 17:42:24 +08:00
he 5d3df0b1f5 修改
continuous-integration/drone/push Build is running Details
2025-09-25 17:40:16 +08:00
he dd4cd5d330 修改
continuous-integration/drone/push Build is passing Details
2025-09-25 17:32:51 +08:00
he 3c28be9bf0 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-25 17:19:49 +08:00
he 6e75404175 提交
continuous-integration/drone/push Build is passing Details
2025-09-25 17:12:37 +08:00
he 5b08640a02 修改
continuous-integration/drone/push Build is passing Details
2025-09-25 16:55:37 +08:00
he 9b3e4194a9 修改
continuous-integration/drone/push Build is passing Details
2025-09-25 16:22:28 +08:00
he c4eabde7a9 修改最多5条靶病灶
continuous-integration/drone/push Build is running Details
2025-09-25 16:21:10 +08:00
he 66e5570d82 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-25 13:59:28 +08:00
he d1be23a69e 模板修改
continuous-integration/drone/push Build is passing Details
2025-09-25 13:51:46 +08:00
he 0ef8604da0 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-25 13:47:40 +08:00
he 05124428ad Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-25 13:33:21 +08:00
he 17ce41209f 导出模板修改 2025-09-25 13:33:19 +08:00
hang a1afbc2487 访视退回过滤
continuous-integration/drone/push Build is passing Details
2025-09-24 17:26:03 +08:00
hang 3f6e006a95 修改提交事务
continuous-integration/drone/push Build is passing Details
2025-09-24 16:11:44 +08:00
hang 380546ca3c 增加影像退回接口
continuous-integration/drone/push Build is passing Details
2025-09-23 16:13:17 +08:00
hang e4cf4cc8b8 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-23 10:08:14 +08:00
hang ed580eab74 界面增加检查数量 2025-09-23 10:08:13 +08:00
he 2530843931 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-22 11:06:48 +08:00
he c4b588376d 修改计算 2025-09-22 11:06:45 +08:00
hang e63d6ba652 增加额外日志
continuous-integration/drone/push Build is passing Details
2025-09-19 17:57:16 +08:00
hang 64ef4ea0f2 继续增加日志
continuous-integration/drone/push Build is passing Details
2025-09-19 17:49:17 +08:00
hang b293559225 修改客户端断网测试
continuous-integration/drone/push Build is passing Details
2025-09-19 17:34:12 +08:00
hang 7214626850 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-19 16:48:35 +08:00
hang a4ef209fb1 修改影像接收设置失败标志 2025-09-19 16:48:33 +08:00
he e4cc044219 修改
continuous-integration/drone/push Build is passing Details
2025-09-19 15:56:05 +08:00
he db6c0457ae Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-19 14:56:44 +08:00
he e745271671 修改PD计算 2025-09-19 14:56:42 +08:00
hang 34686b10cc Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-19 13:16:04 +08:00
hang 711c4c5888 增加查询条件,通过邮件获取用户修改 2025-09-19 13:16:02 +08:00
he 3d19ee7b04 修改计算
continuous-integration/drone/push Build is passing Details
2025-09-18 16:52:01 +08:00
he 72fd347c01 修改
continuous-integration/drone/push Build is passing Details
2025-09-18 14:17:16 +08:00
he 4c1da73c33 修改
continuous-integration/drone/push Build is passing Details
2025-09-18 13:25:11 +08:00
he 2b01c777a7 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-18 10:00:44 +08:00
he d1ae500735 修改PCWG计算 2025-09-18 10:00:41 +08:00
hang 214ea985d9 返回studyUid 自动激活1个月判断
continuous-integration/drone/push Build is passing Details
2025-09-17 17:45:11 +08:00
hang 95fe063706 修改归档属性
continuous-integration/drone/push Build is passing Details
2025-09-17 16:41:38 +08:00
hang b6ceca9744 修改患者检查列表和查询
continuous-integration/drone/push Build is passing Details
2025-09-17 15:03:59 +08:00
hang 42e9c58d7a Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-17 14:17:29 +08:00
hang 8356fff9ce 通过邮箱获取用户信息 2025-09-17 14:17:26 +08:00
he e6f91b9c4b 同步所有pcwg标准
continuous-integration/drone/push Build is passing Details
2025-09-17 13:46:28 +08:00
he ba9c88d836 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-17 11:20:33 +08:00
he 237260dbd0 修改 2025-09-17 11:20:32 +08:00
hang 5a2136f205 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build was killed Details
2025-09-17 10:49:18 +08:00
hang f9d69995d3 scp 服务记录日志修改 2025-09-17 10:49:16 +08:00
he 32d78f556c Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-09-17 10:47:00 +08:00
he d11afb10de 修改 2025-09-17 10:46:59 +08:00
hang 67e7eaaa96 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-17 10:36:50 +08:00
hang af95166782 修改scp 服务监控 2025-09-17 10:36:48 +08:00
he 29093e5617 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-17 09:08:19 +08:00
he b68c00c1b4 修改PCWG 自治疗后第二个访视点以来持续的新骨病变数量 计算 2025-09-17 09:08:18 +08:00
hang 2d06b12368 修改最新推送时间
continuous-integration/drone/push Build is passing Details
2025-09-16 18:05:47 +08:00
hang 0f7b80ff63 删除废弃
continuous-integration/drone/push Build is passing Details
2025-09-16 17:56:05 +08:00
hang 96c8b5d7f8 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-16 17:14:11 +08:00
hang 4ec15c2333 修改推送检查数量 2025-09-16 17:14:08 +08:00
he 11d5722f46 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-16 16:33:12 +08:00
he a079451951 导出模板去除TNM分期 2025-09-16 16:33:10 +08:00
hang eb7db8478f Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-16 14:53:37 +08:00
hang 444d5c8005 修改搜索条件 2025-09-16 14:53:32 +08:00
he d97edf6688 修改稽查
continuous-integration/drone/push Build is passing Details
2025-09-15 16:41:58 +08:00
he 359a6bf602 添加PCWG临时答案
continuous-integration/drone/push Build is passing Details
2025-09-15 16:17:35 +08:00
he bab20666af 稽查修改
continuous-integration/drone/push Build is passing Details
2025-09-15 15:51:50 +08:00
he 05244cdaf7 res 同步病灶调整
continuous-integration/drone/push Build is passing Details
2025-09-15 14:35:18 +08:00
he ef1b76f98c 修改
continuous-integration/drone/push Build is passing Details
2025-09-15 14:25:17 +08:00
he f887699341 稽查修改
continuous-integration/drone/push Build is passing Details
2025-09-15 13:47:51 +08:00
he 6b97d1ce68 稽查修改
continuous-integration/drone/push Build is passing Details
2025-09-15 13:14:00 +08:00
he 334e51d9fd MRECISTHCC 同步病灶
continuous-integration/drone/push Build is passing Details
2025-09-15 11:43:47 +08:00
he 8b43474734 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-15 11:31:10 +08:00
he 149cca011a PWCG 计算 2025-09-15 11:31:08 +08:00
hang aa63ca2def Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 18:37:33 +08:00
hang 9dcb63bdf2 修改scp 测试 2025-09-12 18:37:30 +08:00
he 323534e52b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 17:57:18 +08:00
he b432002266 计算修改 2025-09-12 17:57:17 +08:00
hang e03884227e 增加环境启动
continuous-integration/drone/push Build is passing Details
2025-09-12 17:21:08 +08:00
he 0580b11e39 修改
continuous-integration/drone/push Build is passing Details
2025-09-12 16:54:44 +08:00
he 90a3021938 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 16:45:12 +08:00
he bc3f5c9394 PCWG间隔天数基线改为NA 2025-09-12 16:45:11 +08:00
hang 9e3eafa925 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 13:57:42 +08:00
hang 98f0e9e1a1 修改美国配置文件 2025-09-12 13:57:41 +08:00
he b66b3fcc6c 修改
continuous-integration/drone/push Build is passing Details
2025-09-12 13:40:09 +08:00
he 608f6387ae 修改
continuous-integration/drone/push Build is passing Details
2025-09-12 13:31:05 +08:00
he 4f7e73c990 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 13:23:06 +08:00
he 8baa8b7421 MRECISTHCCC 同步病灶修改 2025-09-12 13:23:05 +08:00
hang bb38899cee Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 13:17:14 +08:00
hang 64f04a3953 维护代码修改-人员添加默认课题组 2025-09-12 13:17:12 +08:00
he 38a42dc44f 去除报告缓存
continuous-integration/drone/push Build is passing Details
2025-09-12 11:35:41 +08:00
he 4c396dc4ae 修改复制 recist1.1 淋巴结病灶状态
continuous-integration/drone/push Build is passing Details
2025-09-12 11:30:52 +08:00
he e17d973fad 去掉骨扫描筛选
continuous-integration/drone/push Build is passing Details
2025-09-12 11:06:21 +08:00
he 1efe15a776 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-12 11:01:00 +08:00
he d7f87f77ab 删除FristAddTaskNum 2025-09-12 11:00:57 +08:00
hang 7eff5fd1bb 项目参与人员 去掉GA
continuous-integration/drone/push Build is passing Details
2025-09-12 09:49:55 +08:00
hang 2fe3441c3f 修改编译错误
continuous-integration/drone/push Build is passing Details
2025-09-12 09:07:34 +08:00
hang 98741d9a3b 接收影像第一张的时候就开始打标签
continuous-integration/drone/push Build is passing Details
2025-09-12 09:00:59 +08:00
hang 9386b89110 修改登出bug
continuous-integration/drone/push Build is passing Details
2025-09-11 17:46:03 +08:00
hang 32ca60156e 患者直接加入项目过滤
continuous-integration/drone/push Build is passing Details
2025-09-11 15:49:49 +08:00
hang b2022a912f 修改课题组绑定,和GA用户列表查看
continuous-integration/drone/push Build is passing Details
2025-09-11 14:52:32 +08:00
hang ffedc3f378 修改检查绑定+ GA 看到的课题组过滤
continuous-integration/drone/push Build is passing Details
2025-09-11 14:29:45 +08:00
hang 6d042459e3 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-11 14:09:27 +08:00
hang 0a5164682f admin 可以看所有医院,不受默认医院影响 2025-09-11 14:09:21 +08:00
he 62037c0d43 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-10 17:29:38 +08:00
he ec45d80b9b 修改
continuous-integration/drone/push Build is passing Details
2025-09-10 16:35:52 +08:00
he 4187673b7a 修改
continuous-integration/drone/push Build is passing Details
2025-09-10 15:59:41 +08:00
he ad62ad7ae0 代码提交
continuous-integration/drone/push Build is passing Details
2025-09-10 15:48:35 +08:00
he 87709f0122 Ires肿瘤导出
continuous-integration/drone/push Build is passing Details
2025-09-10 15:25:03 +08:00
he 5ade2135ee 修改
continuous-integration/drone/push Build is passing Details
2025-09-10 15:11:34 +08:00
he f0a38ebec9 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-10 14:43:21 +08:00
he 15b50e39f1 代码修改 2025-09-10 14:43:19 +08:00
hang 5f71d7f1b2 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-10 13:12:43 +08:00
hang f4f94f1f48 增加课题组标签 相关接口 2025-09-10 13:12:40 +08:00
he 21cafcab53 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-10 11:14:13 +08:00
he c37903b2f4 bug 修改 2025-09-10 11:14:10 +08:00
hang 1fc70b1340 增加课题组标签,以及患者和标签关联
continuous-integration/drone/push Build is passing Details
2025-09-10 10:54:56 +08:00
hang 36844c291a Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-10 10:36:33 +08:00
hang 9b96259e59 修改课题组展示 2025-09-10 10:36:32 +08:00
he 4c3a96a0f6 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is failing Details
2025-09-09 18:12:17 +08:00
he 154c12eb93 稽查单位 2025-09-09 18:12:16 +08:00
hang c09f27bf7d Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 18:00:04 +08:00
hang f80ac02562 账号课题组启用禁用,系统课题组启用禁用实时修改 2025-09-09 18:00:03 +08:00
he f49d2ce06b 添加单位
continuous-integration/drone/push Build is passing Details
2025-09-09 17:42:39 +08:00
he eff5920568 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 17:07:07 +08:00
he 05be768188 单位翻译 2025-09-09 17:07:05 +08:00
hang c9387463ba 默认单位修改
continuous-integration/drone/push Build is passing Details
2025-09-09 15:41:51 +08:00
hang b230139f67 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 15:24:17 +08:00
hang d833093c33 设置subject 访视软删除 2025-09-09 15:24:11 +08:00
he c62fb1df92 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 14:49:53 +08:00
he 8c1a25aae3 稽查修改 2025-09-09 14:49:52 +08:00
hang 758e0aedcb 修改项目绑定检查课题组
continuous-integration/drone/push Build is passing Details
2025-09-09 14:41:04 +08:00
hang 563be56d27 PM 创建项目课题组下拉框
continuous-integration/drone/push Build is passing Details
2025-09-09 13:19:09 +08:00
hang db2bd6b725 增加用户列表查询条件
continuous-integration/drone/push Build is passing Details
2025-09-09 11:42:20 +08:00
hang 81d9fcae2e 修改国际化
continuous-integration/drone/push Build is passing Details
2025-09-09 11:38:17 +08:00
hang ea87692f49 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 10:49:44 +08:00
hang cee9d92a72 修改课题组 和导表去掉中心查询 2025-09-09 10:49:41 +08:00
he bbe89ade16 修改
continuous-integration/drone/push Build is passing Details
2025-09-09 09:47:43 +08:00
he 16e348a996 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-09 09:09:18 +08:00
he b6e3032767 修改 2025-09-09 09:09:16 +08:00
hang 690c759fa1 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-08 18:00:52 +08:00
hang 56a15f3b61 修改上传 2025-09-08 18:00:50 +08:00
he 589e9868a8 修改
continuous-integration/drone/push Build is passing Details
2025-09-08 16:32:23 +08:00
he 82afae93dc Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-08 16:00:55 +08:00
he 6875cf3188 修改 2025-09-08 16:00:53 +08:00
hang 076d99c6ba 增加通用工具返回路径
continuous-integration/drone/push Build is passing Details
2025-09-08 15:38:30 +08:00
hang 79d39125ff 或者文档
continuous-integration/drone/push Build is running Details
2025-09-08 15:35:07 +08:00
hang aafc1cd064 当前登录用户得课题组
continuous-integration/drone/push Build is passing Details
2025-09-08 15:26:08 +08:00
hang 26e7305bcf 返回课题组编码 和AE 限制
continuous-integration/drone/push Build is passing Details
2025-09-08 14:44:30 +08:00
hang d1e08b0fc0 漏提交事务
continuous-integration/drone/push Build is passing Details
2025-09-08 10:30:15 +08:00
hang df87c56544 导表Excel处理
continuous-integration/drone/push Build is passing Details
2025-09-05 16:34:48 +08:00
he a3b69d45ae 添加字段
continuous-integration/drone/push Build is passing Details
2025-09-05 15:16:46 +08:00
he ef95cdd4ec 添加字段
continuous-integration/drone/push Build is passing Details
2025-09-05 15:12:02 +08:00
he 4d7d42753f 修改
continuous-integration/drone/push Build is passing Details
2025-09-05 14:44:35 +08:00
he 9e9db251c8 修改
continuous-integration/drone/push Build is passing Details
2025-09-05 14:37:17 +08:00
he 8b1626e292 阅片期查询修改
continuous-integration/drone/push Build is passing Details
2025-09-05 14:21:50 +08:00
he a5a2dcdac9 PCWG需要全局
continuous-integration/drone/push Build is passing Details
2025-09-05 13:16:47 +08:00
he 93ea0cf8d1 修改模板
continuous-integration/drone/push Build is passing Details
2025-09-05 11:38:04 +08:00
he b91ea2c176 导出修改
continuous-integration/drone/push Build is passing Details
2025-09-05 11:22:03 +08:00
he 75be9eba74 导出修改
continuous-integration/drone/push Build is passing Details
2025-09-05 11:06:14 +08:00
he 335535d6d3 英文模版导出修改
continuous-integration/drone/push Build is passing Details
2025-09-05 10:13:29 +08:00
he 8b61b288fc Reapply "先改IRes导出"
This reverts commit f08a5b0d46.
2025-09-05 09:55:01 +08:00
he f08a5b0d46 Revert "先改IRes导出"
This reverts commit 7bc3378e0c.
2025-09-05 09:51:09 +08:00
he 7bc3378e0c 先改IRes导出
continuous-integration/drone/push Build is passing Details
2025-09-05 09:50:46 +08:00
he b87e531920 修改
continuous-integration/drone/push Build is passing Details
2025-09-04 14:50:27 +08:00
he d5234db48a 重置阅片任务
continuous-integration/drone/push Build is passing Details
2025-09-04 13:30:47 +08:00
he 7f6933df35 典型肝内病灶添加
continuous-integration/drone/push Build is running Details
2025-09-04 13:29:47 +08:00
he 70bff24348 修改患者编号
continuous-integration/drone/push Build is failing Details
2025-09-04 11:40:35 +08:00
he a8a1198c52 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-04 11:24:09 +08:00
he bd83153743 加入TNM分期 2025-09-04 11:24:07 +08:00
hang deeffe034b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-04 11:18:58 +08:00
hang 39f579c10b 国际化修改提交 2025-09-04 11:18:56 +08:00
he 77eac6c1d0 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-04 09:46:54 +08:00
he 5cc192b317 导出修改 2025-09-04 09:46:53 +08:00
hang ba12a2977b 修改存储服务存储非封装的影像
continuous-integration/drone/push Build is passing Details
2025-09-03 16:32:54 +08:00
hang 1a7576039b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-03 16:25:49 +08:00
hang 780f6451c3 修改稽查 2025-09-03 16:25:47 +08:00
he b576478eea Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-03 15:45:26 +08:00
he 8cbc5c5c26 发布 2025-09-03 15:45:25 +08:00
hang 0245aaf7ad Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build was killed Details
2025-09-03 15:42:32 +08:00
hang d954d13f81 minio 6.0.4 2025-09-03 15:42:30 +08:00
he c9e12993a6 修改
continuous-integration/drone/push Build is running Details
2025-09-03 15:40:58 +08:00
he 088a0b6fd5 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-03 15:36:06 +08:00
he 6b18e5eced 修改 2025-09-03 15:36:04 +08:00
hang 5673fcad5f 修改获取请求url测试
continuous-integration/drone/push Build is passing Details
2025-09-03 15:30:48 +08:00
hang 697ac6f57b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-03 15:21:05 +08:00
hang e9b3b012f9 修改minio 版本测试 2025-09-03 15:21:03 +08:00
he d5d3d6e1c9 修改
continuous-integration/drone/push Build is passing Details
2025-09-03 15:03:03 +08:00
he 712d87a4dd 修改
continuous-integration/drone/push Build is passing Details
2025-09-03 14:47:52 +08:00
he f082217e99 稽查修改
continuous-integration/drone/push Build is passing Details
2025-09-03 14:43:15 +08:00
hang 16e5a0567f 修改查询
continuous-integration/drone/push Build is passing Details
2025-09-03 13:49:29 +08:00
hang 5fa12786aa 修改版本
continuous-integration/drone/push Build is passing Details
2025-09-03 12:13:16 +08:00
he 4350aa6459 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-03 11:46:23 +08:00
he 897dd2118d 稽查修改 2025-09-03 11:46:22 +08:00
hang f84a9c481a linux断点调试
continuous-integration/drone/push Build is passing Details
2025-09-03 11:30:21 +08:00
hang 3cb0ed4cd5 输出路径
continuous-integration/drone/push Build is passing Details
2025-09-03 11:16:17 +08:00
hang e346bfc527 创建目录测试
continuous-integration/drone/push Build is passing Details
2025-09-03 10:43:37 +08:00
hang 831ae8a591 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is failing Details
2025-09-02 18:08:28 +08:00
hang b359508ab4 修改minio 下载测试 2025-09-02 18:08:25 +08:00
he 7750b1ba12 BM报告
continuous-integration/drone/push Build is passing Details
2025-09-02 17:56:13 +08:00
he f5f4639cc8 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-02 17:09:18 +08:00
he 32e659c26b 重新发布 2025-09-02 17:09:17 +08:00
hang 2f69df7a83 修改绑定
continuous-integration/drone/push Build is passing Details
2025-09-02 16:50:50 +08:00
hang ff0662867e 修改角色默认值,返回用户基本信息
continuous-integration/drone/push Build is passing Details
2025-09-02 16:04:58 +08:00
hang 3ee9703dca Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-02 14:07:12 +08:00
hang 217df5dc2f 删除中心参数 2025-09-02 14:07:09 +08:00
he 7fe61af141 报告
continuous-integration/drone/push Build is passing Details
2025-09-02 13:39:51 +08:00
he a37a77949a 代码提交
continuous-integration/drone/push Build is passing Details
2025-09-02 13:28:31 +08:00
he eb885cc568 修改
continuous-integration/drone/push Build is passing Details
2025-09-02 10:52:15 +08:00
he c78a96eed0 添加适用的标准
continuous-integration/drone/push Build is passing Details
2025-09-01 17:28:16 +08:00
he f8b23604c2 分裂修改
continuous-integration/drone/push Build is passing Details
2025-09-01 17:18:48 +08:00
he 26d60857bf 稽查
continuous-integration/drone/push Build is running Details
2025-09-01 17:16:43 +08:00
he 4c9b3e1a23 代码提交
continuous-integration/drone/push Build is passing Details
2025-09-01 16:58:44 +08:00
he 5526a2dd53 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-01 16:20:17 +08:00
he f69ad1b4e3 稽查修改 2025-09-01 16:20:15 +08:00
hang b869693d63 修改遗漏领取逻辑
continuous-integration/drone/push Build is passing Details
2025-09-01 16:06:42 +08:00
hang 6f8f6000ba 增加影像分享配置
continuous-integration/drone/push Build is passing Details
2025-09-01 15:12:23 +08:00
hang ed5f8e8d9c 自动绑定逻辑bug
continuous-integration/drone/push Build is passing Details
2025-09-01 14:55:35 +08:00
hang 550cdff28f Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-01 14:27:03 +08:00
hang 6e363601a6 GA 非管理员看到的人员列表 2025-09-01 14:27:00 +08:00
he 6a63ffd1f2 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-01 13:32:59 +08:00
he 03c8cdd1d2 稽查修改 2025-09-01 13:32:58 +08:00
hang 99e5b102b7 修改bug
continuous-integration/drone/push Build is running Details
2025-09-01 13:32:24 +08:00
hang b331799b3f Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-01 13:13:07 +08:00
hang 20014e66d0 影像分享功能增加 2025-09-01 13:13:06 +08:00
he 8be56c5a4d Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-09-01 11:10:08 +08:00
he fa3df97dab 修改 2025-09-01 11:10:07 +08:00
hang dfd4cd533b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-09-01 11:09:00 +08:00
hang 0d3d1a7f70 修改提交影像逻辑测试 2025-09-01 11:08:56 +08:00
he c418b7e474 修改
continuous-integration/drone/push Build is passing Details
2025-09-01 10:42:29 +08:00
he ab79eff346 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-09-01 10:41:21 +08:00
he c6e8ec0149 代码修改 2025-09-01 10:41:20 +08:00
hang e143cb0e73 修改绑定bug
continuous-integration/drone/push Build is passing Details
2025-08-29 18:09:59 +08:00
hang 5d1499025b 修改课题组删除操作
continuous-integration/drone/push Build is passing Details
2025-08-29 17:47:11 +08:00
hang 87c22f1033 修改检查删除课题组
continuous-integration/drone/push Build is passing Details
2025-08-29 17:34:27 +08:00
hang be5fc58ef7 修改GA课题组管理员查询下拉框
continuous-integration/drone/push Build is passing Details
2025-08-29 16:37:01 +08:00
hang d769d43d23 修改项目过滤和添加到项目
continuous-integration/drone/push Build is passing Details
2025-08-29 15:59:45 +08:00
hang 9de6a3c813 修改日志记录
continuous-integration/drone/push Build is passing Details
2025-08-29 14:52:24 +08:00
hang e38219a0ee Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 14:30:40 +08:00
hang 874d94cefb 编译错误 2025-08-29 14:30:38 +08:00
he 8e3f7d4ba4 更新修改
continuous-integration/drone/push Build is running Details
2025-08-29 14:29:32 +08:00
he 1d918909f0 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 14:24:15 +08:00
he 13b4c90518 文档修改 2025-08-29 14:24:14 +08:00
hang 2d2f399601 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-08-29 14:21:55 +08:00
hang f49d8d81b1 修改课题组管理员 和普通GA 看到列表的区别 2025-08-29 14:21:53 +08:00
he 450f6c00ce Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 14:06:03 +08:00
he 07d4df81f6 模板代码修改 2025-08-29 14:06:03 +08:00
hang 2b696855cc Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 13:43:57 +08:00
hang 64bf0fb622 GA 获取自己是管理员的课题组列表 2025-08-29 13:43:56 +08:00
he 68fa7ce02e Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 13:38:14 +08:00
he bd8cf9ee42 修改 2025-08-29 13:38:14 +08:00
hang 224382bf62 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-29 11:36:31 +08:00
hang a19ba3c215 处理scp服务 拆分影像 2025-08-29 11:36:27 +08:00
he 5975004858 修改
continuous-integration/drone/push Build is running Details
2025-08-29 11:36:07 +08:00
he baffb0bb35 修改
continuous-integration/drone/push Build is passing Details
2025-08-29 10:51:28 +08:00
he 6ed0ea76da 修改
continuous-integration/drone/push Build is running Details
2025-08-29 10:50:09 +08:00
he 55f864c16c Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-08-29 10:49:19 +08:00
he 59ecaaa5a7 修改关键帧 2025-08-29 10:49:16 +08:00
hang 4945daa0d4 增加默认值
continuous-integration/drone/push Build is passing Details
2025-08-28 17:32:42 +08:00
hang 59339969da 修改课题组管理
continuous-integration/drone/push Build is running Details
2025-08-28 17:29:42 +08:00
hang fdbdda71eb 课题组GA 是否被禁用
continuous-integration/drone/push Build is passing Details
2025-08-28 17:04:45 +08:00
hang b7c85d6b56 用户的课题组必须启用才能看到项目
continuous-integration/drone/push Build is passing Details
2025-08-28 16:38:42 +08:00
hang e3e884393f Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-28 16:25:26 +08:00
hang 70c744498b 修改待阅列表返回信息 2025-08-28 16:25:23 +08:00
he a3f8730aa8 添加 签名之后 不让设置TNMValue
continuous-integration/drone/push Build is passing Details
2025-08-28 16:16:31 +08:00
he d0352590ed 添加 TNMValue
continuous-integration/drone/push Build is running Details
2025-08-28 16:14:09 +08:00
he fd04315f17 添加字段
continuous-integration/drone/push Build is running Details
2025-08-28 15:55:15 +08:00
hang 6482316195 修改出生日期
continuous-integration/drone/push Build is passing Details
2025-08-28 15:18:03 +08:00
hang 525cae7232 修改查询条件
continuous-integration/drone/push Build is passing Details
2025-08-28 15:01:18 +08:00
hang afaba95ff2 影像修改信息展示
continuous-integration/drone/push Build is passing Details
2025-08-28 14:34:24 +08:00
he 5258ae5d4b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-28 14:16:27 +08:00
he 54e30f008c 添加EvaluateProgress 任务评估进度相关字段 2025-08-28 14:16:25 +08:00
hang 9569cdab5f 更新callingAE
continuous-integration/drone/push Build is passing Details
2025-08-28 13:48:07 +08:00
hang e189daf569 增加字段
continuous-integration/drone/push Build is passing Details
2025-08-28 13:17:24 +08:00
hang 9b60114476 返回信息
continuous-integration/drone/push Build is passing Details
2025-08-28 11:34:41 +08:00
hang 97c123677e 课题组修改
continuous-integration/drone/push Build is passing Details
2025-08-28 09:29:06 +08:00
hang a3b57e2a04 项目基本信息返回课题组名字
continuous-integration/drone/push Build is passing Details
2025-08-27 17:20:26 +08:00
hang f80c1ec86e 列表过滤
continuous-integration/drone/push Build is passing Details
2025-08-27 17:10:31 +08:00
hang 32d613b146 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-27 15:59:10 +08:00
hang 649b02d5d3 人员退出,参与项目bug 2025-08-27 15:59:08 +08:00
he e622f601a4 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-27 15:19:50 +08:00
he fce4fd52de 修改 2025-08-27 15:19:49 +08:00
hang ed2a777fd4 修改缓存,删除限制
continuous-integration/drone/push Build is passing Details
2025-08-27 14:21:39 +08:00
hang 4de4e36e73 修改配置文件
continuous-integration/drone/push Build is passing Details
2025-08-27 09:48:33 +08:00
hang 17937783e9 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-27 09:42:11 +08:00
hang d1f79cd06b 修改配置文件,更新库 2025-08-27 09:42:10 +08:00
he 3f075ec367 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-27 09:18:02 +08:00
he 77add17984 添加获取关键序列 2025-08-27 09:18:01 +08:00
hang 06eae02b7a Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-26 17:25:58 +08:00
hang d7b5066683 项目添加和更新 2025-08-26 17:25:55 +08:00
he 046ad55b57 代码迁移
continuous-integration/drone/push Build is passing Details
2025-08-26 15:28:39 +08:00
he 9782c5ee04 获取访视下拉
continuous-integration/drone/push Build is passing Details
2025-08-26 14:23:20 +08:00
he 5f7c4dda97 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-26 14:14:53 +08:00
he 4ad3d30b1d 修改首次异地登录 2025-08-26 14:14:42 +08:00
hang 0f272ad935 遗漏修改
continuous-integration/drone/push Build is running Details
2025-08-26 14:11:39 +08:00
hang 68ac4c80af 修改scp 服务传输语法获取值
continuous-integration/drone/push Build is passing Details
2025-08-26 14:07:13 +08:00
hang 66095bccb1 重新拉取的时候更新检查信息
continuous-integration/drone/push Build is passing Details
2025-08-26 13:32:35 +08:00
hang 1fd2c01612 修改更新用户bug
continuous-integration/drone/push Build is passing Details
2025-08-26 13:06:53 +08:00
hang 98547ef145 修改映射方式
continuous-integration/drone/push Build is passing Details
2025-08-26 11:51:06 +08:00
hang efa9e511c3 预先提交准备测试 删除添加角色的问题
continuous-integration/drone/push Build is passing Details
2025-08-26 11:25:37 +08:00
hang b4e2af4c63 影像汇总页面增加
continuous-integration/drone/push Build is passing Details
2025-08-26 10:43:55 +08:00
hang 25425eab93 模型给默认参数
continuous-integration/drone/push Build is passing Details
2025-08-26 10:11:28 +08:00
hang e7261b1c7e dicom dir 增加字段,修改下载接口
continuous-integration/drone/push Build is passing Details
2025-08-26 10:07:59 +08:00
hang 02f3bfbfdd 默认值问题修改
continuous-integration/drone/push Build is passing Details
2025-08-25 16:01:05 +08:00
hang 9995a1b519 实体模型给默认值
continuous-integration/drone/push Build is passing Details
2025-08-25 15:55:51 +08:00
hang 10b47de079 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-08-25 15:47:21 +08:00
hang ebf0c6b086 增加收藏功能 2025-08-25 15:47:19 +08:00
he 621da36150 添加Lugano 标准相关信息
continuous-integration/drone/push Build is passing Details
2025-08-25 15:41:27 +08:00
he 34f52d8218 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-25 14:41:16 +08:00
he 0c1dcd4610 添加是否双屏字段 2025-08-25 14:41:14 +08:00
hang ebaa2af196 修改c-find 列表
continuous-integration/drone/push Build is passing Details
2025-08-25 13:46:23 +08:00
hang 552509ad9e 修改项目用户
continuous-integration/drone/push Build is passing Details
2025-08-22 13:39:53 +08:00
hang 806f829e08 课题组打标签
continuous-integration/drone/push Build is passing Details
2025-08-22 11:02:13 +08:00
hang 75f0f5e3a5 增加callningAE
continuous-integration/drone/push Build is passing Details
2025-08-21 17:36:57 +08:00
hang 652d90af98 修改GA 过滤
continuous-integration/drone/push Build is passing Details
2025-08-21 16:16:41 +08:00
hang c4d1c652a3 编译错误
continuous-integration/drone/push Build is passing Details
2025-08-21 14:31:30 +08:00
hang 01b61f8fb6 修改判断
continuous-integration/drone/push Build is running Details
2025-08-21 14:30:29 +08:00
hang 7542c20bcc 修改查询
continuous-integration/drone/push Build is passing Details
2025-08-21 13:58:56 +08:00
hang 3a65046c48 修改课题组列表
continuous-integration/drone/push Build is passing Details
2025-08-21 13:42:28 +08:00
hang 659aadbc7f 修改接口
continuous-integration/drone/push Build is passing Details
2025-08-21 11:45:13 +08:00
hang 8b72566b91 修改接口和映射
continuous-integration/drone/push Build is passing Details
2025-08-21 11:08:37 +08:00
hang ce25556a9f 获取用户详情返回数组
continuous-integration/drone/push Build is passing Details
2025-08-21 10:47:40 +08:00
hang 1847e6f76f 修改过滤条件
continuous-integration/drone/push Build is passing Details
2025-08-21 09:56:56 +08:00
hang e6bf9697a5 课题组增加字段
continuous-integration/drone/push Build is passing Details
2025-08-20 15:26:40 +08:00
hang d2eec7676d GA 添加用户,下拉框过滤课题组
continuous-integration/drone/push Build is running Details
2025-08-20 15:25:26 +08:00
hang 7525c14e7d 邮箱校验规则返回
continuous-integration/drone/push Build is passing Details
2025-08-20 14:53:36 +08:00
hang 5644a2acd7 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-20 14:13:10 +08:00
hang d48ffc5051 课题组增加状态 2025-08-20 14:13:07 +08:00
he 48bb5ce47a 修改bug
continuous-integration/drone/push Build is passing Details
2025-08-20 14:04:53 +08:00
he 8693e3169c Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-20 13:53:41 +08:00
he f73529bfc1 查询修改 2025-08-20 13:53:41 +08:00
hang df6b89b3be 切换医院,设置缓存bug 修改
continuous-integration/drone/push Build is running Details
2025-08-20 13:52:40 +08:00
hang 893effcefe Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-20 13:25:23 +08:00
hang 77444e35fa 项目绑定医院,防止演示切换医院 2025-08-20 13:25:21 +08:00
he 53007ccb6a 修改bug
continuous-integration/drone/push Build is passing Details
2025-08-20 11:30:24 +08:00
he b301d51b2d 修改项目下拉筛选
continuous-integration/drone/push Build is passing Details
2025-08-20 11:21:23 +08:00
he b5d259f907 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is running Details
2025-08-20 11:18:11 +08:00
he 721826e346 修改项目下拉查询 2025-08-20 11:18:10 +08:00
hang c479574905 项目列表过滤
continuous-integration/drone/push Build is running Details
2025-08-20 11:16:23 +08:00
hang 291801efe2 修改HIR配置文件
continuous-integration/drone/push Build is passing Details
2025-08-20 11:10:58 +08:00
hang 13e907f876 邮件修改
continuous-integration/drone/push Build is passing Details
2025-08-20 10:52:34 +08:00
hang bee3084bbf 修改系统邮件配置
continuous-integration/drone/push Build is passing Details
2025-08-19 17:40:06 +08:00
hang 9300f5756d 精简日志展示
continuous-integration/drone/push Build is passing Details
2025-08-19 16:20:49 +08:00
hang 7b3cac1f63 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-19 16:08:17 +08:00
hang 0acdcbae0e 校验码接口修改 2025-08-19 16:08:16 +08:00
he 2c3483fa4e 修改
continuous-integration/drone/push Build is passing Details
2025-08-19 15:37:14 +08:00
hang 1b6d1dd4cb Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-19 15:07:34 +08:00
hang a9b907b717 修改签名接口 2025-08-19 15:07:33 +08:00
he ce5ca145ed Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-19 14:46:38 +08:00
he 15c9a370ee 添加服务注册 2025-08-19 14:46:37 +08:00
hang 006afc56d5 修改列表过滤
continuous-integration/drone/push Build is passing Details
2025-08-19 14:29:54 +08:00
hang 29da1ab464 修改用户,项目添加接口增加参数
continuous-integration/drone/push Build is passing Details
2025-08-19 09:57:12 +08:00
hang a7db0c2887 增加项目课题组,缓存bug修改
continuous-integration/drone/push Build is passing Details
2025-08-18 18:04:28 +08:00
hang f409c6468e Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-18 15:34:30 +08:00
hang ade2bdf181 项目运维人员修改 2025-08-18 15:34:28 +08:00
he 9ecbfb37aa Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-18 15:02:32 +08:00
he c44c861086 中山医院模版 2025-08-18 15:02:31 +08:00
hang a2deb93b6c x
continuous-integration/drone/push Build is passing Details
2025-08-18 14:24:34 +08:00
hang 5527f51880 验证通过,返回账户信息Id
continuous-integration/drone/push Build is running Details
2025-08-18 14:23:25 +08:00
hang b8d9cf1630 课题组修改管理员
continuous-integration/drone/push Build is passing Details
2025-08-18 14:03:47 +08:00
hang 73f1f2938f HIR 课题组列表增加
continuous-integration/drone/push Build is passing Details
2025-08-18 13:42:04 +08:00
hang 5ea6d221e3 修改账户触发日志
continuous-integration/drone/push Build is passing Details
2025-08-18 11:44:52 +08:00
hang 30edf87bc0 修改登录认证授权
continuous-integration/drone/push Build is passing Details
2025-08-18 10:41:31 +08:00
he 93a6bee01b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-18 09:26:52 +08:00
he 17a7634a37 修改swagger 不显示某些方法 2025-08-18 09:26:50 +08:00
hang 4048c28628 升级efcore 测试内存
continuous-integration/drone/push Build is passing Details
2025-08-15 21:08:47 +08:00
hang 816d81b555 临时提交,解决swagger 大内存问题
continuous-integration/drone/push Build is passing Details
2025-08-15 18:49:27 +08:00
hang dedb1c152f 修改映射
continuous-integration/drone/push Build is passing Details
2025-08-15 14:44:17 +08:00
hang 083090ca05 swagger bug 核对
continuous-integration/drone/push Build is passing Details
2025-08-15 14:35:03 +08:00
hang 31c86c5d4a 升级swagger 版本测试
continuous-integration/drone/push Build is passing Details
2025-08-15 13:22:04 +08:00
hang bf785156f4 IRC swagger 迁移
continuous-integration/drone/push Build is running Details
2025-08-15 11:26:24 +08:00
hang 15af716651 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-15 10:55:26 +08:00
hang a2bd2857b2 映射修改 2025-08-15 10:55:24 +08:00
he d0351ef405 同步表结构
continuous-integration/drone/push Build is passing Details
2025-08-15 09:58:56 +08:00
hang 552a77ecd4 HIR 用户 文档调整第二次变更
continuous-integration/drone/push Build is passing Details
2025-08-15 09:50:39 +08:00
hang 9f10af6654 HIR 用户调整,初步修改
continuous-integration/drone/push Build is passing Details
2025-08-14 16:11:00 +08:00
hang 55c87d673c 测试结束
continuous-integration/drone/push Build is passing Details
2025-08-12 17:48:07 +08:00
hang 2607a05104 再次测试
continuous-integration/drone/push Build is passing Details
2025-08-12 17:13:09 +08:00
hang 4f2dc949a5 还原初始拉取
continuous-integration/drone/push Build is passing Details
2025-08-12 17:02:26 +08:00
hang 3695c5d596 继续测试
continuous-integration/drone/push Build is passing Details
2025-08-12 16:33:41 +08:00
hang 91cf1ab48c ?pacs 问题
continuous-integration/drone/push Build is passing Details
2025-08-12 16:27:35 +08:00
hang 2b2c5e3d77 还原,使用tag传输不行
continuous-integration/drone/push Build is passing Details
2025-08-12 16:13:09 +08:00
hang 94c4a81974 使用公用tag 传递信息
continuous-integration/drone/push Build is passing Details
2025-08-12 16:06:01 +08:00
hang b5956ef6d2 cmove 增加私有tag 测试
continuous-integration/drone/push Build is passing Details
2025-08-12 15:47:44 +08:00
hang 3861e7642a cmove-测试
continuous-integration/drone/push Build is passing Details
2025-08-12 15:33:19 +08:00
he 1bfe23f9ec Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-12 15:17:47 +08:00
he 9f0647e156 修复bug 2025-08-12 15:17:46 +08:00
hang 7f6222a0bc Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-08-12 15:03:41 +08:00
hang 39c07ecc4f 测试课题组信息传输 2025-08-12 15:03:39 +08:00
he 28c9b72e35 bug 修复
continuous-integration/drone/push Build is passing Details
2025-08-12 09:25:37 +08:00
hang 2778ecb74a 修改dicom 取tag bug2
continuous-integration/drone/push Build is passing Details
2025-07-25 10:36:22 +08:00
hang 40cbd73226 修改dicom 取tag bug
continuous-integration/drone/push Build is running Details
2025-07-25 10:35:54 +08:00
hang 7b456c9008 pacs server 使用c-find 其他的c-echo
continuous-integration/drone/push Build is passing Details
2025-07-17 14:34:04 +08:00
hang 011a75714e Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-07-17 14:20:48 +08:00
hang 38f408d1de 修改dicomAE 测试使用c-find,同时在c-find前不进行测试 2025-07-17 14:20:47 +08:00
he 006d1bd167 Revert "稽查修改"
continuous-integration/drone/push Build is passing Details
This reverts commit 83e64fd4aa.
2025-07-17 10:20:33 +08:00
he 83e64fd4aa 稽查修改
continuous-integration/drone/push Build is passing Details
2025-07-17 09:56:35 +08:00
hang 7c7ce6632a 获取授权码接口调整
continuous-integration/drone/push Build is passing Details
2025-05-29 14:48:57 +08:00
hang 787bc250c1 X
continuous-integration/drone/push Build is passing Details
2025-05-27 17:07:26 +08:00
hang 3b5ac96a98 导出bug
continuous-integration/drone/push Build is passing Details
2025-05-14 15:59:04 +08:00
hang 3d4dc0c1f4 HIR 导出bug
continuous-integration/drone/push Build is passing Details
2025-05-14 15:50:42 +08:00
hang 2990420361 修改缓存bug
continuous-integration/drone/push Build is passing Details
2025-05-13 14:28:27 +08:00
hang 2521147579 增加医院通用配置
continuous-integration/drone/push Build is passing Details
2025-05-13 10:19:17 +08:00
hang 4f860cca07 恢复老接口
continuous-integration/drone/push Build is passing Details
2025-05-09 09:49:17 +08:00
hang bea324aa56 增加访视名称查询
continuous-integration/drone/push Build is passing Details
2025-04-30 14:01:08 +08:00
hang c78cbbb737 重阅修改测量数据
continuous-integration/drone/push Build is passing Details
2025-04-28 18:00:33 +08:00
he e197f6c2bb 修改
continuous-integration/drone/push Build is passing Details
2025-04-27 17:51:36 +08:00
he c7d8e38cd3 模板修改
continuous-integration/drone/push Build is passing Details
2025-04-27 15:36:30 +08:00
he 8a241754ca Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-04-25 14:47:49 +08:00
he b3e77ec422 模板修改 2025-04-25 14:47:48 +08:00
hang daf593f76a 邮箱修改
continuous-integration/drone/push Build is passing Details
2025-04-24 11:05:21 +08:00
hang 5c4388a2e7 修改初始化逻辑
continuous-integration/drone/push Build is passing Details
2025-04-24 10:40:58 +08:00
hang 0da73ce1db 单独修改单位
continuous-integration/drone/push Build is passing Details
2025-04-24 09:58:53 +08:00
hang 1d2ef4561f 修改账号信息
continuous-integration/drone/push Build is passing Details
2025-04-24 09:42:44 +08:00
hang dbf75535c5 统一修改用户信息
continuous-integration/drone/push Build is passing Details
2025-04-24 09:35:32 +08:00
he aa34c96a39 模板修改
continuous-integration/drone/push Build is passing Details
2025-04-23 11:29:28 +08:00
he e6b6a24b3b 添加英文模板
continuous-integration/drone/push Build is passing Details
2025-04-22 17:49:09 +08:00
hang 0b958f21a5 修改切换角色 统一密码,checkCode 首次登录标志
continuous-integration/drone/push Build is passing Details
2025-04-21 13:37:56 +08:00
hang e6310a4533 过滤OA
continuous-integration/drone/push Build is passing Details
2025-04-18 17:46:51 +08:00
hang 49c3a0d494 修改国际化
continuous-integration/drone/push Build is passing Details
2025-04-18 13:06:59 +08:00
hang 213cb69332 修改切换医院bug
continuous-integration/drone/push Build is passing Details
2025-04-18 10:03:35 +08:00
hang e43dce220c 修改激活逻辑
continuous-integration/drone/push Build is passing Details
2025-04-18 09:54:44 +08:00
hang 52dc6e05d4 修改名字
continuous-integration/drone/push Build is passing Details
2025-04-17 10:10:39 +08:00
hang 31e76a2e97 HIR 修改配置文件
continuous-integration/drone/push Build is running Details
2025-04-17 10:08:01 +08:00
hang 19d9ca44fb 修改映射配置,字段
continuous-integration/drone/push Build is passing Details
2025-04-14 15:33:55 +08:00
hang c8b0681dfa Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-04-03 16:21:01 +08:00
hang eed17feae0 上传自签署https minio 2025-04-03 16:20:59 +08:00
he c0478ef96e 修改
continuous-integration/drone/push Build is running Details
2025-04-03 16:19:32 +08:00
he 4713d2a09b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-04-03 16:05:01 +08:00
he ea72e6cf65 修改 2025-04-03 16:05:01 +08:00
hang 9f5aee9258 修改hir minio 上传测试
continuous-integration/drone/push Build is passing Details
2025-04-03 15:57:06 +08:00
hang e56d1b9573 换一种方式忽略证书
continuous-integration/drone/push Build is passing Details
2025-04-03 11:14:06 +08:00
hang 6d5a7bd3a2 修改验证https 证书测试
continuous-integration/drone/push Build is passing Details
2025-04-03 11:03:45 +08:00
he a73ef7108b 没用的文件删除
continuous-integration/drone/push Build is passing Details
2025-04-03 10:35:45 +08:00
he 507500f051 先不删除文件
continuous-integration/drone/push Build is passing Details
2025-04-03 10:12:47 +08:00
he 913084cc8d 修改
continuous-integration/drone/push Build is passing Details
2025-04-03 09:57:37 +08:00
he 5874223866 修改
continuous-integration/drone/push Build is passing Details
2025-04-03 09:55:04 +08:00
he d5609560e2 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-04-03 09:20:23 +08:00
he a5b4ab6531 修改 2025-04-03 09:20:22 +08:00
hang a91705b35d tj cmove 检查
continuous-integration/drone/push Build is passing Details
2025-04-02 10:01:33 +08:00
hang 65369c73bf 测试发布
continuous-integration/drone/push Build is passing Details
2025-04-01 17:32:37 +08:00
hang eb9bb75825 修改创建的临时token
continuous-integration/drone/push Build is passing Details
2025-04-01 17:04:50 +08:00
hang 69216ae75d HIR 同济对接接口完成
continuous-integration/drone/push Build is passing Details
2025-04-01 16:06:53 +08:00
hang 309ea7b1d1 HIR 对接自动生成账号
continuous-integration/drone/push Build is passing Details
2025-04-01 15:01:39 +08:00
hang 5beacacc0f 医院修改,导致配置修改
continuous-integration/drone/push Build is passing Details
2025-03-28 14:38:23 +08:00
hang 008a909f5b 增加统计配置文件
continuous-integration/drone/push Build is passing Details
2025-03-28 14:17:45 +08:00
hang bdfc65c07b 设置请求方式httpget
continuous-integration/drone/push Build is passing Details
2025-03-28 10:08:52 +08:00
hang 5ee7a70c65 修改账号排序
continuous-integration/drone/push Build is passing Details
2025-03-28 10:03:54 +08:00
hang c9590829b2 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-28 09:54:59 +08:00
hang 80805bde06 增加默认字段 2025-03-28 09:54:57 +08:00
he 20718bca5d Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-28 09:52:31 +08:00
he 3d58e91644 修改模板 2025-03-28 09:52:31 +08:00
hang ade2a25fc4 获取tj 医院tokenInfo
continuous-integration/drone/push Build is passing Details
2025-03-28 09:38:12 +08:00
hang dcddf88a66 getUser 返回账户信息
continuous-integration/drone/push Build is passing Details
2025-03-27 17:31:01 +08:00
hang 89574e05bc Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-27 16:30:50 +08:00
hang 95fe14fece HIR 增加下拉框切换账户 2025-03-27 16:30:43 +08:00
he cfaf14ed65 模板修改
continuous-integration/drone/push Build is passing Details
2025-03-27 16:25:14 +08:00
he a50f82c42a Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-27 15:54:51 +08:00
he 1c0e1e01ce 报告修改医院名称 2025-03-27 15:54:50 +08:00
hang 5ec3fc3d13 修改创建账户默认密码
continuous-integration/drone/push Build is passing Details
2025-03-27 14:48:04 +08:00
he 9bd080b566 修改模板
continuous-integration/drone/push Build is passing Details
2025-03-26 15:52:06 +08:00
he f7cdb5b858 修改
continuous-integration/drone/push Build is passing Details
2025-03-26 14:15:46 +08:00
he 00c3ad8f9e 修改模板
continuous-integration/drone/push Build is passing Details
2025-03-25 16:32:54 +08:00
he d4b3038f6d Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 15:45:16 +08:00
he dde513a976 修改检查类型 2025-03-25 15:45:15 +08:00
hang 8378e8f2d6 多模态过滤
continuous-integration/drone/push Build is passing Details
2025-03-25 15:30:15 +08:00
hang 374f024f85 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is failing Details
2025-03-25 14:56:22 +08:00
hang 32aadceaac 增加多模态 2025-03-25 14:56:19 +08:00
he 285e742136 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 14:34:07 +08:00
he 704a876cf0 修改 2025-03-25 14:34:06 +08:00
hang 7184ea9565 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 14:09:07 +08:00
hang 6da50126e1 增加国际化 2025-03-25 14:09:06 +08:00
he 965c8a56c9 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 13:11:25 +08:00
he 0611c1d9fe 代码修改 2025-03-25 13:11:22 +08:00
hang 642acc9cba Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 11:29:39 +08:00
hang b87fb98c6c 修改pacs 查询 2025-03-25 11:29:37 +08:00
he d0d249655b Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-25 09:37:00 +08:00
he a847bb1785 模版修改 2025-03-25 09:36:58 +08:00
hang 445ee00840 修改时间查询
continuous-integration/drone/push Build is passing Details
2025-03-25 09:25:28 +08:00
he ecd33d969b 修改
continuous-integration/drone/push Build is passing Details
2025-03-24 17:10:59 +08:00
he 470420410e 代码修改
continuous-integration/drone/push Build is passing Details
2025-03-24 16:39:07 +08:00
he 2952b9e59f 添加字段
continuous-integration/drone/push Build is passing Details
2025-03-24 16:18:19 +08:00
he 7e8995a7b2 生成肿瘤报告
continuous-integration/drone/push Build is passing Details
2025-03-24 16:15:21 +08:00
he e7046173f8 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2025-03-24 09:45:15 +08:00
he f1a39e3b9d 修改 2025-03-24 09:45:12 +08:00
hang 2838f232f3 修改权限
continuous-integration/drone/push Build is passing Details
2025-03-21 14:54:34 +08:00
hang 9ac4b262f3 增加id
continuous-integration/drone/push Build is passing Details
2025-03-21 14:08:39 +08:00
hang 582b8b3c07 更新数据库
continuous-integration/drone/push Build is passing Details
2025-03-21 10:19:04 +08:00
hang 91b20e07f2 HIR 管理端医院修改
continuous-integration/drone/push Build is passing Details
2025-03-21 10:15:31 +08:00
hang 5a99f476f9 增加拉取查询
continuous-integration/drone/push Build is passing Details
2025-03-20 15:04:45 +08:00
hang e06b47c8b3 查询某个项目下患者最新的检查列表初步修改
continuous-integration/drone/push Build is passing Details
2025-03-18 13:52:57 +08:00
hang 613cf6441b 修改推送监控记录
continuous-integration/drone/push Build is passing Details
2025-03-17 17:51:43 +08:00
hang 57dd964db2 minio 区域配置,导致上传失败问题
continuous-integration/drone/push Build is passing Details
2025-02-17 14:07:28 +08:00
hang 42dd5d384f 测试
continuous-integration/drone/push Build is passing Details
2025-02-07 19:55:42 +08:00
hang f2138623f4 修改日志记录文本名
continuous-integration/drone/push Build is passing Details
2025-02-07 17:56:32 +08:00
hang c69b2569ce 增加日志记录发送Cmove
continuous-integration/drone/push Build is passing Details
2025-02-07 17:21:29 +08:00
hang 6f8b88422b 修改配置文件
continuous-integration/drone/push Build is passing Details
2025-02-07 16:58:26 +08:00
hang 4c4d19b0d6 修改测试
continuous-integration/drone/push Build is passing Details
2025-02-07 16:17:50 +08:00
hang 91e0f0b787 每个检查只取instance的最新的一条
continuous-integration/drone/push Build is passing Details
2025-02-07 13:26:24 +08:00
hang c7f64ea0fe 修改查询位置
continuous-integration/drone/push Build is passing Details
2025-02-07 12:27:53 +08:00
hang fdb0b74296 修改Cmove 推送命令
continuous-integration/drone/push Build is passing Details
2025-02-07 11:25:08 +08:00
hang 0d7a04f1e8 清理状态再次测试
continuous-integration/drone/push Build is passing Details
2025-01-07 14:01:34 +08:00
hang 0a72c15dfd xxx
continuous-integration/drone/push Build is passing Details
2025-01-07 13:46:39 +08:00
hang 282c0b40c2 HIR 申请重阅,如果后续任务已经拷贝了表单,申请当前任务后,后续拷贝的表单删除
continuous-integration/drone/push Build is passing Details
2025-01-07 13:40:24 +08:00
hang 5783f5836a 数据库配置
continuous-integration/drone/push Build is passing Details
2025-01-06 14:35:54 +08:00
hang aff1f5b599 维护数据根据发送端加锁
continuous-integration/drone/push Build is passing Details
2024-12-30 09:01:12 +08:00
hang b12079f8d9 修改数据库连接
continuous-integration/drone/push Build is passing Details
2024-12-27 17:38:11 +08:00
hang 99de20ef76 修改AOA 不能看admin
continuous-integration/drone/push Build is passing Details
2024-12-27 17:19:57 +08:00
hang c187b5fb94 修改参数位置
continuous-integration/drone/push Build is passing Details
2024-12-20 13:55:02 +08:00
hang d852de4a5b 修改稽查报错
continuous-integration/drone/push Build is passing Details
2024-12-20 12:50:41 +08:00
hang d10020d944 修改关联关系
continuous-integration/drone/push Build is passing Details
2024-12-20 11:13:29 +08:00
hang f7c17546da 多模态修改
continuous-integration/drone/push Build is passing Details
2024-12-20 11:05:33 +08:00
hang c267bb34b4 支持多模态查询
continuous-integration/drone/push Build is passing Details
2024-12-20 10:31:59 +08:00
hang 98b0b36e3b 修改AE 测试
continuous-integration/drone/push Build is passing Details
2024-12-19 16:00:50 +08:00
hang 468224cae9 修改c-find 测试pacs在线与否
continuous-integration/drone/push Build is passing Details
2024-12-19 15:00:32 +08:00
hang 6b385b619a 修改国际化
continuous-integration/drone/push Build is passing Details
2024-12-19 14:42:56 +08:00
hang 88669ccbff 修改验证 和测试
continuous-integration/drone/push Build is passing Details
2024-12-19 14:30:14 +08:00
hang 5f338de0cd 修改时间解析
continuous-integration/drone/push Build is passing Details
2024-12-19 12:29:50 +08:00
hang c266c68be8 修改时间查询
continuous-integration/drone/push Build is passing Details
2024-12-19 10:36:21 +08:00
hang 364b84fd1c 修改时间
continuous-integration/drone/push Build is passing Details
2024-12-19 10:03:56 +08:00
hang 982bd80898 修改modality 查询
continuous-integration/drone/push Build is passing Details
2024-12-19 09:48:45 +08:00
hang 0050ae8d0a 增加patientName
continuous-integration/drone/push Build is passing Details
2024-12-18 13:10:43 +08:00
hang 8d11115fab 修改提示
continuous-integration/drone/push Build is passing Details
2024-12-18 12:55:06 +08:00
hang 355ca22134 增加客户端pacs ae 配置
continuous-integration/drone/push Build is passing Details
2024-12-18 11:30:19 +08:00
hang d568964c64 修改 HIR 验证
continuous-integration/drone/push Build is passing Details
2024-12-17 16:37:38 +08:00
hang 81443e5e36 列表展示
continuous-integration/drone/push Build is passing Details
2024-12-17 14:03:28 +08:00
hang 1c4d513f5b 修改查询
continuous-integration/drone/push Build is passing Details
2024-12-17 13:40:00 +08:00
hang d0a3ce9a09 后台任务Cmove 影像
continuous-integration/drone/push Build is passing Details
2024-12-16 13:44:54 +08:00
hang 0a368c0607 修改增加接口
continuous-integration/drone/push Build is passing Details
2024-12-13 16:52:15 +08:00
hang 1104c1481e 修改解析
continuous-integration/drone/push Build is passing Details
2024-12-13 16:00:25 +08:00
hang 7318dd4812 修改搜索条件
continuous-integration/drone/push Build is passing Details
2024-12-13 13:24:18 +08:00
hang 1ee30d047d 修改Patient 请求
continuous-integration/drone/push Build is passing Details
2024-12-12 17:48:33 +08:00
hang 39e7218b52 拉取影像
continuous-integration/drone/push Build is passing Details
2024-12-12 16:28:43 +08:00
hang 959fa1c40c 修改HIR 提示
continuous-integration/drone/push Build is passing Details
2024-12-02 13:33:55 +08:00
hang fb074048df 修改用户过滤
continuous-integration/drone/push Build is passing Details
2024-11-29 17:44:45 +08:00
hang 0b20c42513 修改加密解密
continuous-integration/drone/push Build is passing Details
2024-11-29 15:19:43 +08:00
hang 7c0e53db73 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2024-11-28 16:19:10 +08:00
hang d77a6ebda0 加密解密的修改 2024-11-28 16:19:07 +08:00
he 42f7bf9c97 修改模板
continuous-integration/drone/push Build is passing Details
2024-11-28 14:55:42 +08:00
hang b9d9552ae8 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is passing Details
2024-11-28 13:20:04 +08:00
hang ba81a842b7 修改用户机构名字 2024-11-28 13:20:03 +08:00
hang 28b3f16ef0 修改用户机构名字
continuous-integration/drone/push Build is passing Details
2024-11-28 13:17:31 +08:00
hang 37bf4905bb 修改IR查询条件
continuous-integration/drone/push Build is passing Details
2024-11-28 10:57:48 +08:00
hang 0ab9cebe45 修改IR 阅片查询
continuous-integration/drone/push Build is passing Details
2024-11-28 10:49:45 +08:00
hang a8c9587572 修改环境配置
continuous-integration/drone/push Build is passing Details
2024-11-28 10:30:16 +08:00
hang 48380aa7ea 修改HIR 配置文件
continuous-integration/drone/push Build is passing Details
2024-11-27 14:18:23 +08:00
hang b1831bfba0 修改token获取
continuous-integration/drone/push Build is passing Details
2024-11-27 13:41:35 +08:00
hang b9f866807e 修改模板调整
continuous-integration/drone/push Build is passing Details
2024-11-25 17:12:32 +08:00
hang 8896450fcc 修改导表 判断
continuous-integration/drone/push Build is passing Details
2024-11-25 16:21:20 +08:00
hang 2dc0cc3525 修改导表bug 初步测试
continuous-integration/drone/push Build is passing Details
2024-11-25 15:08:12 +08:00
hang a3f635894b 修改导表,日志记录
continuous-integration/drone/push Build is passing Details
2024-11-25 11:47:52 +08:00
hang 542ead68a7 稽查修改
continuous-integration/drone/push Build is passing Details
2024-11-25 09:30:30 +08:00
hang 7c25809ad5 稽查修改数据
continuous-integration/drone/push Build is passing Details
2024-11-22 17:10:09 +08:00
hang 1f14adec2a 增加邮箱查询
continuous-integration/drone/push Build is passing Details
2024-11-22 16:58:28 +08:00
hang 8173e6a8f2 修改下载返回间隔
continuous-integration/drone/push Build is failing Details
2024-11-22 16:25:00 +08:00
he 0baf4700f1 发布
continuous-integration/drone/push Build is failing Details
2024-11-22 15:22:05 +08:00
he e3f1fe5569 doctorID 匹配修改
continuous-integration/drone/push Build is failing Details
2024-11-22 15:14:43 +08:00
he 9aa5c27f60 Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8
continuous-integration/drone/push Build is failing Details
2024-11-22 14:53:30 +08:00
he a1479420c8 去掉doctorid匹配 2024-11-22 14:53:29 +08:00
hang 0f368f0a5e 修改发布
continuous-integration/drone/push Build is passing Details
2024-11-21 11:22:54 +08:00
hang 5d0c6417a4 修改Patient 返回影响列表
continuous-integration/drone/push Build is passing Details
2024-11-21 09:35:01 +08:00
hang 12d8944ca7 前端用新的方式对接修改
continuous-integration/drone/push Build is passing Details
2024-11-21 09:24:22 +08:00
hang 521a4ad3f0 HIR_UAT 修改
continuous-integration/drone/push Build is passing Details
2024-11-20 16:25:10 +08:00
hang 040777ec87 修改查询参数
continuous-integration/drone/push Build is passing Details
2024-11-14 17:22:51 +08:00
hang b68d3a5d99 移除HIR后端下载字段
continuous-integration/drone/push Build is passing Details
2024-11-14 17:00:11 +08:00
hang 0af3c5ab8b 影响下载修改
continuous-integration/drone/push Build is passing Details
2024-11-14 16:41:30 +08:00
hang 6ca1e81b6a 修改发布脚本
continuous-integration/drone/push Build is passing Details
2024-11-14 16:00:43 +08:00
hang 068b3fa8d7 修改HIR 获取检查报错
continuous-integration/drone/push Build is failing Details
2024-11-14 15:57:44 +08:00
hang 976b89e970 HIR 修改下载代码 2024-11-14 14:48:08 +08:00
he 47e85ebbdf Merge branch 'Test_HIR_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_HIR_Net8 2024-11-14 10:53:25 +08:00
he 44f33fb7f0 阅片报告功能 2024-11-14 10:53:23 +08:00
hang 2c5ba280e9 调整申请重阅调整 2024-11-14 10:12:32 +08:00
hang 5250cd524a 阅片接口返回之前的参数对接 2024-11-13 18:30:39 +08:00
hang 787dd9aa5f 修改标准默认配置,修改待阅列表数据 2024-11-13 15:39:16 +08:00
hang e059dcb2b2 HIR 稽查 授权,配置测试提交 2024-11-13 11:14:02 +08:00
hang 75bf9b394b 迁移HIR 初步提交 2024-11-12 16:50:28 +08:00
hang c158d53a39 HIR 数据库初始化准备 2024-11-12 09:40:13 +08:00
hang 8e6125796b IRC 迁移HIR 功能初步修改 2024-11-11 23:50:23 +08:00
718 changed files with 761204 additions and 1503620 deletions

View File

@ -1,37 +0,0 @@
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)));
}
}
}
}

View File

@ -1,61 +0,0 @@
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;//标记当前异常已经被处理过了
}
}
}

View File

@ -1,120 +0,0 @@
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(I18n.T("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;
}
}
}

View File

@ -1,57 +0,0 @@
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();
}
}
}

View File

@ -1,64 +0,0 @@
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);
});
}
}
}

View File

@ -1,59 +0,0 @@

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;
});
}
}
}

View File

@ -1,36 +0,0 @@
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;
}
}
}

View File

@ -1,42 +0,0 @@
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);
}
}
}
}

View File

@ -1,45 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
<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.416.8" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
<PackageReference Include="fo-dicom" Version="5.2.1" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Minio" Version="6.0.4" />
<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.2" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.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="8.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Helper\" />
</ItemGroup>
</Project>

View File

@ -1,186 +0,0 @@
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 主机配置
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;
});
builder.Services.AddFellowOakDicom().AddTranscoderManager<NativeTranscoderManager>()
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
.AddImageManager<ImageSharpImageManager>();
#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.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
DicomSetupBuilder.UseServiceProvider(app.Services);
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();

View File

@ -1,31 +0,0 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:11224",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5127",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -1,111 +0,0 @@
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
}

View File

@ -1,376 +0,0 @@
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, IServiceProvider injectServiceProvider)
: base(stream, fallbackEncoding, log, dependencies)
{
_serviceProvider = injectServiceProvider.CreateScope().ServiceProvider;
}
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.FirstOrDefaultAsync(t => t.Id == 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));
}
}
}

View File

@ -1,356 +0,0 @@
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.FirstOrDefaultAsync(t=>t.Id== studyId);
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var findInstance = await _instanceRepository.FirstOrDefaultAsync(t => t.Id == 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);
}
}
}

View File

@ -1,11 +0,0 @@
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);
}
}

View File

@ -1,770 +0,0 @@
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("未定义的存储介质类型");
}
}
}

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,42 @@
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class SafeBussinessHelper
{
public static async Task<bool> RunAsync(Func<Task> func, [CallerMemberName] string caller = "", string errorMsgTitle = "")
{
try
{
await func();
return true;
}
catch (Exception ex)
{
Log.Logger.Error($"【{errorMsgTitle}失败 - {caller}】: {ex.Message}");
return false;
}
}
public static async Task<(bool Success, T? Result)> RunAsync<T>(Func<Task<T>> func, [CallerMemberName] string caller = "", string errorMsgTitle = "")
{
try
{
var result = await func();
return (true, result);
}
catch (Exception ex)
{
Log.Logger.Error($"【{errorMsgTitle}失败 - {caller}】: {ex.Message}");
return (false, default);
}
}
}
}

View File

@ -27,8 +27,7 @@ namespace IRaCIS.Core.SCP
//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.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
options.UseLoggerFactory(logFactory);

View File

@ -7,28 +7,29 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.6" />
<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.416.8" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
<PackageReference Include="AWSSDK.S3" Version="4.0.6.9" />
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.2" />
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
<PackageReference Include="fo-dicom" Version="5.2.4" />
<PackageReference Include="fo-dicom" Version="5.2.2" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.4" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.4" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Minio" Version="6.0.3" />
<PackageReference Include="Minio" Version="7.0.0" />
<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.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.4.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.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="8.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
</ItemGroup>
<ItemGroup>
@ -36,4 +37,12 @@
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.Prod_HIR_SCP.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
</Project>

View File

@ -14,6 +14,7 @@ using MassTransit;
using MassTransit.NewIdProviders;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using Panda.DynamicWebApi;
using Serilog;
using Serilog.Events;
@ -82,7 +83,6 @@ builder.Services.AddControllers(options =>
.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"));
@ -126,14 +126,14 @@ builder.Services.Configure<ForwardedHeadersOptions>(options =>
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
builder.Services.AddFellowOakDicom().AddTranscoderManager<NativeTranscoderManager>()
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
.AddImageManager<ImageSharpImageManager>();
//Dicom影像渲染图片 跨平台
//builder.Services.AddDicomSetup();
////Dicom影像渲染图片 跨平台
////builder.Services.AddDicomSetup();
//new DicomSetupBuilder()
// .RegisterServices(s =>
// s.AddFellowOakDicom()
@ -141,10 +141,10 @@ builder.Services.AddFellowOakDicom().AddTranscoderManager<NativeTranscoderManage
// //.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
// .AddImageManager<ImageSharpImageManager>())
// .SkipValidation()
// .Build();
#endregion
// Add services to the container.
@ -219,9 +219,15 @@ else
DicomSetupBuilder.UseServiceProvider(app.Services);
// Program.cs
IRCAppConfig.Configuration = builder.Configuration;
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();

View File

@ -1,34 +1,34 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"Test_IRC_SCP": {
"Test_HIR_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC_SCP"
"ASPNETCORE_ENVIRONMENT": "Test_HIR_SCP"
}
},
"Uat_IRC_SCP": {
"Uat_HIR_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Uat_IRC_SCP"
"ASPNETCORE_ENVIRONMENT": "Uat_HIR_SCP"
}
},
"US_Prod_IRC_SCP": {
"Prod_HIR_SCP": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:6200",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "US_Prod_SCP"
"ASPNETCORE_ENVIRONMENT": "Prod_HIR_SCP"
}
}
}

View File

@ -22,23 +22,50 @@ using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Newtonsoft.Json;
using FellowOakDicom.Imaging.Codec;
using FellowOakDicom.IO.Buffer;
using System.Diagnostics.CodeAnalysis;
using FellowOakDicom.Network.Client;
using MassTransit.Futures.Contracts;
using Microsoft.Identity.Client;
namespace IRaCIS.Core.SCP.Service
{
public class DicomSCPServiceOption
{
public bool IsSupportThirdService { get; set; }
public bool IsForwardImageMultiThread { get; set; }
public List<string> CalledAEList { get; set; }
public string ServerPort { get; set; }
}
public class ThirdDestinationAE
{
public int Port { get; set; }
public string Name { get; set; }
public string IP { get; set; }
}
public static class IRCAppConfig
{
public static IConfiguration Configuration { get; set; }
}
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
{
//private IServiceProvider _injectServiceProvider { get; set; }
private IServiceProvider _serviceProvider { get; set; }
private List<Guid> _SCPStudyIdList => _ImageUploadList.Where(t => t.SCPStudyId != Guid.Empty).Select(t => t.SCPStudyId).ToList();
@ -47,9 +74,18 @@ namespace IRaCIS.Core.SCP.Service
private SCPImageUpload _upload { get; set; }
private Guid _trialId { get; set; }
private DicomSCPServiceOption DicomSCPServiceConfig { get; set; }
public HospitalGroup CurrentHospitalGroup { get; set; }
private List<Guid> HospitalGroupIdList { get; set; }
private bool _releasedNormally = false;
private bool _isCurrentThirdForward = false;
private List<ThirdDestinationAE> ThirdDestinationAEList { get; set; }
private Guid _trialSiteId { get; set; }
@ -62,23 +98,39 @@ namespace IRaCIS.Core.SCP.Service
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
// Lossless
DicomTransferSyntax.JPEGLSLossless,
DicomTransferSyntax.JPEG2000Lossless,
DicomTransferSyntax.JPEGProcess14SV1,
DicomTransferSyntax.JPEGProcess14,
DicomTransferSyntax.RLELossless,
// 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
DicomTransferSyntax.JPEGLSNearLossless,
DicomTransferSyntax.JPEG2000Lossy,
DicomTransferSyntax.JPEGProcess1,
DicomTransferSyntax.JPEGProcess2_4,
// 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
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
// 定义一个静态信号量,控制同时最多 N 个转发线程
private static SemaphoreSlim _forwardLimiter;
// ✅ 静态构造函数(只执行一次,全局初始化)
static CStoreSCPService()
{
// 默认单线程
var maxThreads = IRCAppConfig.Configuration.GetValue<int>("DicomSCPServiceConfig:MultiThreadCount", 1);
_forwardLimiter = new SemaphoreSlim(maxThreads);
Log.Logger.Information($"初始化 DICOM 转发线程限制为: {maxThreads}");
}
public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies, IServiceProvider injectServiceProvider)
: base(stream, fallbackEncoding, log, dependencies)
@ -92,53 +144,42 @@ namespace IRaCIS.Core.SCP.Service
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 option = _serviceProvider.GetService<IOptionsMonitor<DicomSCPServiceOption>>().CurrentValue;
DicomSCPServiceConfig = option;
var _hospitalGroupRepository = _serviceProvider.GetService<IRepository<HospitalGroup>>();
var _dicomAERepository = _serviceProvider.GetService<IRepository<DicomAE>>();
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>>();
ThirdDestinationAEList = _dicomAERepository.Where(t => t.PacsTypeEnum == PacsType.Destination).Select(t => new ThirdDestinationAE() { IP = t.IP, Port = t.Port, Name = t.CalledAE }).ToList();
var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault();
var aeList = _dicomAERepository/*.Where(t => t.PacsTypeEnum == PacsType.PacsServer)*/.Select(t => t.CalledAE).ToList();
if (findTrialSiteAE != null)
{
_trialSiteId = findTrialSiteAE.TrialSiteId;
var list = _hospitalGroupRepository.Where(t => t.IsEnable).ToList();
isCanReceiveIamge = true;
}
CurrentHospitalGroup = list.FirstOrDefault(t => t.CallingAE == association.CallingAE);
}
if (association.CallingAE == "test-callingAE")
{
isCanReceiveIamge = true;
}
var unionAEList = aeList.Union(list.Select(t => t.CallingAE)).ToList();
if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge == false)
var calledAEList = option.CalledAEList;
if (!calledAEList.Contains(association.CalledAE) || !unionAEList.Any(t => t == association.CallingAE))
{
Log.Logger.Warning($"拒绝CallingAE:{association.CallingAE} CalledAE:{association.CalledAE}的连接");
Log.Logger.Warning($"拒绝CalledAE:{association.CalledAE} CallingAE:{association.CallingAE}连接");
return SendAssociationRejectAsync(
DicomRejectResult.Permanent,
@ -158,74 +199,82 @@ namespace IRaCIS.Core.SCP.Service
}
}
return SendAssociationAcceptAsync(association);
}
public async Task OnReceiveAssociationReleaseRequestAsync()
{
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var @lock = _distributedLockProvider.CreateLock($"{_upload.CallingAE}");
using (await @lock.AcquireAsync())
if (_isCurrentThirdForward == false)
{
await DataMaintenanceAsaync();
//记录监控
await AddUploadLogAsync();
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var @lock = _distributedLockProvider.CreateLock($"{_upload.CallingAE}");
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
//将检查设置为传输结束
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
using (await @lock.AcquireAsync())
{
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
await DataMaintenanceAsaync();
await AddUploadLogAsync();
_releasedNormally = true;
Log.Logger.Information($"进入释放连接请求 {_releasedNormally}");
}
}
await SendAssociationReleaseResponseAsync();
await SendAssociationReleaseResponseAsync();
}
private async Task AddUploadLogAsync()
{
//记录监控
//转发第三方,那么不记录日志
if (_isCurrentThirdForward == false)
{
//记录监控
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
_upload.EndTime = DateTime.Now;
_upload.StudyCount = _ImageUploadList.Count;
_upload.TrialId = _trialId;
_upload.TrialSiteId = _trialSiteId;
_upload.EndTime = DateTime.Now;
_upload.StudyCount = _ImageUploadList.Count;
_upload.UploadJsonStr = (new SCPImageLog() { UploadList = _ImageUploadList }).ToJsonStr();
_upload.UploadJsonStr = (new SCPImageLog() { UploadList = _ImageUploadList }).ToJsonStr();
if (_upload.FileCount > 0)
{
//可能是测试echo 导致记录了
await _SCPImageUploadRepository.AddAsync(_upload, true);
}
}
//可能是测试echo 导致记录了
await _SCPImageUploadRepository.AddAsync(_upload, _upload.FileCount > 0 ? true : false);
}
private async Task DataMaintenanceAsaync()
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束开始维护数据处理检查Modality");
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束开始维护数据处理检查Modality 以及自动创建访视,绑定检查");
var patientStudyService = _serviceProvider.GetService<IPatientStudyService>();
await patientStudyService.AutoBindingPatientStudyVisitAsync(_SCPStudyIdList);
//处理检查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 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, t.StudyInstanceUid }).ToList();
foreach (var g in seriesModalityList.GroupBy(t => new { t.SCPStudyId, t.StudyInstanceUid }))
{
var modality = string.Join('、', g.Select(t => t.Modality).Distinct().ToList());
@ -246,7 +295,9 @@ namespace IRaCIS.Core.SCP.Service
modalityForEdit = "PET-CT";
}
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == g.Key, u => new SCPStudy() { Modalities = modality, ModalityForEdit = modalityForEdit });
await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == g.Key.SCPStudyId, u => new SCPStudy() { Modalities = modality, ModalityForEdit = modalityForEdit });
}
@ -262,27 +313,70 @@ namespace IRaCIS.Core.SCP.Service
public async void OnConnectionClosed(Exception exception)
{
/* nothing to do here */
//奇怪的bug 上传的时候用王捷修改的影像会关闭重新连接导致检查id 丢失,然后状态不一致
if (exception == null)
if (_isCurrentThirdForward == false)
{
//var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
////将检查设置为传输结束
//await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
//await _studyRepository.SaveChangesAndClearAllTrackingAsync();
}
else
{
//记录日志
await AddUploadLogAsync();
if (exception != null || _releasedNormally == false)
{
//客户端断网,恢复后,也是没有异常的,估计是超时走了关闭
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true, IsUploadFaild = true });
//记录日志
await AddUploadLogAsync();
}
else
{
//将检查设置为传输结束
await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true, IsUploadFaild = false });
}
await _studyRepository.SaveChangesAndClearAllTrackingAsync();
}
Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
Log.Logger.Warning($"连接关闭 {_releasedNormally} {exception?.Message} {exception?.InnerException?.Message}");
}
private async Task<DicomStatus> ForwardToThirdPartyAsync(DicomCStoreRequest request, ThirdDestinationAE findDestination)
{
await _forwardLimiter.WaitAsync(); // 限制并发数量
try
{
var forwardRequest = new DicomCStoreRequest(request.File.Clone());
var client = DicomClientFactory.Create(
findDestination.IP,
findDestination.Port,
false,
DicomSCPServiceConfig.CalledAEList.First(),
findDestination.Name);
DicomStatus finalStatus = DicomStatus.Success;
forwardRequest.OnResponseReceived += (rq, rp) =>
{
Log.Logger.Information($"Forwarded C-STORE Response: {rq.SOPInstanceUID} {rp.Status}");
finalStatus = rp.Status; // 记录目标 PACS 返回状态
};
await client.AddRequestAsync(forwardRequest);
await client.SendAsync();
return finalStatus; // 返回实际状态
}
catch (Exception ex)
{
Log.Logger.Error("Error forwarding C-STORE: " + ex.Message);
return DicomStatus.ProcessingFailure; // 出错返回失败状态
}
finally
{
_forwardLimiter.Release();
}
}
public async Task<DicomCStoreResponse> OnCStoreRequestAsync(DicomCStoreRequest request)
@ -300,30 +394,74 @@ namespace IRaCIS.Core.SCP.Service
return new DicomCStoreResponse(request, DicomStatus.Success);
}
var _cmoveStudyRepository = _serviceProvider.GetService<IRepository<CmoveStudy>>();
#region 判断是否转发第三方影像
if (DicomSCPServiceConfig.IsSupportThirdService)
{
var cmoveInfo = _cmoveStudyRepository.Where(t => t.StudyInstanceUIDList.Any(c => c == studyInstanceUid)).OrderByDescending(t => t.CreateTime).FirstOrDefault();
//确定是第三方请求
if (cmoveInfo != null && ThirdDestinationAEList.Any(t => t.Name == cmoveInfo.DestinationAE))
{
_isCurrentThirdForward = true;
var findDestination = ThirdDestinationAEList.FirstOrDefault(t => t.Name == cmoveInfo.DestinationAE);
if (DicomSCPServiceConfig.IsForwardImageMultiThread)
{
// 多线程模式,异步执行
_ = Task.Run(() => ForwardToThirdPartyAsync(request, findDestination));
// 立即返回 Success
return new DicomCStoreResponse(request, DicomStatus.Success);
}
else
{
// 单线程模式,同步等待完成
var responseStatus = await ForwardToThirdPartyAsync(request, findDestination);
return new DicomCStoreResponse(request, responseStatus);
}
}
}
#endregion
//确保来了影像集合存在
if (!_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
{
_ImageUploadList.Add(new ImageUploadInfo() { StudyInstanceUid = studyInstanceUid });
}
//Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid, trialId.ToString());
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, _trialId.ToString());
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, _trialId.ToString());
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
var ossService = _serviceProvider.GetService<IOSSService>();
var dicomArchiveService = _serviceProvider.GetService<IDicomArchiveService>();
var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
var _studyGroupRepository = _serviceProvider.GetService<IRepository<SCPStudyHospitalGroup>>();
var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
var storeRelativePath = string.Empty;
var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}/{studyInstanceUid}";
var ossFolderPath = $"Dicom/{studyInstanceUid}";
long fileSize = 0;
try
{
using (MemoryStream ms = new MemoryStream())
{
await request.File.SaveAsync(ms);
@ -410,8 +548,7 @@ namespace IRaCIS.Core.SCP.Service
{
try
{
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.File, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE,fileSize);
var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.File, storeRelativePath, Association.CallingAE, Association.CalledAE, fileSize);
var series = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
@ -435,10 +572,14 @@ namespace IRaCIS.Core.SCP.Service
series.ImageResizePath = seriesPath;
//await _seriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { ImageResizePath = seriesPath });
}
}
await _seriesRepository.SaveChangesAsync();
if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
@ -458,6 +599,38 @@ namespace IRaCIS.Core.SCP.Service
{
find.SCPStudyId = scpStudyId;
#region 给检查打课题组标签
//添加课题组标签
if (CurrentHospitalGroup != null)
{
if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == CurrentHospitalGroup.Id))
{
await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = CurrentHospitalGroup.Id });
}
}
else
{
var findCmoveInfo = _cmoveStudyRepository.Where(t => t.StudyInstanceUIDList.Any(c => c == studyInstanceUid)).OrderByDescending(t => t.CreateTime).FirstOrDefault();
if (findCmoveInfo != null)
{
foreach (var item in findCmoveInfo.HopitalGroupIdList)
{
if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == item))
{
await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = item });
}
}
}
else
{
Log.Logger.Warning($"未找到{studyInstanceUid}的Cmove记录");
}
}
#endregion
}
}
}
@ -476,19 +649,20 @@ namespace IRaCIS.Core.SCP.Service
}
//监控信息设置
_upload.FileCount++;
_upload.FileSize = _upload.FileSize + fileSize;
return new DicomCStoreResponse(request, DicomStatus.Success);
}
//监控信息设置
_upload.FileCount++;
_upload.FileSize = _upload.FileSize + fileSize;
return new DicomCStoreResponse(request, DicomStatus.Success);
}
public Task OnCStoreRequestExceptionAsync(string tempFileName, Exception e)
{
Log.Logger.Warning($"CStoreRequestException {tempFileName} {e?.Message} {e?.InnerException?.Message}");
// let library handle logging and error response
return Task.CompletedTask;
}

View File

@ -11,7 +11,6 @@ using FellowOakDicom.Network;
using IRaCIS.Core.SCP.Service;
using IRaCIS.Core.Infra.EFCore;
using MassTransit;
using System.Runtime.Intrinsics.X86;
using Serilog.Sinks.File;
using IRaCIS.Core.Infrastructure.Extention;
@ -53,20 +52,21 @@ namespace IRaCIS.Core.SCP.Service
/// <param name="dataset"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Guid> ArchiveDicomFileAsync(DicomFile dicomFile, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE,long fileSize)
public async Task<Guid> ArchiveDicomFileAsync(DicomFile dicomFile, string fileRelativePath, string callingAE, string calledAE, long fileSize)
{
var dataset = dicomFile.Dataset;
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);
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());
Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid);
Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
var isStudyNeedAdd = false;
var isSeriesNeedAdd = false;
@ -77,15 +77,16 @@ namespace IRaCIS.Core.SCP.Service
//using (@lock.Acquire())
{
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId );
var findStudy = await _studyRepository.FirstOrDefaultAsync(t=>t.Id== studyId);
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr);
var findStudy = await _studyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
var findInstance = await _instanceRepository.FirstOrDefaultAsync(t => t.Id == 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*/)
//先传输了,修改了患者编号的又传输了没有修改患者编号的导致后传输的没有修改患者编号的下面的检查为0
if (findPatient == null /*&& findStudy == null*/)
{
isPatientNeedAdd = true;
@ -93,8 +94,6 @@ namespace IRaCIS.Core.SCP.Service
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),
@ -120,20 +119,6 @@ namespace IRaCIS.Core.SCP.Service
{
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
{
@ -192,13 +177,12 @@ namespace IRaCIS.Core.SCP.Service
PatientId = findPatient.Id,
Id = studyId,
TrialId = trialId,
TrialSiteId = trialSiteId,
StudyInstanceUid = studyInstanceUid,
StudyTime = studyTime,
DicomStudyDate = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty),
DicomStudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty),
Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
//ModalityForEdit = modalityForEdit,
Description = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
@ -220,12 +204,6 @@ namespace IRaCIS.Core.SCP.Service
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
Manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty),
ManufacturerModelName = dataset.GetSingleValueOrDefault(DicomTag.ManufacturerModelName, string.Empty),
DeviceSerialNumber = dataset.GetSingleValueOrDefault(DicomTag.DeviceSerialNumber, string.Empty),
DeviceUID = dataset.GetSingleValueOrDefault(DicomTag.DeviceUID, string.Empty),
SoftwareVersions = dataset.GetSingleValueOrDefault(DicomTag.SoftwareVersions, string.Empty),
PatientWeight = dataset.GetSingleValueOrDefault(DicomTag.PatientWeight, string.Empty),
//IsDoubleReview = addtionalInfo.IsDoubleReview,
@ -287,9 +265,6 @@ namespace IRaCIS.Core.SCP.Service
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
RadiopharmaceuticalInformationSequence = dataset.GetSingleValueOrDefault(DicomTag.RadiopharmaceuticalInformationSequence, string.Empty),
AcquisitionDate = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionDate, string.Empty),
InstanceCount = 0
};
@ -323,6 +298,12 @@ namespace IRaCIS.Core.SCP.Service
SeriesInstanceUid = findSerice.SeriesInstanceUid,
SopInstanceUid = sopInstanceUid,
SOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty),
MediaStorageSOPClassUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty),
TransferSyntaxUID = transferSyntaxUID,
MediaStorageSOPInstanceUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty),
IsEncapsulated = isEncapsulated,
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,
@ -341,25 +322,9 @@ namespace IRaCIS.Core.SCP.Service
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
PhotometricInterpretation = dataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty),
BitsAllocated = dataset.GetSingleValueOrDefault(DicomTag.BitsAllocated, 0),
PixelRepresentation = dataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, string.Empty),
RescaleIntercept = dataset.GetSingleValueOrDefault(DicomTag.RescaleIntercept, string.Empty),
RescaleSlope = dataset.GetSingleValueOrDefault(DicomTag.RescaleSlope, string.Empty),
ImagePositionPatient = dataset.GetSingleValueOrDefault(DicomTag.ImagePositionPatient, string.Empty),
ImageOrientationPatient = dataset.GetSingleValueOrDefault(DicomTag.ImageOrientationPatient, string.Empty),
SequenceOfUltrasoundRegions = dataset.GetSingleValueOrDefault(DicomTag.SequenceOfUltrasoundRegions, string.Empty),
FrameTime = dataset.GetSingleValueOrDefault(DicomTag.FrameTime, string.Empty),
CorrectedImage = dataset.GetSingleValueOrDefault(DicomTag.CorrectedImage, string.Empty),
Units = dataset.GetSingleValueOrDefault(DicomTag.Units, string.Empty),
DecayCorrection = dataset.GetSingleValueOrDefault(DicomTag.DecayCorrection, string.Empty),
EncapsulatedDocument = dataset.GetSingleValueOrDefault(DicomTag.EncapsulatedDocument, string.Empty),
Path = fileRelativePath,
FileSize= fileSize,
FileSize = fileSize,
};
++findStudy.InstanceCount;
@ -368,9 +333,9 @@ namespace IRaCIS.Core.SCP.Service
else
{
findInstance.SOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty);
findInstance.MediaStorageSOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty);
findInstance.TransferSytaxUID = transferSyntaxUID;
findInstance.MediaStorageSOPInstanceUID = dataset.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty);
findInstance.MediaStorageSOPClassUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty);
findInstance.TransferSyntaxUID = transferSyntaxUID;
findInstance.MediaStorageSOPInstanceUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty);
findInstance.IsEncapsulated = isEncapsulated;
findInstance.UpdateTime = DateTime.Now;
}
@ -392,13 +357,14 @@ namespace IRaCIS.Core.SCP.Service
{
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 _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath, FileSize = fileSize });
}
await _studyRepository.SaveChangesAsync();

View File

@ -5,7 +5,7 @@ namespace IRaCIS.Core.SCP.Service
{
public interface IDicomArchiveService
{
Task<Guid> ArchiveDicomFileAsync(DicomFile dicomFile, Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE,long fileSize);
Task<Guid> ArchiveDicomFileAsync(DicomFile dicomFile,string fileRelativePath,string callingAE,string calledAE,long fileSize);
}
}

View File

@ -12,6 +12,7 @@ using MassTransit;
using Microsoft.Extensions.Options;
using Minio;
using Minio.DataModel.Args;
using System.Net;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
@ -118,7 +119,7 @@ public class AWSTempToken
public string SecretAccessKey { get; set; }
public string BucketName { get; set; }
public string ViewEndpoint { get; set; }
public DateTime Expiration { get; set; }
public DateTime? Expiration { get; set; }
}
public enum ObjectStoreUse
@ -216,9 +217,19 @@ public class OSSService : IOSSService
.WithBucket(minIOConfig.BucketName)
.WithObject(ossRelativePath)
.WithStreamData(memoryStream)
.WithObjectSize(memoryStream.Length);
await minioClient.PutObjectAsync(putObjectArgs);
var putResponse = await minioClient.PutObjectAsync(putObjectArgs);
if (putResponse.ResponseStatusCode == HttpStatusCode.OK)
{
}
else
{
throw new BusinessValidationFailedException($"上传失败ResponseStatusCode{putResponse.ResponseStatusCode}{putResponse.ResponseContent}");
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{

View File

@ -0,0 +1,268 @@
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 Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.EntityFrameworkCore;
namespace IRaCIS.Core.SCP.Service
{
public interface IPatientStudyService
{
Task<IResponseOutput> AutoBindingPatientStudyVisitAsync(List<Guid> scpStudyIdList);
}
[ApiExplorerSettings(GroupName = "Trial")]
public class PatientStudyService : BaseService, IPatientStudyService
{
private readonly IRepository<SCPStudySubjectVisit> _studySubjectVisitRepository;
private readonly IRepository<SubjectPatient> _subjectPatientRepository;
private readonly IRepository<Trial> _trialRepository;
private readonly IRepository<SCPPatient> _patientRepository;
private readonly IRepository<SCPStudy> _studyRepository;
private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
public PatientStudyService(IRepository<SCPStudySubjectVisit> studySubjectVisitRepository, IRepository<SCPStudy> studyRepository, IRepository<SubjectPatient> subjectPatientRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
{
_studySubjectVisitRepository = studySubjectVisitRepository;
_studyRepository = studyRepository;
_subjectPatientRepository = subjectPatientRepository;
_trialRepository = trialRepository;
_patientRepository = patientRepository;
_subjectRepository = subjectRepository;
_subjectVisitRepository = subjectVisitRepository;
_distributedLockProvider = distributedLockProvider;
}
public class AuToBindingStudyInfo
{
public Guid SCPStudyId { get; set; }
public DateTime? StudyTime { get; set; }
}
private async Task DealAutoBindingStudyAsync(Guid trialId, Guid subjectId, List<AuToBindingStudyInfo> studyList, decimal? startBindVisitNum = null)
{
//自动创建访视 和检查绑定
//1. 查询已存在的访视
var subjectAllVisitList = await _subjectVisitRepository.Where(t => t.SubjectId == subjectId)
.Select(t => new
{
t.SubjectId,
SubjectVisitId = t.Id,
t.SubmitState,
VisitNum = t.VisitNum,
MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime),
MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime)
})
.ToListAsync();
//2、获取项目配置
var trialconfig = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault();
//3、 未提交的最小的访视号 从这个访视开始绑定
decimal subjectMaxVisitNum = 0;
if (startBindVisitNum == null)
{
if (subjectAllVisitList.Any(t => t.SubmitState != SubmitStateEnum.Submitted))
{
subjectMaxVisitNum = subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum);
}
else
{
//没有未提交的那么开始绑定的就是已提交的加1
subjectMaxVisitNum = subjectAllVisitList.Any() ? subjectAllVisitList.Last().VisitNum + 1 : 0;
}
}
else
{
subjectMaxVisitNum = startBindVisitNum.Value;
}
//var subjectMaxVisitNum = startBindVisitNum == null ? subjectAllVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).MinOrDefault(t => t.VisitNum) : startBindVisitNum.Value;
List<(int VisitCount, Guid SCPStudyId)> visits = new List<(int, Guid)>();
int visitCount = 0;
DateTime? lastVisitTime = null;
foreach (var study in studyList)
{
if (lastVisitTime == null || (study.StudyTime - lastVisitTime.Value).Value.TotalDays >= 15)
{
// 当前时间点与上一个访视时间点间隔大于等于 15 天,需要建立一个新的访视
visitCount++;
visits.Add((visitCount, study.SCPStudyId));
}
else
{
visits.Add((visitCount, study.SCPStudyId));
}
lastVisitTime = study.StudyTime;
}
//4、生成访视 并且绑定
for (int i = 0; i < visitCount; i++)
{
var bindSubjectVisitId = Guid.Empty;
var bindVisitNum = i + subjectMaxVisitNum;
var existSubjectVisit = subjectAllVisitList.FirstOrDefault(t => t.SubjectId == subjectId && t.VisitNum == bindVisitNum);
if (existSubjectVisit == null)
{
bindSubjectVisitId = NewId.NextGuid();
//基线
if (bindVisitNum == 0)
{
await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindBaseLineName, VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit, IsBaseLine = true });
}
else
{
await _subjectVisitRepository.AddAsync(new SubjectVisit() { TrialId = trialId, SubjectId = subjectId, VisitName = trialconfig.BlindFollowUpPrefix + $" {(int)bindVisitNum}", VisitNum = bindVisitNum, Id = bindSubjectVisitId, SubmitState = SubmitStateEnum.ToSubmit });
}
}
else
{
bindSubjectVisitId = existSubjectVisit.SubjectVisitId;
}
var currentVisitStudyList = visits.Where(t => t.VisitCount == (i + 1)).ToList();
foreach (var item in currentVisitStudyList)
{
//访视状态为未提交才绑定
if (!subjectAllVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisitId == bindSubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted))
{
var find = await _subjectVisitRepository.FindAsync(bindSubjectVisitId);
find.SubmitState = SubmitStateEnum.ToSubmit;
await _studySubjectVisitRepository.AddAsync(new SCPStudySubjectVisit() { TrialId = trialId, SubjectVisitId = bindSubjectVisitId, SCPStudyId = item.SCPStudyId, SubjectId = subjectId });
}
}
}
await _subjectPatientRepository.SaveChangesAsync();
}
/// <summary>
/// 传输完成后,自动给检查绑定访视
/// </summary>
/// <param name="inCommand"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> AutoBindingPatientStudyVisitAsync(List<Guid> scpStudyIdList)
{
//一个检查 可能绑定到不同的项目的不同subject 有的该检查已绑定访视,有的该检查绑定了访视
var query = from scpStudy in _studyRepository.Where(t => scpStudyIdList.Contains(t.Id))
join subjectPatient in _subjectPatientRepository.AsQueryable()
on scpStudy.PatientId equals subjectPatient.PatientId
select new
{
subjectPatient.Subject.Status,
subjectPatient.Subject.TrialId,
subjectPatient.SubjectId,
subjectPatient.PatientId,
SCPStudyId = scpStudy.Id,
scpStudy.StudyTime
};
var list = query.ToList();
if (list.Count > 0)
{
var subjectIdList = list.Select(t => t.SubjectId).ToList();
var allSubjectVisitList = await _subjectVisitRepository.Where(t => subjectIdList.Contains(t.SubjectId))
.Select(t => new { t.SubjectId, SubjectVisitId = t.Id, t.SubmitState, VisitNum = t.VisitNum, MaxStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), MinStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime) })
.ToListAsync();
foreach (var g in list.GroupBy(t => new { t.SubjectId, t.TrialId, t.Status }))
{
var subjectId = g.Key.SubjectId;
var trialId = g.Key.TrialId;
//访视结束,那么就不处理
if (g.Key.Status == SubjectStatus.EndOfVisit)
{
continue;
}
// 预先处理1 数据库可能有已存在的subject 患者绑定,在这里要一起考虑绑定
var dbPatientIdList = _subjectPatientRepository.Where(t => t.SubjectId == subjectId).Select(t => t.PatientId).ToList();
// 预先处理2 删除未提交的所有绑定的检查记录,所有检查一起考虑绑定
await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted);
//预处理3 找到该subjecct 已提交的访视的最大检查时间,绑定的检查时间要比这个时间要大
var maxStudyTime = allSubjectVisitList.Where(t => t.SubjectId == subjectId && t.SubmitState == SubmitStateEnum.Submitted).MaxOrDefault(t => t.MaxStudyTime);
// 预处理4 处理需要绑定的检查
//获取 该受试者绑定患者已存在的检查,考虑要生成多少个访视,去除已提交的检查
var studyList = await _studyRepository.Where(t => dbPatientIdList.Contains(t.PatientId)
&& !t.SCPStudySubjectVisitList.Any(t => t.SubjectId == subjectId && t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted))
.WhereIf(maxStudyTime != null, t => t.StudyTime > maxStudyTime)
.Select(t => new AuToBindingStudyInfo { SCPStudyId = t.Id, StudyTime = t.StudyTime }).OrderBy(t => t.StudyTime).ToListAsync();
await DealAutoBindingStudyAsync(trialId, subjectId, studyList);
}
await _subjectVisitRepository.SaveChangesAsync();
}
//将检查设置为传输结束
await _studyRepository.BatchUpdateNoTrackingAsync(t => scpStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
return ResponseOutput.Ok();
}
}
}

View File

@ -0,0 +1,36 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "47.102.87.183",
"Port": "9000",
"UseSSL": false,
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"BucketName": "hir-images",
"ViewEndpoint": "http://47.102.87.18:9001/hir-images/"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=47.102.87.183,1434;Database=HIR_Prod;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
"Hangfire": "Server=47.102.87.183,1434;Database=HIR_Prod_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"IsForwardImageMultiThread": true,
"MultiThreadCount": 10,
"CalledAEList": [
"HIRAE",
"STORESCP"
],
"ServerPort": 11115
}
}

View File

@ -1,37 +0,0 @@
{
"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
}
}

View File

@ -0,0 +1,35 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "192.168.40.99",
"Port": "9000",
"UseSSL": false,
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
"BucketName": "tj-hir",
"ViewEndpoint": "http://192.168.40.99:9000/tj-hir"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
"Hangfire": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP",
"HIRAE",
"Value2",
"Value3"
],
"ServerPort": 11112
}
}

View File

@ -0,0 +1,36 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "106.14.89.110",
"Port": "9001",
"UseSSL": false,
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"BucketName": "hir-test",
"ViewEndpoint": "http://106.14.89.110:9001/hir-test/"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"IsForwardImageMultiThread": true,
"MultiThreadCount":10,
"CalledAEList": [
"HIRAE",
"STORESCP"
],
"ServerPort": 11115
}
}

View File

@ -1,48 +0,0 @@
{
"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
}
}

View File

@ -0,0 +1,36 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "3.226.182.187",
"Port": "9001",
"UseSSL": false,
"AccessKeyId": "7rvVIHs7D6pbyscRcJhz",
"SecretAccessKey": "DQsCQldHFL3QRjlnaLWV7oM4E9PtsO21QPC2h9BD",
"BucketName": "hir-us",
"ViewEndpoint": "http://hir-minio.uat.elevateimaging.ai/hir-us"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=3.226.182.187,1435;Database=US_HIR;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=3.226.182.187,1435;Database=US_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"IsForwardImageMultiThread": true,
"MultiThreadCount": 10,
"CalledAEList": [
"STORESCP",
"HIRAE"
],
"ServerPort": 11112
}
}

View File

@ -1,34 +0,0 @@
{
"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-mssql-prod,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-prod,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}

View File

@ -1,34 +0,0 @@
{
"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
}
}

View File

@ -0,0 +1,36 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "101.132.253.119",
"Port": "9001",
"UseSSL": false,
"AccessKeyId": "ylWQa99fDdVdTfnj47ll",
"SecretAccessKey": "kVpy2RIYN0GmyFsU2qAWhbKDf4Nskt23tEqd6sob",
"BucketName": "hir-uat",
"ViewEndpoint": "http://101.132.253.119:9001/hir-uat/"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"IsForwardImageMultiThread": true,
"MultiThreadCount": 10,
"CalledAEList": [
"STORESCP",
"HIRAE"
],
"ServerPort": 11112
}
}

View File

@ -1,35 +0,0 @@
{
"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": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "tl-med-irc-uat-store",
"ViewEndpoint": "https://tl-med-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server101.132.253.119,1435;Database=Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"DicomSCPServiceConfig": {
"CalledAEList": [
"STORESCP"
],
"ServerPort": 11112
}
}

View File

@ -19,8 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRC.Core.SCP", "IRC.Core.SCP\IRC.Core.SCP.csproj", "{ECD08F47-DC1A-484E-BB91-6CDDC8823CC5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IRC.Core.Dicom", "IRC.Core.Dicom\IRC.Core.Dicom.csproj", "{0545F0A5-D97B-4A47-92A6-A8A02A181322}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -59,10 +57,6 @@ Global
{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
{0545F0A5-D97B-4A47-92A6-A8A02A181322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0545F0A5-D97B-4A47-92A6-A8A02A181322}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0545F0A5-D97B-4A47-92A6-A8A02A181322}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0545F0A5-D97B-4A47-92A6-A8A02A181322}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,7 +1,6 @@
using AlibabaCloud.SDK.Sts20150401;
using Amazon.Auth.AccessControlPolicy;
using Amazon.SecurityToken;
using AutoMapper;
using Azure.Core;
using IdentityModel.Client;
using IdentityModel.OidcClient;
@ -22,7 +21,6 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Tls;
using RestSharp;
using RestSharp.Authenticators;
using System;
@ -104,11 +102,6 @@ namespace IRaCIS.Api.Controllers
}
[AllowAnonymous]
[HttpGet, Route("user/getPublicKey")]
public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)
@ -126,7 +119,7 @@ namespace IRaCIS.Api.Controllers
var token = _tokenService.GetToken(new UserTokenInfo()
{
IdentityUserId = Guid.NewGuid(),
UserName = "ImageShare",
UserName = "Share001",
UserTypeEnum = UserTypeEnum.ShareImage,
});
@ -134,6 +127,7 @@ namespace IRaCIS.Api.Controllers
}
[HttpGet("user/GetObjectStoreToken")]
[AllowAnonymous]
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
{
@ -183,7 +177,6 @@ namespace IRaCIS.Api.Controllers
return tempToken;
}
#region 老项目依赖
[HttpGet("user/GenerateSTS")]
@ -210,23 +203,7 @@ namespace IRaCIS.Api.Controllers
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,
PreviewEndpoint = ossOptions.PreviewEndpoint
};
// 返回STS令牌信息给前端
var stsToken = new

View File

@ -51,30 +51,30 @@ namespace IRaCIS.Core.API.Controllers.Special
[TrialGlobalLimit( "AddOrUpdateTrial", "BeforeOngoingCantOpt", "AfterStopCannNotOpt" )]
public async Task<IResponseOutput<Trial>> AddOrUpdateTrial(TrialCommand param)
{
//var userId = Guid.Parse(User.FindFirst("id").Value);
var userId = Guid.Parse(User.FindFirst("id").Value);
var result = await _trialService.AddOrUpdateTrial(param);
//if (_trialService.TrialExpeditedChange)
//{
// var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(param.Id.Value);
// var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
if (_trialService.TrialExpeditedChange)
{
var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(param.Id.Value);
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
// calcList.ForEach(t =>
// {
// if (needCalReviewerIds.Contains(t.DoctorId))
// {
// _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
// {
// NeedCalculateReviewers = new List<Guid>()
// {
// t.DoctorId
// },
// CalculateMonth = DateTime.Parse(t.YearMonth)
// }, User.FindFirst("id").Value);
calcList.ForEach(t =>
{
if (needCalReviewerIds.Contains(t.DoctorId))
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
t.DoctorId
},
CalculateMonth = DateTime.Parse(t.YearMonth)
}, User.FindFirst("id").Value);
// }
// });
//}
}
});
}
return result;
}

View File

@ -2,7 +2,6 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.BusinessFilter;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Image.QA;
using IRaCIS.Core.Application.Service;
@ -23,7 +22,6 @@ namespace IRaCIS.Core.API.Controllers
[ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
[UnitOfWork]
public class InspectionController(
ITrialDocumentService _trialDocumentService,
IReadingImageTaskService _iReadingImageTaskService,
ITrialConfigService _trialConfigService,
IClinicalAnswerService _clinicalAnswerService,
@ -35,31 +33,6 @@ namespace IRaCIS.Core.API.Controllers
) : ControllerBase
{
[HttpPost, Route("Inspection/NoneDicomStudy/UpdateNoneDicomStudy")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UpdateNoneDicomStudy(DataInspectionDto<NoneDicomEdit> opt, [FromServices] INoneDicomStudyService _noneDicomStudyService)
{
var singId = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _noneDicomStudyService.UpdateNoneDicomStudy(opt.Data);
await _inspectionService.CompletedSign(singId, result);
return result;
}
[HttpPost, Route("Inspection/QCOperation/UpdateDicomStudyInfo")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UpdateDicomStudyInfo(DataInspectionDto<DicomStudyEdit> opt, [FromServices] IQCOperationService _qcOperationService)
{
var singId = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _qcOperationService.UpdateDicomStudyInfo(opt.Data);
await _inspectionService.CompletedSign(singId, result);
return result;
}
#region 获取稽查数据
/// <summary>
/// 获取稽查数据
@ -78,7 +51,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitOncologyReadingInfo")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SetOncologyReadingInfo(DataInspectionDto<SubmitOncologyReadingInfoInDto> opt)
@ -95,7 +68,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitDicomVisitTask")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SubmitDicomVisitTask(DataInspectionDto<SubmitDicomVisitTaskInDto> opt)
@ -114,7 +87,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitGlobalReadingInfo")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SubmitGlobalReadingInfo(DataInspectionDto<SubmitGlobalReadingInfoInDto> opt)
@ -133,7 +106,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialReadingInfoSign")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> TrialReadingInfoSign(DataInspectionDto<TrialReadingInfoSignInDto> opt)
@ -152,7 +125,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicalReview/FinishMedicalReview")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt)
@ -169,7 +142,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicineQuestion/ConfirmReadingMedicineQuestion")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(DataInspectionDto<ConfirmReadingMedicineQuestionInDto> opt)
@ -187,7 +160,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitVisitTaskQuestions")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SubmitVisitTaskQuestions(DataInspectionDto<SubmitVisitTaskQuestionsInDto> opt)
@ -205,7 +178,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCSignClinicalData")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> CRCSignClinicalData(DataInspectionDto<CRCSignClinicalDataInDto> opt)
@ -223,7 +196,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCConfirmClinical")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> CRCConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@ -240,7 +213,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCCancelConfirmClinical")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> CRCCancelConfirmClinical(DataInspectionDto<CRCCancelConfirmClinicalInDto> opt)
@ -258,7 +231,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/PMConfirmClinical")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> PMConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@ -276,7 +249,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt)
@ -293,7 +266,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SubmitClinicalFormAndSign(DataInspectionDto<SubmitClinicalFormInDto> opt)
@ -310,7 +283,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeVisitTaskResult")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(DataInspectionDto<SaveJudgeVisitTaskResult> opt)
@ -329,7 +302,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialBasicInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
public async Task<IResponseOutput> ConfigTrialBasicInfoConfirm(DataInspectionDto<BasicTrialConfig> opt)
{
@ -371,7 +344,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialUrgentInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
public async Task<IResponseOutput> ConfigTrialUrgentInfoConfirm(DataInspectionDto<TrialUrgentConfig> opt)
{
opt.Data.IsTrialUrgentConfirmed = true;
@ -384,7 +357,7 @@ namespace IRaCIS.Core.API.Controllers
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt)
{
opt.Data.IsTrialPACSConfirmed = true;
@ -400,7 +373,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialConfigSignatureConfirm")]
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> TrialConfigSignatureConfirm(DataInspectionDto<SignConfirmDTO> opt)
{
@ -417,7 +390,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingCriterion/ResetAndAsyncCriterion")]
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> ResetAndAsyncCriterion(DataInspectionDto<ResetAndAsyncCriterionInDto> opt)
{
@ -435,7 +408,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> CRCRequestToQC(DataInspectionDto<CRCRequestToQCCommand> opt)
{
@ -450,31 +423,21 @@ namespace IRaCIS.Core.API.Controllers
/// 设置QC 通过或者不通过 7:QC failed 8QC passed
/// </summary>
[HttpPost, Route("Inspection/QCOperation/QCPassedOrFailed")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> QCPassedOrFailed(DataInspectionDto<QCPassedOrFailedDto> opt)
{
var singid = await _inspectionService.RecordSing(opt.SignInfo);
if (opt.Data.IsSecondPass != null)
{
var result = await _qCOperationService.QCSecondReviewPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, (bool)opt.Data.IsSecondPass);
await _inspectionService.CompletedSign(singid, result);
return result;
}
else
{
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState);
await _inspectionService.CompletedSign(singid, result);
return result;
}
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState);
await _inspectionService.CompletedSign(singid, result);
return result;
}
/// <summary>
/// 一致性核查 回退 对话记录不清除 只允许PM回退
/// </summary>
[HttpPost, Route("Inspection/QCOperation/CheckBack")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> CheckBack(DataInspectionDto<IDDto> opt)
{
@ -491,7 +454,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadClinicalData/ReadClinicalDataSign")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> ReadClinicalDataSign(DataInspectionDto<ReadingClinicalDataSignIndto> opt)
{
@ -506,7 +469,7 @@ namespace IRaCIS.Core.API.Controllers
/// CRC 设置已经重传完成
/// </summary>
[HttpPost, Route("Inspection/QCOperation/SetReuploadFinished")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt)
{
@ -522,7 +485,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/TrialConfig/updateTrialState")]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
[TrialGlobalLimit( "BeforeOngoingCantOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UpdateTrialState(DataInspectionDto<UpdateTrialStateDto> opt)
{
@ -533,21 +496,7 @@ namespace IRaCIS.Core.API.Controllers
}
/// <summary>
/// 用户 签名某个文档
/// </summary>
/// <returns></returns>
[HttpPost, Route("Inspection/TrialDocument/userConfirm")]
[TrialGlobalLimit("BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UserConfirm(DataInspectionDto<UserConfirmCommand> opt)
{
var singid = await _inspectionService.RecordSing(opt.SignInfo);
opt.Data.SignText = opt.SignInfo.SignText;
var result = await _trialDocumentService.UserConfirm(opt.Data);
await _inspectionService.CompletedSign(singid, result);
return result;
}
/// <summary>
@ -555,13 +504,13 @@ namespace IRaCIS.Core.API.Controllers
/// </summary>
/// <returns></returns>
[HttpPost, Route("Inspection/VisitTask/ConfirmReReading")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskService _visitTaskService)
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskHelpeService _visitTaskCommonService, [FromServices] IVisitTaskService _visitTaskService)
{
var singId = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _visitTaskService.ConfirmReReading(opt.Data);
var result = await _visitTaskService.ConfirmReReading(opt.Data, _visitTaskCommonService);
await _inspectionService.CompletedSign(singId, result);
return result;
}

View File

@ -27,7 +27,6 @@ using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using MiniExcelLibs;
using Newtonsoft.Json;
@ -39,7 +38,6 @@ using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Path = System.IO.Path;
@ -273,7 +271,6 @@ namespace IRaCIS.Core.API.Controllers
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
public bool? IsImageSegmentLabel { get; set; }
public class OSSFileDTO
{
@ -300,7 +297,7 @@ namespace IRaCIS.Core.API.Controllers
[HttpPost, Route("Study/ArchiveStudy")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> ArchiveStudyNew(Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId, Guid studyMonitorId,
[FromServices] ILogger<UploadDownLoadController> _logger,
[FromServices] IStudyService _studyService,
@ -455,7 +452,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="_studyMonitorRepository"></param>
/// <returns></returns>
[HttpPost, Route("Study/PreArchiveStudy")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
[FromServices] IStudyService _studyService,
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
@ -491,7 +488,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="_noneDicomStudyFileRepository"></param>
/// <returns></returns>
[HttpPost("NoneDicomStudy/UploadNoneDicomFile")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> UploadNoneDicomFile(UploadNoneDicomFileCommand incommand,
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository,
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository,
@ -522,17 +519,7 @@ namespace IRaCIS.Core.API.Controllers
}
else
{
if (incommand.IsImageSegmentLabel == true)
{
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, ImageLabelNoneDicomStudyId = noneDicomStudyId.Value, 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 });
}
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
}
@ -540,7 +527,7 @@ namespace IRaCIS.Core.API.Controllers
}
var uploadFinishedTime = DateTime.Now;
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyId, true);
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
noneDicomStudy.FileCount = noneDicomStudy.FileCount + (incommand.VisitTaskId != null ? 0 : incommand.UploadedFileList.Count);
@ -568,22 +555,19 @@ namespace IRaCIS.Core.API.Controllers
/// 一致性核查 excel上传 支持三种格式
/// </summary>
/// <param name="trialId"></param>
/// <param name="isFullCheck"></param>
/// <param name="oSSService"></param>
/// <param name="_inspectionFileRepository"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, bool isFullCheck, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
{
var fileName = string.Empty;
var templateFileStream = new MemoryStream();
var inspectionFileId = Guid.Empty;
await FileUploadToOSSAsync(async (realFileName, fileStream) =>
{
fileName = realFileName;
@ -598,11 +582,9 @@ namespace IRaCIS.Core.API.Controllers
templateFileStream.Seek(0, SeekOrigin.Begin);
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", realFileName);
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, "InspectionUpload/Check", realFileName);
var addEntity = await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
inspectionFileId = addEntity.Id;
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId });
return ossRelativePath;
@ -748,11 +730,8 @@ namespace IRaCIS.Core.API.Controllers
if (etcCheckList == null || etcCheckList.Count == 0)
{
await _inspectionFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == inspectionFileId, u => new InspectionFile() { CheckState = EDCCheckState.Failed });
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
}
else
{
@ -772,8 +751,6 @@ namespace IRaCIS.Core.API.Controllers
if (etcCheckList.Count == 0)
{
await _inspectionFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == inspectionFileId, u => new InspectionFile() { CheckState = EDCCheckState.Failed });
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
}
@ -785,19 +762,8 @@ namespace IRaCIS.Core.API.Controllers
//var client = _mediator.CreateRequestClient<ConsistenCheckCommand>();
//await client.GetResponse<ConsistenCheckResult>(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
if (isFullCheck)
{
await _mediator.Send(new ConsistenFullCheckCommand() { ETCList = etcCheckList, TrialId = trialId, InspectionFileId = inspectionFileId });
}
else
{
//不获取结果,不用定义返回类型
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
}
//不获取结果,不用定义返回类型
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
return ResponseOutput.Ok();
@ -831,139 +797,6 @@ namespace IRaCIS.Core.API.Controllers
_userInfo = userInfo;
}
[HttpPost, Route("TrialSiteSurvey/UploadTrialSiteSurveyUser")]
[DisableFormValueModelBinding]
public async Task<IResponseOutput> UploadTrialSiteSurveyUser(Guid trialId, string baseUrl, string routeUrl,
[FromServices] IRepository<TrialSite> _trialSiteRepository,
[FromServices] IRepository<UserType> _usertypeRepository,
[FromServices] ITrialSiteSurveyService _trialSiteSurveyService,
[FromServices] IOSSService oSSService,
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _systemEmailConfig,
[FromServices] IRepository<InspectionFile> _inspectionFileRepository)
{
var templateFileStream = new MemoryStream();
await FileUploadToOSSAsync(async (realFileName, fileStream) =>
{
await fileStream.CopyToAsync(templateFileStream);
templateFileStream.Seek(0, SeekOrigin.Begin);
if (!realFileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase))
{
// 请用提供格式的模板excel上传需要处理的数据
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_TemplateUploadData"]);
}
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/SiteSurvey", realFileName);
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
return ossRelativePath;
});
//去掉空白行
var excelList = MiniExcel.Query<SiteSurveyUserImportDto>(templateFileStream, excelType: ExcelType.XLSX).ToList()
.Where(t => !(string.IsNullOrWhiteSpace(t.TrialSiteCode) && string.IsNullOrWhiteSpace(t.FirstName) && string.IsNullOrWhiteSpace(t.LastName) && string.IsNullOrWhiteSpace(t.Email)
&& string.IsNullOrWhiteSpace(t.Phone) && string.IsNullOrWhiteSpace(t.UserTypeStr) && string.IsNullOrWhiteSpace(t.OrganizationName))).ToList();
//处理前后空格
foreach (var excel in excelList)
{
excel.Email = excel.Email.Trim();
excel.Phone = excel.Phone.Trim();
excel.OrganizationName = excel.OrganizationName.Trim();
excel.UserTypeStr = excel.UserTypeStr?.Trim();
excel.TrialSiteCode = excel.TrialSiteCode.Trim();
excel.FirstName = excel.FirstName.Trim();
excel.LastName = excel.LastName.Trim();
}
var emailRegexStr = _systemEmailConfig.CurrentValue.EmailRegexStr;
if (excelList.Any(t => !Regex.IsMatch(t.Email, emailRegexStr)))
{
var errorList = excelList.Where(t => !Regex.IsMatch(t.Email, emailRegexStr)).Select(t => t.Email).ToList();
//有邮箱不符合邮箱格式,请核查Excel数据
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidEmail"] + string.Join(" | ", errorList));
}
if (excelList.Any(t => string.IsNullOrWhiteSpace(t.TrialSiteCode) || string.IsNullOrWhiteSpace(t.FirstName) || string.IsNullOrWhiteSpace(t.LastName) || string.IsNullOrWhiteSpace(t.Email) || string.IsNullOrWhiteSpace(t.UserTypeStr)))
{
//请确保Excel中 每一行的 中心编号,姓名,邮箱,用户类型数据记录完整再进行上传
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_EnsureCompleteData"]);
}
var siteCodeList = excelList.Select(t => t.TrialSiteCode.Trim().ToUpper()).Distinct().ToList();
if (_trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode.ToUpper())).Count() != siteCodeList.Count)
{
//在项目中未找到该Excel中部分或全部中心
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_InvalidCenters"]);
}
foreach (var item in excelList.GroupBy(t => t.Email.Trim()))
{
var itemList = item.ToList();
var first = item.First();
if (itemList.Any(t => t.Email.Trim() != first.Email.Trim() || t.Phone.Trim() != first.Phone.Trim() || t.OrganizationName.Trim() != first.OrganizationName.Trim() || t.FirstName.Trim() != first.FirstName.Trim() || t.LastName.Trim() != first.LastName.Trim()))
{
//同一邮箱,用户信息应该保持一致!
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_CheckDuplicateAccounts"]);
}
}
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.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();
foreach (var item in excelList)
{
switch (item.UserTypeStr.Trim().ToUpper())
{
case "CRC":
item.UserTypeId = sysUserTypeList.FirstOrDefault(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).UserTypeId;
item.UserTypeEnum = UserTypeEnum.ClinicalResearchCoordinator;
break;
case "CRA":
item.UserTypeId = sysUserTypeList.FirstOrDefault(t => t.UserTypeEnum == UserTypeEnum.CRA).UserTypeId;
item.UserTypeEnum = UserTypeEnum.CRA;
break;
}
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).TrialSiteId;
}
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, list);
return ResponseOutput.Ok();
}
/// <summary> 通用文件下载 </summary>
@ -1004,11 +837,7 @@ namespace IRaCIS.Core.API.Controllers
EmailBodyHtml = 4,
ReadKeyFile = 5,
Other = 6,
Other = 5
}
/// <summary>
@ -1040,9 +869,6 @@ namespace IRaCIS.Core.API.Controllers
case UploadFileType.EmailBodyHtml:
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.EmailTemplate, fileName));
break;
case UploadFileType.ReadKeyFile:
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.ReadKetFile, fileName));
break;
default:
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetOtherFileUploadPath(_hostEnvironment, StaticData.Folder.TempFile, fileName));

View File

@ -0,0 +1,363 @@
using AutoMapper.Execution;
using DocumentFormat.OpenXml.Bibliography;
using FellowOakDicom;
using FellowOakDicom.Network;
using FellowOakDicom.Network.Client;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Bcpg;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
namespace IRaCIS.Core.API.HostService
{
public class DicomSCPService : DicomService, IDicomServiceProvider, IDicomCFindProvider, IDicomCEchoProvider, IDicomCMoveProvider
{
private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
{
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
{
// Lossless
DicomTransferSyntax.JPEGLSLossless,
DicomTransferSyntax.JPEG2000Lossless,
DicomTransferSyntax.JPEGProcess14SV1,
DicomTransferSyntax.JPEGProcess14,
DicomTransferSyntax.RLELossless,
// Lossy
DicomTransferSyntax.JPEGLSNearLossless,
DicomTransferSyntax.JPEG2000Lossy,
DicomTransferSyntax.JPEGProcess1,
DicomTransferSyntax.JPEGProcess2_4,
// Uncompressed
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
private IServiceProvider _serviceProvider { get; set; }
private DicomSCPServiceOption DicomSCPServiceConfig { get; set; }
public string CallingAE { get; protected set; }
public string CalledAE { get; protected set; }
public DicomSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies, IServiceProvider injectServiceProvider)
: base(stream, fallbackEncoding, log, dependencies)
{
_serviceProvider = injectServiceProvider.CreateScope().ServiceProvider;
}
public void OnConnectionClosed(Exception exception)
{
if (exception != null)
{
Logger.LogError($"Closed, exception is {exception.Message}");
}
}
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
{
Logger.LogError($"Received abort from {source}, reason is {reason}");
}
public Task OnReceiveAssociationReleaseRequestAsync()
{
return SendAssociationReleaseResponseAsync();
}
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
{
CallingAE = association.CallingAE;
CalledAE = association.CalledAE;
Logger.LogInformation($"Received association request from AE: {CallingAE} with IP: {association.RemoteHost} ");
DicomSCPServiceConfig = _serviceProvider.GetService<IOptionsMonitor<DicomSCPServiceOption>>().CurrentValue;
var calledAEList = DicomSCPServiceConfig.CalledAEList;
//不支持三方服务 或者CallAE不对那么拒绝连接
if (!calledAEList.Contains(CalledAE) || DicomSCPServiceConfig.IsSupportThirdService == false || CallingAE != DicomSCPServiceConfig.ThirdCallningAE)
{
Logger.LogError($"Association with {CallingAE} rejected since called aet {CalledAE} is unknown");
return SendAssociationRejectAsync(DicomRejectResult.Permanent, DicomRejectSource.ServiceUser, DicomRejectReason.CalledAENotRecognized);
}
foreach (var pc in association.PresentationContexts)
{
if (pc.AbstractSyntax == DicomUID.Verification
|| pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelFind
|| pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelMove
|| pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelFind
|| pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelMove)
{
pc.AcceptTransferSyntaxes(_acceptedTransferSyntaxes);
}
else if (pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelGet
|| pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelGet)
{
pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
}
else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
{
pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
}
else
{
Logger.LogWarning($"Requested abstract syntax {pc.AbstractSyntax} from {CallingAE} not supported");
pc.SetResult(DicomPresentationContextResult.RejectAbstractSyntaxNotSupported);
}
}
Logger.LogInformation($"Accepted association request from {CallingAE}");
return SendAssociationAcceptAsync(association);
}
public Task<DicomCEchoResponse> OnCEchoRequestAsync(DicomCEchoRequest request)
{
Logger.LogInformation("Received verification request from AE {0} with IP: {1}", CallingAE, Association.RemoteHost);
return Task.FromResult(new DicomCEchoResponse(request, DicomStatus.Success));
}
public async IAsyncEnumerable<DicomCFindResponse> OnCFindRequestAsync(DicomCFindRequest request)
{
Console.WriteLine("Received C-FIND request, forwarding to real PACS...");
var cts = new CancellationTokenSource();
var _dicomAERepository = _serviceProvider.GetService<IRepository<DicomAE>>();
var find = await _dicomAERepository.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.PacsServer && t.CalledAE == DicomSCPServiceConfig.ThirdSearchPacsAE);
var hirClient = await _dicomAERepository.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRClient);
if (find == null || hirClient == null)
{
Logger.LogInformation("客户端和Pacs配置未查询到");
yield return new DicomCFindResponse(request, DicomStatus.ProcessingFailure);
yield break;
}
string patientID = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
string patientName = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
string studyDate = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty);
string studyInstanceUID = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
string accessionNumber = request.Dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty);
if (patientID.IsNullOrEmpty() && patientName.IsNullOrEmpty() && studyInstanceUID.IsNullOrEmpty() && studyDate.IsNullOrEmpty() && accessionNumber.IsNullOrEmpty())
{
yield return new DicomCFindResponse(request, DicomStatus.MissingAttribute);
yield break;
}
// 创建 channel 用于异步传递响应
var channel = Channel.CreateUnbounded<DicomCFindResponse>();
// 克隆 dataset 避免线程/状态冲突
var clonedDataset = request.Dataset?.Clone() ?? new DicomDataset();
var forward = new DicomCFindRequest(request.SOPClassUID, request.Level)
{
Dataset = clonedDataset
};
var receivedCount = 0;
// 标记是否已收到 final 状态Success/Failure/Cancel
var finalReceived = false;
// 当远端 PACS 返回响应时,异步写入 channel
forward.OnResponseReceived += (rq, rp) =>
{
#region 取消,现在不行
////100条的时候直接取消
//if (receivedCount >= 10)
//{
// rp.Status = DicomStatus.Cancel;
// cts.Cancel(); // 触发取消
// Logger.LogWarning("超过100条剩余的取消!");
//}
//receivedCount++;
#endregion
var dsCopy = rp.Dataset?.Clone();
var proxyResp = new DicomCFindResponse(request, rp.Status)
{
Dataset = dsCopy
};
channel.Writer.TryWrite(proxyResp);
if (!rp.Status.Equals(DicomStatus.Pending))
{
finalReceived = true;
}
};
// 异步发送到真实 PACS
_ = Task.Run(async () =>
{
try
{
var client = DicomClientFactory.Create(find.IP, find.Port, false, hirClient.CalledAE, find.CalledAE);
await client.AddRequestAsync(forward);
await client.SendAsync(cancellationToken: cts.Token);
}
catch (Exception ex)
{
Console.WriteLine("Error forwarding C-FIND: " + ex.Message);
}
finally
{
channel.Writer.Complete();
}
});
// 异步 yield 返回给上游
await foreach (var resp in channel.Reader.ReadAllAsync())
{
yield return resp;
}
// 兜底:如果没有 final 响应,返回 Success
if (!finalReceived)
{
yield return new DicomCFindResponse(request, DicomStatus.Success);
}
}
public async IAsyncEnumerable<DicomCMoveResponse> OnCMoveRequestAsync(DicomCMoveRequest request)
{
Console.WriteLine("Received C-Move request, forwarding to real PACS...");
var _dicomAERepository = _serviceProvider.GetService<IRepository<DicomAE>>();
var _cmoveStudyRepository = _serviceProvider.GetService<IRepository<CmoveStudy>>();
var find = await _dicomAERepository.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.PacsServer && t.CalledAE == DicomSCPServiceConfig.ThirdSearchPacsAE);
var hirServer = await _dicomAERepository.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRServer);
var hirClient = await _dicomAERepository.FirstOrDefaultAsync(t => t.PacsTypeEnum == PacsType.HIRClient);
if (find == null || hirClient == null || hirServer == null)
{
Logger.LogInformation("客户端和Pacs配置未查询到");
}
var studyInstanceUid = request.Dataset?.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
if (studyInstanceUid.IsNotNullOrEmpty())
{
await _cmoveStudyRepository.AddAsync(new CmoveStudy() { CallingAE = CallingAE, CalledAE = CalledAE, DestinationAE = request.DestinationAE, StudyInstanceUIDList = new List<string>() { studyInstanceUid }, HopitalGroupIdList = new List<Guid>() }, true);
}
var channel = Channel.CreateUnbounded<DicomCMoveResponse>();
var clonedDataset = request.Dataset?.Clone() ?? new DicomDataset();
var forward = new DicomCMoveRequest(hirServer.CalledAE, studyInstanceUid)
{
Dataset = clonedDataset
};
bool finalReceived = false;
// PACS 返回响应时写入 channel
forward.OnResponseReceived += (rq, rp) =>
{
var dsCopy = rp.Dataset?.Clone();
var proxyResp = new DicomCMoveResponse(request, rp.Status)
{
Dataset = dsCopy,
Remaining = rp.Remaining,
Completed = rp.Completed,
Failures = rp.Failures,
Warnings = rp.Warnings,
};
Logger.LogInformation($"Completed:{rp.Completed}");
channel.Writer.TryWrite(proxyResp);
if (!rp.Status.Equals(DicomStatus.Pending))
{
finalReceived = true;
}
};
// 异步发送到真实 PACS
_ = Task.Run(async () =>
{
try
{
var client = DicomClientFactory.Create(find.IP, find.Port, false, hirClient.CalledAE, find.CalledAE);
await client.AddRequestAsync(forward);
await client.SendAsync();
}
catch (Exception ex)
{
Console.WriteLine("Error forwarding C-MOVE: " + ex.Message);
}
finally
{
channel.Writer.Complete();
}
});
// 异步 yield 回上游
await foreach (var resp in channel.Reader.ReadAllAsync())
{
yield return resp;
}
// 兜底
if (!finalReceived)
{
yield return new DicomCMoveResponse(request, DicomStatus.Success);
}
}
}
}

View File

@ -20,8 +20,6 @@ namespace IRaCIS.Core.API.HostService;
public class HangfireHostService(IRecurringMessageScheduler _recurringMessageScheduler,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IMediator _mediator,
ILogger<HangfireHostService> _logger) : IHostedService
{
@ -41,22 +39,7 @@ public class HangfireHostService(IRecurringMessageScheduler _recurringMessageSch
HangfireJobHelper.RemoveCronJob(jobId);
}
// 清除所有可能存在的定时任务,防止类型加载错误
var allJobIdList = JobStorage.Current.GetConnection().GetRecurringJobs().Select(t => t.Id).ToList();
foreach (var jobId in allJobIdList)
{
try
{
HangfireJobHelper.RemoveCronJob(jobId);
_logger.LogInformation($"已清除定时任务: {jobId}");
}
catch (Exception ex)
{
_logger.LogWarning($"清除定时任务 {jobId} 时出错: {ex.Message}");
}
}
// 项目手动选择,周期性邮件
var taskInfoList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend)
.Select(t => new { t.Id, t.Code, TrialCode = t.Trial.TrialCode, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
.ToListAsync();
@ -72,20 +55,6 @@ public class HangfireHostService(IRecurringMessageScheduler _recurringMessageSch
}
// 系统邮件定时任务
var systemTaskInfoList = await _emailNoticeConfigrepository.Where(t => t.EmailCron != string.Empty && t.IsAutoSend)
.Select(t => new { t.Id, t.Code, t.EmailCron, t.BusinessScenarioEnum, })
.ToListAsync();
foreach (var task in systemTaskInfoList)
{
//利用主键作为任务Id
var jobId = $"{task.Id}_({task.BusinessScenarioEnum})";
HangfireJobHelper.AddOrUpdateTimingCronJob(jobId, task.BusinessScenarioEnum, task.EmailCron);
}
//await _recurringMessageScheduler.ScheduleRecurringPublish(new QCImageQuestionSchedule() { CronExpression = "0/3 * * * * ? " }, new MasstransiTestCommand { value = "message at " + DateTime.Now.ToString() });

View File

@ -69,9 +69,9 @@
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.19" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@ -82,9 +82,9 @@
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Email" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.1" />
<PackageReference Include="Serilog.Sinks.Email" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.3" />
</ItemGroup>
<ItemGroup>
@ -110,6 +110,54 @@
<Content Update="Resources\zh-CN.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\downLoad\file.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_IRECIST_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_PCWG3_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\ReportTemplate_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\TumorEvaluation_IRECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\TumorEvaluation_IRECIST1.1_EN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\TumorEvaluation_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_IRECIST_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_PCWG3_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\协和\ReportTemplate_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_IRECIST_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_PCWG3_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\同济\ReportTemplate_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_IRECIST_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_PCWG3_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\ReadReoprtTemplate\医院模板\复旦大学肿瘤附属医院\ReportTemplate_RECIST1.1_CN_V1.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>

View File

@ -275,13 +275,7 @@
<param name="opt"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.UserConfirm(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Contracts.UserConfirmCommand})">
<summary>
用户 签名某个文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.ConfirmReReading(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.ViewModel.ConfirmReReadingCommand},IRaCIS.Core.Application.Service.IVisitTaskService)">
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.ConfirmReReading(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.ViewModel.ConfirmReReadingCommand},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService)">
<summary>
重阅同意
</summary>
@ -318,12 +312,11 @@
<param name="_noneDicomStudyFileRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,System.Boolean,IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.InspectionFile})">
<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="isFullCheck"></param>
<param name="oSSService"></param>
<param name="_inspectionFileRepository"></param>
<returns></returns>

View File

@ -1,7 +1,8 @@
using IRaCIS.Core.API;
using FellowOakDicom.Network;
using FellowOakDicom;
using IRaCIS.Core.API;
using IRaCIS.Core.API.HostService;
using IRaCIS.Core.Application.BusinessFilter;
using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service;
@ -25,6 +26,9 @@ using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using FellowOakDicom.Imaging.NativeCodec;
using FellowOakDicom.Imaging;
using IRaCIS.Core.Application.Contracts;
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
@ -37,11 +41,6 @@ var config = new ConfigurationBuilder()
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
var openSwaggerStr = config["ASPNETCORE_OpenSwagger"];
var isOpenSwagger= openSwaggerStr == null|| openSwaggerStr?.ToLower()=="true";
if (string.IsNullOrWhiteSpace(enviromentName))
{
@ -101,11 +100,12 @@ builder.Services.AddControllers(options =>
options.Filters.Add<UnitOfWorkFilter>();
options.Filters.Add<LimitUserRequestAuthorization>();
options.Filters.Add<TrialGlobalLimitActionFilter>();
options.Filters.Add<RequestDuplicationFilter>();
})
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
builder.Services.AddOptions().Configure<DicomSCPServiceOption>(_configuration.GetSection("DicomSCPServiceConfig"));
// Panda动态WebApi + UnifiedApiResultFilter + 省掉控制器代码
builder.Services.AddDynamicWebApiSetup();
//MinimalAPI
@ -117,13 +117,8 @@ builder.Services.AddAutoMapperSetup();
builder.Services.AddEFSetup(_configuration, enviromentName);
//Http 响应压缩
builder.Services.AddResponseCompressionSetup();
if (isOpenSwagger)
{
//Swagger Api 文档
builder.Services.AddSwaggerSetup();
}
//Swagger Api 文档
builder.Services.AddSwaggerSetup();
//JWT Token 验证
builder.Services.AddJWTAuthSetup(_configuration);
@ -136,11 +131,17 @@ builder.Services.AddFusionCache();
// hangfire 定时任务框架 有界面,更友好~
builder.Services.AddhangfireSetup(_configuration);
//Serilog 日志可视化 LogDashboard日志
//builder.Services.AddLogDashboardSetup();
//Dicom影像渲染图片 跨平台
builder.Services.AddDicomSetup();
builder.Services.AddFellowOakDicom().AddTranscoderManager<NativeTranscoderManager>()
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
.AddImageManager<ImageSharpImageManager>();
//builder.Services.AddDicomSetup();
new DicomSetupBuilder()
.SkipValidation()
.Build();
// 实时应用
builder.Services.AddSignalR();
@ -155,6 +156,7 @@ builder.Services.AddSignalR();
//builder.Services.AddAntiforgery();
#endregion
var app = builder.Build();
@ -221,19 +223,12 @@ app.UseResponseCompression();
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
app.UseStaticFiles();
//LogDashboard
//app.UseLogDashboard("/LogDashboard");
//hangfire
app.UseHangfireConfig(env);
// Swagger
if (isOpenSwagger)
{
SwaggerSetup.Configure(app, env);
}
SwaggerSetup.Configure(app, env);
//serilog 记录请求的用户信息
app.UseSerilogConfig(env);
@ -293,6 +288,13 @@ try
//Log.Logger.Warning($"ContentRootPath——xx{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
#endregion
DicomSetupBuilder.UseServiceProvider(app.Services);
var logger = app.Services.GetService<Microsoft.Extensions.Logging.ILogger<Program>>();
var server = DicomServerFactory.Create<DicomSCPService>(_configuration.GetSection("DicomSCPServiceConfig").GetValue<int>("ServerPort"), userState: app.Services, logger: logger);
app.Run();

View File

@ -16,69 +16,39 @@
"ASPNETCORE_ENVIRONMENT": "Test_IRC"
}
},
"IRaCIS.Test_IRC": {
"Uat_HIR": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC",
"ASPNETCORE_OpenSwagger": "true"
"ASPNETCORE_ENVIRONMENT": "Uat_HIR"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.Test_IRC_PGSQL": {
"Prod_HIR": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Test_IRC_PGSQL"
"ASPNETCORE_ENVIRONMENT": "Prod_HIR"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.Event_IRC": {
"US_HIR": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
"ASPNETCORE_ENVIRONMENT": "US_HIR"
},
"applicationUrl": "http://localhost:6100"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"publishAllPorts": true
},
"IRaCIS.Uat_IRC": {
"Test_HIR": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Uat_IRC"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.Prod_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Prod_IRC"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.US_Uat_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "US_Uat_IRC"
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.US_Prod_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "US_Prod_IRC"
"ASPNETCORE_ENVIRONMENT": "Test_HIR"
},
"applicationUrl": "http://localhost:6100"
}
}
}

View File

@ -1,3 +1,2 @@
{
}

View File

@ -1,15 +0,0 @@
//using LogDashboard;
//using LogDashboard.Authorization;
//namespace IRaCIS.Core.API.Filter
//{
// public class LogDashBoardAuthFilter : ILogDashboardAuthorizationFilter
// {
// //在此可以利用 本系统的UerTypeEnum 判断
// public bool Authorization(LogDashboardContext context)
// {
// return context.HttpContext.User.Identity.IsAuthenticated;
// }
// }
//}

View File

@ -21,6 +21,7 @@ namespace IRaCIS.Core.API
=>
{
opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>

View File

@ -46,6 +46,8 @@ namespace IRaCIS.Core.API
OnMessageReceived = (context) =>
{
if (context.Request.Query.TryGetValue("access_token", out StringValues values))
{
var queryToken = values.FirstOrDefault();

View File

@ -1,6 +1,7 @@
using FellowOakDicom;
using FellowOakDicom.Imaging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.API
{
@ -9,12 +10,14 @@ namespace IRaCIS.Core.API
public static void AddDicomSetup(this IServiceCollection services)
{
new DicomSetupBuilder()
.RegisterServices(s => s.AddFellowOakDicom()
.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
.AddImageManager<ImageSharpImageManager>()
.RegisterServices(s => s.AddFellowOakDicom().AddLogging(config => config.AddConsole())
.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
//.AddImageManager<ImageSharpImageManager>()
)
.SkipValidation()
.Build();
}
}
}

View File

@ -82,12 +82,14 @@ namespace IRaCIS.Core.API
triggerOptions.AddTrigger<UserAddTrigger>();
triggerOptions.AddTrigger<UserLogAfterTrigger>();
triggerOptions.AddTrigger<IdenttiyUserRoleInfoTrigger>();
triggerOptions.AddTrigger<UserLogAfterTrigger>();
});
});

View File

@ -1,25 +0,0 @@

//using LogDashboard;
//using Microsoft.Extensions.DependencyInjection;
//namespace IRaCIS.Core.API
//{
// public static class LogDashboardSetup
// {
// public static void AddLogDashboardSetup(this IServiceCollection services)
// {
// //IIS 配置虚拟路径部署会出现IIS静态文件404
// services.AddLogDashboard(opt =>
// {
// //opt.PathMatch = "/api/LogDashboard";
// opt.PathMatch = "/LogDashboard";
// //opt.AddAuthorizationFilter(new LogDashboardBasicAuthFilter("admin", "zhizhun2018"));
// //opt.AddAuthorizationFilter(new LogDashBoardAuthFilter());
// });
// }
// }
//}

View File

@ -126,51 +126,6 @@ namespace IRaCIS.Core.API
}
public class DateOnlyUniversalJsonConverter : JsonConverter
{
private readonly string _format;
public DateOnlyUniversalJsonConverter(string format = "yyyy-MM-dd")
{
_format = format;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateOnly) || objectType == typeof(DateOnly?);
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteValue(""); // null -> 空字符串
return;
}
var date = (DateOnly)value;
if (date == default)
{
writer.WriteValue(""); // default(DateOnly) -> 空字符串
}
else
{
writer.WriteValue(date.ToString(_format));
}
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var str = reader.TokenType == JsonToken.Null ? null : reader.Value?.ToString();
if (string.IsNullOrWhiteSpace(str) || !DateOnly.TryParse(str, out var date))
{
return objectType == typeof(DateOnly?) ? null : default(DateOnly);
}
return date;
}
}
#region 废弃

View File

@ -49,8 +49,6 @@ namespace IRaCIS.Core.API
//必须放在后面
options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
//options.SerializerSettings.Converters.Add(new DateOnlyUniversalJsonConverter("yyyy-MM-dd"));
})
.AddControllersAsServices()//动态webApi属性注入需要

View File

@ -25,17 +25,16 @@ namespace IRaCIS.Core.API
.MinimumLevel.Override("MassTransit", LogEventLevel.Warning)
//https://github.com/ZiggyCreatures/FusionCache/blob/main/docs/Logging.md
.MinimumLevel.Override("ZiggyCreatures.Caching.Fusion", LogEventLevel.Warning)
// Filter out ASP.NET Core infrastructre logs that are Information and below 日志太多了 一个请求 记录好几条
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Warning)
.MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
.Enrich.FromLogContext()
.Enrich.FromLogContext()
.Filter.ByExcluding(logEvent => logEvent.Properties.ContainsKey("RequestPath") && logEvent.Properties["RequestPath"].ToString().Contains("/health"))
.WriteTo.Console()
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day,retainedFileCountLimit:60);
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day);
#region 根据环境配置是否打开错误发送邮件通知

View File

@ -1,5 +1,6 @@
using IP2Region.Net.Abstractions;
using IP2Region.Net.XDB;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.BackGroundJob;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service;
@ -28,13 +29,12 @@ public static class ServiceCollectionSetup
services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
services.AddOptions().Configure<IRCEncreptOption>(_configuration.GetSection("EncrypteResponseConfig"));
services.AddOptions().Configure<RequestDuplicationOptions>(_configuration.GetSection("RequestDuplicationOptions"));
services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
services.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
services.Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
//ת<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȡ<EFBFBD><C8A1>ʵIP
//转发头设置 获取真实IP
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
@ -52,7 +52,7 @@ public static class ServiceCollectionSetup
services.AddScoped<IObtainTaskAutoCancelJob, ObtainTaskAutoCancelJob>();
// ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Service <20><>β<EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>
// 注册以Service 结尾的服务
services.Scan(scan => scan
.FromAssemblies(typeof(BaseService).Assembly)
.AddClasses(classes => classes.Where(t => t.Name.Contains("Service")))
@ -71,23 +71,23 @@ public static class ServiceCollectionSetup
#endregion
// MediatR <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD> <20>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD> ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>handler<65><72>Ӧ<EFBFBD><D3A6>ϵ
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
#region <EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#region 历史废弃配置
//builder.Services.AddMemoryCache();
////<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
////上传限制 配置
//builder.Services.Configure<FormOptions>(options =>
//{
// options.MultipartBodyLengthLimit = int.MaxValue;
// options.ValueCountLimit = int.MaxValue;
// options.ValueLengthLimit = int.MaxValue;
//});
//IP <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD>
//IP 限流 可设置白名单 或者黑名单
//services.AddIpPolicyRateLimitSetup(_configuration);
// <EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ
// 用户类型 策略授权
//services.AddAuthorizationPolicySetup(_configuration);
#endregion
}
@ -95,25 +95,25 @@ public static class ServiceCollectionSetup
}
#region Autofac <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#region Autofac 废弃
//public class AutofacModuleSetup : Autofac.Module
//{
// protected override void Load(ContainerBuilder containerBuilder)
// {
// #region byzhouhang 20210917 <EFBFBD>˴<EFBFBD>ע<EFBFBD><EFBFBD>Ͳִ<EFBFBD> <20><><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>Domain<69><6E> <20><>Infra.EFcore <20><><EFBFBD><EFBFBD> <20>յIJִ<C4B2><D6B4>ӿڶ<D3BF><DAB6><EFBFBD><EFBFBD> <20>ִ<EFBFBD><D6B4>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
// #region byzhouhang 20210917 此处注册泛型仓储 可以减少Domain层 和Infra.EFcore 两层 空的仓储接口定义和 仓储文件定义
// containerBuilder.RegisterGeneric(typeof(Repository<>))
// .As(typeof(IRepository<>)).InstancePerLifetimeScope();//ע<EFBFBD><EFBFBD>Ͳִ<EFBFBD>
// .As(typeof(IRepository<>)).InstancePerLifetimeScope();//注册泛型仓储
// containerBuilder.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
// #endregion
// #region ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>autofac <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ȡ https://www.cnblogs.com/xwhqwer/p/15320838.html
// #region 指定控制器也由autofac 来进行实例获取 https://www.cnblogs.com/xwhqwer/p/15320838.html
// //<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
// //获取所有控制器类型并使用属性注入
// containerBuilder.RegisterAssemblyTypes(typeof(BaseService).Assembly)
// .Where(type => typeof(IDynamicWebApi).IsAssignableFrom(type))
// .PropertiesAutowired();
@ -129,7 +129,7 @@ public static class ServiceCollectionSetup
// //containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
// //ע<EFBFBD><EFBFBD>hangfire<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
// //注册hangfire任务 依赖注入
// containerBuilder.RegisterType<ObtainTaskAutoCancelJob>().As<IObtainTaskAutoCancelJob>().InstancePerDependency();
// }

View File

@ -16,31 +16,32 @@ namespace IRaCIS.Core.API;
public enum SwaggerVersion
{
[Description("文件记录(FileRecord)")]
FileRecord = -1,
[Description("HIR修改")]
HIR = -1,
[Description("医生模块(Reviewer)")]
[Description("医生模块")]
Reviewer = 1,
[Description("项目模块(Trial)")]
[Description("项目模块")]
Trial = 2,
[Description("入组模块(Enroll)")]
[Description("入组模块")]
Enroll = 3,
[Description("工作量模块(Workload)")]
[Description("工作量模块")]
Workload = 4,
[Description("通用信息获取(Common)")]
[Description("通用信息获取")]
Common = 5,
[Description("机构信息模块(Institution)")]
[Description("机构信息模块")]
Institution = 6,
[Description("统计模块(DashboardStatistics)")]
[Description("统计模块")]
DashboardStatistics = 7,
[Description("财务模块(Financial)")]
[Description("财务模块")]
Financial = 8,
[Description("管理模块(Management)")]
Management =9,
[Description("影像模块(Image)")]
Image =10,
[Description("读片模块(Reading)")]
Reading =11
[Description("管理模块")]
Management = 9,
[Description("影像模块")]
Image = 10,
[Description("读片模块")]
Reading = 11
};

View File

@ -27,8 +27,7 @@ namespace IRaCIS.Core.API
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
{
SchemaName = "dbo",
}).UseRecommendedSerializerSettings();
// 移除 UseSimpleAssemblyNameTypeSerializer() 以避免类型加载问题
}).UseRecommendedSerializerSettings().UseSimpleAssemblyNameTypeSerializer();
}

View File

@ -1,85 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "tl-med-irc-event-store",
"ViewEndpoint": "https://tl-med-irc-event-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endpoint": "http://192.168.3.68",
"port": "8001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "uat@extimaging.com",
"FromName": "UAT_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.event.extimaging.com/login",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -0,0 +1,67 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "hir-oss.tres.extimaging.com",
"Port": "443",
"UseSSL": true,
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"BucketName": "hir-images",
"ViewEndpoint": "https://hir-oss.tres.extimaging.com/hir-images"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=mssql,1433;Database=HIR_Prod;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
"Hangfire": "Server=mssql,1433;Database=HIR_Prod_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"AESKey": "HIR_System_AES_Key_Info",
"CmoveIntervalMinutes": 1,
"CmoveInstanceIntervalMinutes": 1,
//
"IsNeedChangePassWord": true,
//
"ChangePassWordDays": 1000,
"OpenImageShare": true
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test@extimaging.com",
"FromName": "BCTOP",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "https://bctop.tres.extimaging.com/login",
"CompanyName": "BCTOP",
"CompanyNameCN": "BCTOP",
"CompanyShortName": "BCTOP",
"CompanyShortNameCN": "BCTOP",
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"ThirdSearchPacsAE": "XCPACS",
"ThirdCallningAE": "LYAE",
"CalledAEList": [
"HIRSCUAE",
"HIRSCPAE"
],
"ServerPort": 11112
}
}

View File

@ -1,93 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"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",
"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",
"port": "8001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "irc@extimaging.com",
"FromName": "IRC Imaging System",
"AuthorizationCode": "ExtImg@2022",
"SiteUrl": "http://irc.extimaging.com/login",
"SystemShortName": "IRC",
"OrganizationName": "ExtImaging",
"OrganizationNameCN": "ExtImaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.193.237"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -0,0 +1,62 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "192.168.40.99",
"Port": "9000",
"UseSSL": false,
"AccessKeyId": "Jnywl9aIw83yewZIJKod",
"SecretAccessKey": "N83bTzoJGkg4OLW8x54IZRwwSvdxcdYi9UZ2BYII",
"BucketName": "tj-hir",
"ViewEndpoint": "http://192.168.40.99:9000/tj-hir"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR;User ID=sa;Password=xc_123456;TrustServerCertificate=true",
"Hangfire": "Server=192.168.40.98,1433;Database=TJ_Prod_HIR_Hangfire;User ID=sa;Password=xc_123456;TrustServerCertificate=true"
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": false,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"AESKey": "HIR_System_AES_Key_Info",
"CmoveIntervalMinutes": 1,
"CmoveInstanceIntervalMinutes": 1
},
"SystemHospitalConfig": {
"HospitalCode": "EI",
"HospitalLogoPath": "/System/GeneralDocuments/1716453306898_图片2.png",
"TrialKeepCount": 60,
"HospitalName": "上海展影医疗科技有限公司",
"HospitalAliasName": "展影医疗",
"Country": "中国",
"City": "上海",
"Province": "上海",
"Address": "上海市杨浦区国泰路复旦科技园",
"Phone": "021-60702575",
"IsCanConnectInternet": false
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test-study@extimaging.com",
"FromName": "Test_HIR",
"AuthorizationCode": "zhanying123",
"SiteUrl": "http://hir.test.extimaging.com/login"
}
}

View File

@ -0,0 +1,71 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "hir-oss.test.extimaging.com",
"Port": "443",
"UseSSL": true,
//"endPoint": "106.14.89.110",
//"port": "9001",
//"useSSL": false,
"AccessKeyId": "fbStsVYCIPKHQneeqMwD",
"SecretAccessKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
"BucketName": "hir-test",
//"viewEndpoint": "https://hir.test.extimaging.com/oss/hir-test"
"ViewEndpoint": "https://hir-oss.test.extimaging.com/hir-test"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"AESKey": "HIR_System_AES_Key_Info",
"CmoveIntervalMinutes": 1,
"CmoveInstanceIntervalMinutes": 1,
//
"IsNeedChangePassWord": true,
//
"ChangePassWordDays": 1000,
"OpenImageShare": true
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test-study@extimaging.com",
"FromName": "Test_HIR",
"AuthorizationCode": "zhanying123",
"SiteUrl": "http://hir.test.extimaging.com/login",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"ThirdSearchPacsAE": "XCPACS",
"ThirdCallningAE": "LYAE",
"CalledAEList": [
"HIRSCUAE",
"HIRSCPAE"
],
"ServerPort": 11112
}
}

View File

@ -1,181 +1,103 @@
{
//
"Logging": {
//
"LogLevel": {
//
"Default": "Information",
//
"Microsoft": "Warning",
// ASP.NET Core
"Microsoft.Hosting.Lifetime": "Information"
}
},
//
"ConnectionStrings": {
//
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
// Hangfire
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
//
"ObjectStoreService": {
// 使
"ObjectStoreUse": "AliyunOSS",
//
"AliyunOSS": {
// OSS Region ID
"RegionId": "cn-shanghai",
// OSS 访
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
// OSS 访
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
// OSS 访 ID
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
// OSS 访 Secret
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
// OSS ARN
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
// OSS Bucket
"BucketName": "zy-irc-test-store",
// OSS 访
"ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com",
// OSS
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
// OSS 访
"DurationSeconds": 7200,
// OSS
"PreviewEndpoint": "https://test-oss.test.extimaging.com"
"DurationSeconds": 7200
},
// MinIO
"MinIO": {
// MinIO 访
"EndPoint": "hir-oss.test.extimaging.com",
// MinIO
"Port": "443",
// 使 SSL
"UseSSL": true,
// MinIO ARN
"AccessKey": "fbStsVYCIPKHQneeqMwD",
// MinIO 访
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
// MinIO BucketName
"BucketName": "irc-test",
// MinIO 访
"ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
},
// AWS S3
"AWS": {
// AWS S3 Region
"Region": "us-east-1",
// AWS S3 访
"EndPoint": "s3.us-east-1.amazonaws.com",
// 使 SSL
"UseSSL": true,
// AWS S3 ARN
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
// AWS S3 访 ID
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
// AWS S3 访 Secret
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
// AWS S3 Bucket
"BucketName": "ei-med-s3-lili-uat-store",
// AWS S3 访
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
// AWS S3
"DurationSeconds": 7200
}
},
//
"BasicSystemConfig": {
//
"OpenUserComplexPassword": false,
//
"OpenSignDocumentBeforeWork": false,
//
"OpenLoginLimit": false,
//
"LoginMaxFailCount": 5,
//
"LoginFailLockMinutes": 1,
//
"AutoLoginOutMinutes": 10,
// MFA
"OpenLoginMFA": false,
//
"ContinuousReadingTimeMin": 120,
//
"ReadingRestTimeMin": 10,
//
"IsNeedChangePassWord": true,
//
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 2,
//
"OpenTrialRelationDelete": true,
// PDF
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf",
//MFA
"UserMFAVerifyMinutes": 1440
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 1,
"AutoLoginOutMinutes": 1,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf"
},
//
"SystemEmailSendConfig": {
// SMTP
"Port": 465,
// SMTP
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
//
"FromEmail": "test@extimaging.com",
//
"FromName": "Test IRC Imaging System",
// SMTP
"FromName": "Test_IRC",
"AuthorizationCode": "SHzyyl2021",
// 访
"SiteUrl": "http://irc.test.extimaging.com/login",
//
"SystemShortName": "IRC",
//
"OrganizationName": "ExtImaging",
//
"OrganizationNameCN": "ExtImaging",
//
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
//
"CompanyNameCN": "上海展影医疗科技有限公司",
//
"CompanyShortName": "Extensive Imaging",
//
"CompanyShortNameCN": "展影医疗",
//
"IsEnv_US": false,
//
"IsOpenErrorNoticeEmail": false,
//
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
//
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
"ErrorNoticeEmailList": ["872297557@qq.com"]
},
// PACS
"SystemPacsConfig": {
// PACS
"Port": "11113",
// PACSIP
"IP": "106.14.89.110"
},
//
"RequestDuplicationOptions": {
//
"IsEnabled": true,
//
"DuplicationWindowMs": 200,
//
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -1,104 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"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": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"internalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-test-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": {
"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/"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 1,
"AutoLoginOutMinutes": 1,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "test@extimaging.com",
"FromName": "Test_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.test.extimaging.com/login",
"OrganizationName": "ExtImaging",
"OrganizationNameCN": "ExtImaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗"
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "106.14.89.110"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -0,0 +1,68 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "hir-minio.uat.elevateimaging.ai",
"Port": "443",
"UseSSL": true,
"AccessKeyId": "7rvVIHs7D6pbyscRcJhz",
"SecretAccessKey": "DQsCQldHFL3QRjlnaLWV7oM4E9PtsO21QPC2h9BD",
"BucketName": "hir-us",
//"viewEndpoint": "https://hir.test.extimaging.com/oss/hir-test"
"ViewEndpoint": "https://hir-minio.uat.elevateimaging.ai/hir-us"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=3.226.182.187,1435;Database=US_HIR;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=3.226.182.187,1435;Database=US_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"AESKey": "HIR_System_AES_Key_Info",
"CmoveIntervalMinutes": 1,
"CmoveInstanceIntervalMinutes": 1,
//
"IsNeedChangePassWord": true,
//
"ChangePassWordDays": 1000,
"OpenImageShare": true
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "uat-study@extimaging.com",
"FromName": "Uat_HIR",
"AuthorizationCode": "zhanying123",
"SiteUrl": "https://hir.uat.elevateimaging.ai/login",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"ThirdSearchPacsAE": "XCPACS",
"ThirdCallningAE": "LYAE",
"CalledAEList": [
"HIRSCUAE",
"HIRSCPAE"
],
"ServerPort": 11112
}
}

View File

@ -1,101 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-mssql-prod,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-prod,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": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": true,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 1,
"OpenTrialRelationDelete": false,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"Imap": "imap-mail.outlook.com",
"ImapPort": 993,
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi System",
"AuthorizationCode": "Q#669869497420ul",
"SystemShortName": "LiLi",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login",
"IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
},
"SystemPacsConfig": {
"Port": "104",
"IP": "44.210.231.169"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -1,108 +0,0 @@
{
"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,
// 1 Elevate 2 Extensive
"TemplateType": 1,
"OpenLoginMFA": true,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"Imap": "imap-mail.outlook.com",
"ImapPort": 993,
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi System",
"AuthorizationCode": "Q#669869497420ul",
"SystemShortName": "LiLi",
"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,
"IsOpenErrorNoticeEmail": false,
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -1,107 +0,0 @@
{
"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,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": true,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 1,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"Imap": "imap-mail.outlook.com",
"ImapPort": 993,
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi System",
"AuthorizationCode": "Q#669869497420ul",
"SystemShortName": "LiLi",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.uat.elevateimaging.ai/login",
"IsEnv_US": true,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
},
"SystemPacsConfig": {
"Port": "104",
"IP": "3.226.182.187"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -0,0 +1,69 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"MinIO": {
"EndPoint": "hir-oss.uat.extimaging.com",
"Port": "443",
"UseSSL": true,
//"endPoint": "106.14.89.110",
//"port": "9001",
//"useSSL": false,
"AccessKeyId": "L6owzRVeDJJw3PcRmK2c",
"SecretAccessKey": "2XvFDYSH7EyHQNtpDCgk4efgdsdarQmRKgx1LlOI",
"BucketName": "hir-uat",
"ViewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HIR_New;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HIR_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": false,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"AESKey": "HIR_System_AES_Key_Info",
"CmoveIntervalMinutes": 1,
"CmoveInstanceIntervalMinutes": 1,
//
"IsNeedChangePassWord": true,
//
"ChangePassWordDays": 1000,
"OpenImageShare": true
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test-study@extimaging.com",
"FromName": "Test_HIR",
"AuthorizationCode": "zhanying123",
"SiteUrl": "http://hir.test.extimaging.com/login",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"DicomSCPServiceConfig": {
"IsSupportThirdService": true,
"ThirdSearchPacsAE": "XCPACS",
"ThirdCallningAE": "LYAE",
"CalledAEList": [
"HIRSCUAE",
"HIRSCPAE"
],
"ServerPort": 11112
}
}

View File

@ -1,115 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"RegionId": "cn-shanghai",
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
"BucketName": "tl-med-irc-uat-store",
"ViewEndpoint": "https://tl-med-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai",
"DurationSeconds": 7200
},
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
},
"AWS": {
"Region": "us-east-1",
"EndPoint": "s3.us-east-1.amazonaws.com",
"UseSSL": true,
"RoleArn": "arn:aws:iam::471112624751:role/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
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": true,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 120,
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 1 Elevate 2 Extensive
"TemplateType": 2,
//MFA
"UserMFAVerifyDays": 1
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"Imap": "imap.qiye.aliyun.com",
"ImapPort": 993,
"FromEmail": "uat@extimaging.com",
"FromName": "Uat IRC Imaging System",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.uat.extimaging.com/login",
"SystemShortName": "IRC",
"OrganizationName": "ExtImaging",
"OrganizationNameCN": "ExtImaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",
"CompanyShortNameCN": "展影医疗",
"IsEnv_US": false,
"IsOpenErrorNoticeEmail": false,
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
},
"SystemPacsConfig": {
"Port": "11113",
"IP": "101.132.253.119"
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

View File

@ -3,7 +3,7 @@
"SecurityKey": "ShangHaiZhanYing_SecurityKey_SHzyyl@2021",
"Issuer": "Extimaging",
"Audience": "EICS",
"TokenExpireMinute": "10080"//7
"TokenExpireMinute": "10080" //7
},
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
@ -74,12 +74,5 @@
"redirect_uri": "https://oauthlogin.net/oauth/githubcallback",
"scope": "repo"
}
},
"RequestDuplicationOptions": {
"IsEnabled": true,
"DuplicationWindowMs": 200,
"CacheTimeSeconds": 5,
"ExcludedPaths": [
]
}
}

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