Compare commits

...

265 Commits

Author SHA1 Message Date
zhangmu aa7125abd1 Merge pull request '专家评审子系统' (#320) from durian/forgeplus-react:expert_review into dev_military_osredm 2021-12-16 12:00:27 +08:00
谢思 bf58961a23 专家评审子系统 2021-12-16 10:54:06 +08:00
zhangmu a560159a63 Merge pull request '初始化专家评审模块' (#317) from tongChong/forgeplus-react:dev_military_osredm into dev_military_osredm 2021-12-14 13:31:29 +08:00
何童崇 3ecae5ba43 初始化专家评审模块 2021-12-14 13:27:27 +08:00
baladiwei 846a24aef4 Merge pull request 'merge after release' (#309) from pre_dev_military into dev_military 2021-12-08 13:48:40 +08:00
baladiwei 955eed9232 Merge pull request '修改创客删除与恢复' (#308) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-12-08 13:47:48 +08:00
何童崇 1bad39e83a 修改创客删除与恢复 2021-11-25 15:59:04 +08:00
何童崇 c9e7da7df3 优化调用地址引用 2021-11-25 11:40:57 +08:00
何童崇 7f0b770dca 修改创客,优化创客调用Java发送请求的接口 2021-11-25 11:26:59 +08:00
baladiwei 70536036e1 Merge pull request 'merge after release' (#283) from pre_dev_military into dev_military 2021-11-25 09:33:40 +08:00
baladiwei 0f92ff94a0 Merge pull request '修改公告页面bug' (#280) from tongChong/forgeplus-react:hotfix_api_address into pre_dev_military 2021-11-23 14:46:40 +08:00
何童崇 6507c87bc8 Merge branch 'dev_military' of https://git.trustie.net/Gitlink/forgeplus-react into hotfix_api_address 2021-11-22 15:13:36 +08:00
何童崇 b423e4b7e7 修改公告页面bug 2021-11-22 14:58:34 +08:00
baladiwei 938be1da55 Merge pull request 'merge after release' (#278) from pre_dev_military into dev_military 2021-11-22 11:28:48 +08:00
何童崇 162fd200a5 修改创客管理员发布的问题 2021-11-11 10:40:57 +08:00
baladiwei d9bd0387db Merge pull request '修改API调用指向路径及发布任务时的判断逻辑' (#254) from tongChong/forgeplus-react:hotfix_api_address into pre_dev_military 2021-11-10 15:04:28 +08:00
何童崇 c0cfe12db4 修改发布任务判断逻辑 2021-11-10 14:57:42 +08:00
何童崇 c3ecbe1f97 修改调用路径后未加跨域参数的问题 2021-11-10 10:39:08 +08:00
何童崇 a59a8c3693 修改指向路径 2021-11-10 09:33:12 +08:00
baladiwei 97f62a5684 Merge pull request 'pre-release merge' (#104) from pre_dev_military into dev_military 2021-09-30 17:46:56 +08:00
baladiwei e74a3b6a95 Merge pull request '解决合并时未先pull源代码合并记录的问题' (#103) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-09-30 17:46:00 +08:00
何童崇 38878183d5 Merge branch 'dev_military' of https://git.trustie.net/Gitlink/forgeplus-react into dev-jk-maker 2021-09-30 17:40:05 +08:00
baladiwei 0e0c13f1a4 Merge pull request '修改创客延期和项目侧边栏' (#100) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-09-30 17:35:59 +08:00
何童崇 a667a32de0 修改任务状态展示问题 2021-09-30 17:06:33 +08:00
何童崇 230e597787 修改延期的问题 2021-09-30 16:50:19 +08:00
何童崇 f0ea3a53c4 修改延期的问题 2021-09-30 16:08:48 +08:00
何童崇 51a4680481 优化延期、侧边导航 2021-09-30 11:49:44 +08:00
baladiwei 61a4882e58 Merge pull request '修改创客的调用' (#81) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-09-27 11:04:38 +08:00
何童崇 148e8f91eb 上传佐证材料查询参数修改 2021-09-27 10:53:05 +08:00
baladiwei 8f52a091fa Merge pull request '查看加密公告-电话验证错误提示语句' (#80) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-09-27 10:45:43 +08:00
tongChong 62eabdf7c0 Merge pull request '修改加密公告电话验证的var' (#31) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-09-27 10:42:01 +08:00
谢思 d5490d5e71 修改加密公告电话验证的var 2021-09-27 10:28:47 +08:00
baladiwei cef374c52d Merge pull request '查看加密公告-电话验证错误提示语句' (#79) from tongChong/forgeplus-react:dev_military_notice into dev_military 2021-09-27 10:26:32 +08:00
谢思 7be60d3140 Merge branch 'dev_military' of https://git.trustie.net/Gitlink/forgeplus-react into dev_military_notice_xiesi 2021-09-27 10:18:29 +08:00
durian feafa5b6f3 Merge pull request '查看加密公告-电话验证错误提示语句' (#30) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-09-27 10:14:06 +08:00
谢思 2dd6ed108f 查看加密公告-电话验证错误提示语句 2021-09-27 10:11:59 +08:00
baladiwei 969323fdde Merge pull request '修改跳转的小bug' (#78) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-09-27 09:38:34 +08:00
何童崇 a73b4ff79a 修改跳转的小bug 2021-09-26 20:39:46 +08:00
baladiwei 16ca2a359e Merge pull request 'pre-release merge' (#77) from pre_dev_military into dev_military 2021-09-26 18:42:07 +08:00
baladiwei 444d954e72 Merge pull request '新增创客空间功能' (#76) from tongChong/forgeplus-react:dev-jk-maker into pre_dev_military 2021-09-26 18:41:08 +08:00
何童崇 6fc31c0bb8 拆分,不同功能调用不同的API,暂时用个简易版后续优化 2021-09-26 18:31:01 +08:00
何童崇 cf73f72e19 Merge branch 'pre_dev_military' of https://git.trustie.net/Gitlink/forgeplus-react into dev-jk-maker 2021-09-26 15:11:39 +08:00
baladiwei 745a25a003 Merge pull request '查看加密公告--电话验证' (#75) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-09-26 15:11:01 +08:00
tongChong b080df1449 Merge pull request '查看加密信息-电话验证' (#28) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-09-26 14:28:59 +08:00
何童崇 0aa2a4aec3 允许跨域传cookie 2021-09-26 14:23:26 +08:00
何童崇 4dc1c4c814 合并公告的修改 2021-09-26 10:53:20 +08:00
何童崇 ddc576b054 上传创客issue修改 2021-09-26 10:25:06 +08:00
谢思 caef7a0ab3 查看加密公告--电话验证 2021-09-22 14:59:09 +08:00
谢思 85f0578302 查看加密公告--电话验证 2021-09-22 14:55:02 +08:00
baladiwei bff55b6810 Merge pull request '修改指向路径' (#69) from tongChong/forgeplus-react:dev_military_notice into dev_military 2021-09-17 16:33:19 +08:00
baladiwei 01f71bca87 Merge pull request '修改指向路径' (#70) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-09-17 16:33:06 +08:00
何童崇 d3cea0ff3b 修改指向路径 2021-09-17 16:22:35 +08:00
baladiwei be6e3d273b Merge pull request '公告加密前端代码' (#68) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-09-17 16:02:25 +08:00
何童崇 6b8f1e3749 修改导航条高亮 2021-09-17 15:13:54 +08:00
tongChong b5e145b4b5 Merge pull request '公告优化' (#25) from durian/forgeplus-react:hotfix-hot-xiesi into dev_military_notice 2021-09-17 14:14:46 +08:00
何童崇 15b63be594 上传公告修改 2021-09-17 14:13:59 +08:00
谢思 032127bef6 公告优化 2021-09-17 13:26:06 +08:00
谢思 f4f843a7b9 通知中心优化 2021-09-17 10:27:20 +08:00
何童崇 4cf8357463 修改调用路径 2021-09-16 16:57:53 +08:00
何童崇 0ff1367ad8 上传公告修改 2021-09-16 16:51:31 +08:00
何童崇 0e44cbbcdd 修改因后端返回结构带来的数据判定问题 2021-09-15 09:37:05 +08:00
tongChong e736591a4f Merge pull request '将对左侧导航栏的修改提交至公告' (#16) from hotfix-tab into dev_military_notice 2021-09-14 17:33:11 +08:00
tongChong d15900fc7c Merge pull request '公告页面banner图' (#13) from durian/forgeplus-react:hotfix-hot-xiesi into hotfix-tab 2021-09-14 09:40:38 +08:00
谢思 4f87542f1f 公告页面banner图 2021-09-13 14:50:51 +08:00
何童崇 94ee3601c9 修改多个issue,修改管理页路由组件引入方式 2021-09-09 16:35:19 +08:00
tongChong 19d09c7901 Merge pull request '红山开源的公告页面再改版' (#10) from durian/forgeplus-react:hotfix-hot-xiesi into hotfix-tab 2021-09-09 09:46:10 +08:00
谢思 3b29605321 公告二次改版 2021-09-07 09:09:35 +08:00
何童崇 6e82862307 修改创客空间微调及代理功能 2021-09-01 09:08:19 +08:00
tongChong 700ac5862e Merge pull request '修改创客空间' (#7) from durian/forgeplus-react:dev-jk-maker-xiesi into dev-jk-maker 2021-08-31 15:59:47 +08:00
谢思 4ccab2ed4f issues非按钮复杂判断修改 2021-08-31 15:51:58 +08:00
何童崇 3f3299a3b8 合并公告修改代码 2021-08-26 15:31:32 +08:00
baladiwei b73a38351b Merge pull request 'pre-release merge' (#26) from pre_dev_military into dev_military 2021-08-26 14:55:37 +08:00
baladiwei 586c5d6d1d Merge pull request '优化未查询到无数据时公告的展示' (#25) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-08-26 14:53:24 +08:00
tongChong 819772d180 Merge pull request '红山开源的公告页面' (#6) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-08-26 13:32:24 +08:00
谢思 e733f1886e 红山开源公告页面暂无数据(居中样式) 2021-08-26 13:28:35 +08:00
tongChong 86d2442958 Merge pull request '红山开源的公告页面' (#5) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-08-26 11:50:51 +08:00
谢思 b7fc83edf9 公告数据展示 2021-08-26 10:28:15 +08:00
tongChong 74325b5dc7 Merge pull request '红山开源的公告页面' (#4) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-08-25 09:48:08 +08:00
xiesi a25959bfa0 修改红山开源公告页面无数据展示效果 2021-08-25 09:33:06 +08:00
baladiwei fe72be2f30 Merge pull request 'pre-release' (#23) from pre_dev_military into dev_military 2021-08-24 17:34:03 +08:00
baladiwei 4d41f44100 Merge pull request '公告新增2个类型' (#22) from tongChong/forgeplus-react:dev_military_notice into pre_dev_military 2021-08-24 17:14:00 +08:00
tongChong afa839e0b1 Merge pull request '红山开源的公告页面' (#3) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-08-24 13:59:21 +08:00
xiesi 83d59a2e64 修改公告详情页面的公告类型 2021-08-24 13:46:00 +08:00
tongChong 758f4267ed Merge pull request '红山开源的公告页面' (#2) from durian/forgeplus-react:dev_military_notice_xiesi into dev_military_notice 2021-08-24 13:29:17 +08:00
xiesi 38948a84cd 修改红山开源公告数据展示部分 2021-08-24 13:05:29 +08:00
xiesi 51d739f4a0 修改公告导航菜单 2021-08-24 11:51:31 +08:00
tongChong 706830928e 修改公告页面左侧导航栏-谢思
修改公告页面左侧导航栏-谢思
2021-08-23 14:40:16 +08:00
xiesi 8dc08c3992 红山开源的公告页面 2021-08-23 14:18:11 +08:00
何童崇 70ec86569f 修改延期的搜索 2021-08-11 09:24:22 +08:00
何童崇 00b41844bb 修改搜索回到第一页的问题 2021-08-10 17:32:31 +08:00
何童崇 81c93d2580 修改延期代码 2021-08-10 16:44:24 +08:00
何童崇 a87e55103c 修改跳转路由 2021-08-10 14:36:39 +08:00
何童崇 05101c5e32 上传延期列表及操作 2021-08-10 14:17:33 +08:00
何童崇 e72b3e687f 修改路由bug 2021-08-06 16:23:14 +08:00
何童崇 f25a52622d 上传issue修改 2021-08-05 17:46:48 +08:00
何童崇 f5fa216b23 修改issue 2021-08-04 21:48:21 +08:00
何童崇 a57b96a1b8 修改时间bug 2021-08-04 15:59:14 +08:00
何童崇 8efbea44ab 修改延期时间显示 2021-08-04 13:52:41 +08:00
何童崇 fa80b5d1df 解决因为热更新导致的table警告问题 2021-07-27 09:22:10 +08:00
何童崇 6c95ff98f4 修改bug,优化代码 2021-07-26 16:15:55 +08:00
何童崇 cb7170a87c 合并代码 2021-07-19 14:01:05 +08:00
何童崇 7757e4b6b7 修改bug 2021-07-19 13:43:58 +08:00
何童崇 cad9a4fc3a 修改bug 2021-07-16 11:11:20 +08:00
何童崇 dc20d3e270 修改bug,新增管理路由 2021-07-16 11:11:17 +08:00
何童崇 4503e1b176 上传修改bug 2021-07-16 11:10:54 +08:00
何童崇 91fe328eaf 增加管理员统筹所有任务的列表 2021-07-16 11:09:46 +08:00
何童崇 8d9d5c3ce3 修改bug 2021-07-16 11:09:06 +08:00
何童崇 a2aa344e31 修改bug 2021-07-16 11:08:28 +08:00
何童崇 981e199273 修改bug 2021-07-16 11:08:26 +08:00
何童崇 b6d6309c3c 增加上传支付凭证,修改bug 2021-07-16 11:07:42 +08:00
何童崇 16aac3b835 修改bug 2021-07-16 11:07:16 +08:00
何童崇 bdf3a8e72a 修改bug 2021-07-16 11:06:28 +08:00
何童崇 507976bf10 修改bug 2021-07-16 11:05:50 +08:00
何童崇 b6c2c66321 上传协议部分及bug修改 2021-07-16 11:04:41 +08:00
何童崇 0b7fbe564c 对接上传协议及确认支付 2021-07-16 11:04:41 +08:00
何童崇 ce958f3369 修改bug 2021-07-16 11:04:41 +08:00
何童崇 0e176d9334 修改bug 2021-07-16 11:04:41 +08:00
何童崇 3608b7b712 修改bug 2021-07-16 11:04:35 +08:00
何童崇 b9888a81f6 修改bug 2021-07-16 11:03:28 +08:00
何童崇 0bb6ec51c2 上传申诉材料审核bug 2021-07-16 11:03:16 +08:00
何童崇 7d2c90dfd1 上传申诉材料审核及修改成果对接代码样式 2021-07-16 11:02:57 +08:00
何童崇 66c5f09813 上传申诉材料审核及修改成果对接代码 2021-07-16 11:02:55 +08:00
何童崇 a4d38f8c86 新增佐证上传与审核 2021-07-16 11:02:37 +08:00
何童崇 21a3c54754 修改BUG增加审核 2021-07-16 11:02:00 +08:00
何童崇 4493711521 增加成果审核页面 2021-07-16 11:00:37 +08:00
何童崇 76b23f88db 修复成果提交时的bug,联调我是创客 2021-07-16 11:00:18 +08:00
何童崇 bca9499844 上传成果修改 2021-07-16 10:59:24 +08:00
何童崇 3137048aed 添加成果内容 2021-07-16 10:58:42 +08:00
何童崇 62b5d86082 修改需求的部分bug及对接成果 2021-07-16 10:58:16 +08:00
何童崇 7a472651f1 修改了需求部分bug 2021-07-16 10:57:24 +08:00
何童崇 99c90295c0 上传我的成果静态页面 2021-07-16 10:57:22 +08:00
何童崇 d7fd642f7f 上传我的需求及 2021-07-16 10:56:55 +08:00
何童崇 97bc41e771 上传创客新增任务及列表代码 2021-07-16 10:56:13 +08:00
何童崇 6156d98af2 新增创客空间 2021-07-16 10:54:47 +08:00
caishi 6facc3e65f title 2021-07-16 10:40:44 +08:00
何童崇 c8f6891239 修改bug 2021-07-16 10:13:27 +08:00
何童崇 11b5c87888 修改bug,新增管理路由 2021-07-16 09:13:05 +08:00
caishi 2f538ff394 keywords desc 2021-07-15 16:35:59 +08:00
何童崇 48a153d434 上传修改bug 2021-07-15 14:33:14 +08:00
何童崇 9c3ecabf47 增加管理员统筹所有任务的列表 2021-07-14 20:19:43 +08:00
何童崇 f18070da47 修改bug 2021-07-14 14:42:05 +08:00
何童崇 1e87e0c8ec 修改bug 2021-07-14 10:45:58 +08:00
何童崇 bec68aa090 修改bug 2021-07-14 10:35:05 +08:00
何童崇 aed83337fa 增加上传支付凭证,修改bug 2021-07-14 09:09:30 +08:00
何童崇 e5b7110090 修改bug 2021-07-13 16:29:56 +08:00
何童崇 716916b7b6 修改bug 2021-07-13 11:38:08 +08:00
何童崇 b5ccdbfcd6 修改bug 2021-07-13 10:53:19 +08:00
何童崇 1e7df569e6 上传协议部分及bug修改 2021-07-12 14:11:55 +08:00
何童崇 701d9dfc99 对接上传协议及确认支付 2021-07-10 21:56:04 +08:00
何童崇 e7b3a01c47 修改bug 2021-07-10 11:23:30 +08:00
何童崇 b19c084ac8 修改bug 2021-07-10 10:40:10 +08:00
何童崇 1d4bb3f4fc 修改bug 2021-07-10 10:00:19 +08:00
何童崇 e0b267bd6c 修改bug 2021-07-09 14:35:14 +08:00
何童崇 4bf4aa7c78 上传申诉材料审核bug 2021-07-08 17:33:51 +08:00
何童崇 e3643be01b 上传申诉材料审核及修改成果对接代码样式 2021-07-08 16:07:52 +08:00
何童崇 9c8add0152 上传申诉材料审核及修改成果对接代码 2021-07-08 15:49:38 +08:00
何童崇 edb7099131 新增佐证上传与审核 2021-07-06 21:28:38 +08:00
何童崇 cce818d4e0 修改BUG增加审核 2021-07-06 14:46:19 +08:00
caishi 909663bc47 新增招标公告 2021-07-02 13:58:22 +08:00
caishi 9ea9da9672 nav没有显示,被清空 2021-07-02 11:54:49 +08:00
何童崇 97bd7673e1 新增招标公告类型 2021-07-02 10:57:35 +08:00
何童崇 2aa89426ad 增加成果审核页面 2021-07-01 17:09:41 +08:00
何童崇 5131dacf05 修复成果提交时的bug,联调我是创客 2021-07-01 10:58:03 +08:00
何童崇 6b63cd25aa 上传成果修改 2021-06-28 17:35:05 +08:00
caishi 8162b8b908 修改头部选中样式 2021-06-28 16:02:25 +08:00
何童崇 7a59d43eec 修改头部选中样式 2021-06-28 15:56:48 +08:00
caishi 008ba8d1de 修改富文本样式及文件下载路径 2021-06-28 14:07:33 +08:00
何童崇 98a9344b02 修改样式 2021-06-28 14:05:12 +08:00
何童崇 b8342288dd 修改富文本样式 2021-06-28 13:56:23 +08:00
何童崇 09e81b9e78 添加成果内容 2021-06-28 11:53:37 +08:00
caishi 7cf5e23cb9 修改指向后台的url及优化代码结构 2021-06-25 14:11:30 +08:00
何童崇 8594168d33 修改指向后台的url及优化代码结构 2021-06-25 13:15:35 +08:00
caishi 2d7c6cb82d 合并公告模块 2021-06-24 17:11:12 +08:00
何童崇 c36925c136 新增公告模块代码 2021-06-24 17:01:05 +08:00
何童崇 6ec6ab2308 修改需求的部分bug及对接成果 2021-06-23 08:54:04 +08:00
何童崇 4109e4b07e 修改了需求部分bug 2021-06-21 13:43:31 +08:00
何童崇 216e984740 上传我的成果静态页面 2021-06-19 16:37:35 +08:00
何童崇 92f3934d5e 上传我的需求及 2021-06-18 17:07:10 +08:00
何童崇 2ed7e0d4c4 上传创客新增任务及列表代码 2021-06-17 15:28:13 +08:00
caishi 6cfe81aea3 meta keywords 2021-06-16 17:15:51 +08:00
何童崇 4dcbd51482 新增创客空间 2021-06-15 15:56:44 +08:00
caishi c32b333bc2 Merge branch 'dev_m_copy' into dev_military
# Conflicts:
#	src/forge/DevOps/Index.jsx
#	src/forge/Index.js
#	src/forge/Main/Detail.js
#	src/forge/Merge/MessageCount.js
#	src/forge/Settings/Collaborator.js
#	src/forge/Settings/CollaboratorMember.jsx
#	src/forge/users/watch_users.js
#	src/modules/tpm/NewHeader.js
2021-04-12 15:57:30 +08:00
caishi c965da7dd5 默认 2021-03-22 09:47:34 +08:00
caishi b44399968f 协作者分页 2021-03-22 09:46:30 +08:00
caishi 2591f28ccc bug 2021-03-22 09:37:37 +08:00
caishi 5530e8c723 diff-查看文件 2021-03-10 10:48:08 +08:00
caishi fa26dc9fa5 diff-查看文件 2021-03-10 10:47:23 +08:00
caishi 4cf40f9dfc update 2021-03-09 15:33:18 +08:00
caishi 2c034f5dff 修改资料-url 2021-03-09 14:09:06 +08:00
caishi d68d8318c1 account 2021-03-09 13:59:02 +08:00
caishi 41ae6b1f8d 修改资料练级 2021-03-09 13:55:02 +08:00
caishi a6e2171fca filedetail 2021-03-09 11:49:48 +08:00
caishi 916cc293ac url 2021-03-08 11:15:05 +08:00
caishi 5565eac601 nodata 2021-03-08 09:55:12 +08:00
caishi 860b71c7c6 外围贡献者 2021-03-04 17:02:20 +08:00
caishi f1c2841fe0 logo 2021-03-03 16:46:45 +08:00
caishi c6d5078d42 Merge branch 'develop' into dev_m_copy 2021-03-02 11:43:58 +08:00
caishi ebe2d625fa Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus-react into dev_military 2021-03-02 11:43:26 +08:00
caishi b5e1a91af5 style 2021-03-02 11:43:19 +08:00
caishi 4b8d72a6eb Merge branch 'develop' into dev_m_copy 2021-03-02 10:52:09 +08:00
caishi f0e1858cd4 update 2021-03-01 16:01:26 +08:00
caishi a92468953a style 2021-03-01 11:11:30 +08:00
caishi fdab967b6a Merge branch 'develop' into dev_m_copy
# Conflicts:
#	src/AppConfig.js
#	src/forge/DevOps/Index.jsx
#	src/forge/Index.js
#	src/forge/Main/Detail.js
#	src/forge/Main/IndexItem.js
#	src/forge/Merge/MessageCount.js
#	src/forge/Settings/Collaborator.js
#	src/forge/users/watch_users.js
#	src/modules/tpm/NewHeader.js
2021-03-01 10:21:14 +08:00
caishi 7e8929f166 appconfig 2021-03-01 10:17:38 +08:00
caishi 0a39ed80da Merge branch 'dev_m_copy' into dev_military
# Conflicts:
#	src/forge/Merge/MessageCount.js
2021-03-01 10:11:48 +08:00
caishi 5ed44f1d63 特殊项目审核 2021-02-26 16:58:31 +08:00
caishi 64e639ebea update 2021-02-26 11:53:08 +08:00
caishi 3fb9eb40f3 watch_users 2021-02-25 17:07:35 +08:00
caishi efc2443bb8 列表查询 2021-02-25 16:58:59 +08:00
caishi 2c3d917bd4 mygetHelmetapi2 2021-02-09 10:44:41 +08:00
caishi 617f139f52 fault 2021-02-04 15:13:08 +08:00
caishi de550d5f42 remove 2021-02-04 15:05:37 +08:00
caishi f12230dc91 url 2021-02-04 15:02:26 +08:00
caishi 1df2639cd5 pulls权限 2021-01-13 15:47:10 +08:00
caishi c746e9e634 pulls 2021-01-13 14:21:12 +08:00
caishi d8d464a332 pullrequest 2021-01-12 17:45:54 +08:00
caishi 83e337b2e9 pullrequest 2021-01-12 17:44:46 +08:00
caishi 5a6b7bd717 update 2021-01-12 09:30:30 +08:00
caishi c68a3dbd6f 项目成员访问特殊开源许可证项目不用上传文件 2021-01-11 18:14:59 +08:00
caishi 350f9426ea 工作流 2021-01-05 10:33:58 +08:00
caishi 5bda100e32 update 2021-01-05 09:23:58 +08:00
caishi dde7fa730a 同上-update 2021-01-04 16:43:15 +08:00
caishi 3f8f1b8083 特殊项目申请列表 2021-01-04 16:28:19 +08:00
caishi 6eef4bd09e 信息 2020-12-31 15:16:26 +08:00
caishi 0dcaea3db4 检测是否上传了文件 2020-12-31 14:13:31 +08:00
caishi 033134fa83 json 2020-12-29 16:28:08 +08:00
caishi 1bab0b01f7 debug 2020-12-29 16:18:20 +08:00
caishi 7b2f233cae 隐藏devops 2020-12-29 11:38:08 +08:00
caishi 2ecdd73c7f 外围贡献者 2020-12-28 20:42:12 +08:00
caishi 4e7a2fa3d7 Merge branch 'develop' into dev_m_copy
# Conflicts:
#	public/css/edu-purge.css
#	public/css/iconfont.css
#	src/AppConfig.js
#	src/forge/Main/CoderRootDirectory.js
#	src/forge/Main/Index.js
#	src/forge/Main/list.css
#	src/forge/Newfile/m_editor.js
#	src/forge/css/index.scss
#	src/modules/tpm/NewHeader.js
#	src/modules/tpm/TPMIndex.css
2020-12-24 17:50:26 +08:00
caishi 91662e2e3e back 2020-12-24 15:37:40 +08:00
sylor_huang@126.com c2129c994a change Header5 2020-09-16 15:14:46 +08:00
sylor_huang@126.com e968ece34c Change Header4 2020-09-16 15:08:54 +08:00
sylor_huang@126.com 70d407963e Change Header2 2020-09-16 14:58:37 +08:00
sylor_huang@126.com 00ccba74a1 Change Header1 2020-09-16 14:48:58 +08:00
sylor_huang@126.com 0790abb6f9 Change Header 2020-09-16 14:39:13 +08:00
caishi 6c4c161a1b Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus-react into dev_military
# Conflicts:
#	src/AppConfig.js
2020-09-15 17:21:42 +08:00
caishi 65a2bd43cf route 2020-09-15 17:21:10 +08:00
sylor_huang@126.com 10f813a443 Change banner 2020-09-15 09:38:57 +08:00
sylor_huang@126.com e79ec30c81 Change Index Category8 2020-09-14 14:53:09 +08:00
sylor_huang@126.com 2a7fea3612 Change Index Category6 2020-09-14 14:44:41 +08:00
sylor_huang@126.com cc46a3ac30 Change Index Category5 2020-09-14 14:08:03 +08:00
sylor_huang@126.com cca5f98c9b Change Index Category4 2020-09-14 11:50:45 +08:00
sylor_huang@126.com d4535005c8 Change Index Category3 2020-09-14 11:28:20 +08:00
sylor_huang@126.com 73d128e0c9 Change Resume 2020-09-14 09:26:46 +08:00
sylor_huang@126.com f09457a0ac Change Index Category 2020-09-11 18:49:41 +08:00
sylor_huang@126.com 78c218b12b Change Index Category 2020-09-11 18:45:34 +08:00
sylor_huang@126.com d9f87fdd18 Change Index Page 2020-09-11 18:31:31 +08:00
caishi 33c3395221 getpath 2020-08-27 10:14:07 +08:00
sylor_huang@126.com 74d26a40d3 Change Edit Url 2020-08-24 11:37:51 +08:00
sylor_huang@126.com 3f78ed249c Fix:Issues 2020-08-21 11:29:05 +08:00
caishi 07e1525f09 router 2020-08-20 18:10:40 +08:00
sylor_huang@126.com a9161b86a2 Change 2020-08-20 15:01:01 +08:00
sylor_huang@126.com e0e6cdcc79 Fix: Issues 2020-08-20 11:57:36 +08:00
sylor_huang@126.com 3b0c708d82 Fix: Issues 2020-08-20 11:44:27 +08:00
sylor_huang@126.com 0922df3875 Hide LoginDialog 2020-08-19 18:18:03 +08:00
sylor_huang@126.com ad3fe09cfb Merge branch 'newVersion_forge' into dev_military 2020-08-18 17:43:24 +08:00
sylor_huang@126.com 91f4327eb4 Change 2020-08-18 17:43:04 +08:00
sylor_huang@126.com f2f910b5e4 Add Dun Check For Project 2020-08-18 10:36:33 +08:00
sylor_huang@126.com 85d924db70 Fix: Add New File Language Api Wrong6 2020-08-13 11:56:39 +08:00
Jasder f1614a4b62 Delete url 2020-08-10 11:27:41 +08:00
Jasder 2fa71241db FIX 更改header的背景色 2020-08-09 23:24:12 +08:00
Jasder 13c6556574 FIX 更改logo导航链接 2020-08-09 23:20:08 +08:00
caishi 5601b71937 junke 2020-08-09 23:08:11 +08:00
Jasder 1a024f8011 FIX 去掉使用手册 2020-08-09 22:20:51 +08:00
144 changed files with 17755 additions and 4151 deletions

3
.gitignore vendored
View File

@ -86,3 +86,6 @@ typings/
.DS_Store
.idea/*
package.json
package-lock.json

View File

@ -101,9 +101,13 @@ module.exports = {
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
alias: {
educoder: __dirname + "/../src/common/educoder.js",
src: path.join(paths.appSrc), // 整个源代码目录
forge: path.join(paths.appSrc, 'forge'),
military: path.join(paths.appSrc, 'military'),
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
"react-native": "react-native-web",
'react-dom': '@hot-loader/react-dom',
},
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).

View File

@ -87,6 +87,9 @@ module.exports = {
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
alias: {
educoder: __dirname + "/../src/common/educoder.js",
src: path.join(paths.appSrc),
forge: path.join(paths.appSrc, 'forge'),
military: path.join(paths.appSrc, 'military'),
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
"react-native": "react-native-web",

14
jsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"educoder": ["./src/common/educoder.js"],
"forge":["./src/forge"],
"military":["./src/military"],
}
},
"exclude": [
"node_modules",
"build"
]
}

6767
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,7 @@
"styled-components": "^4.4.1",
"sw-precache-webpack-plugin": "0.11.4",
"url-loader": "0.6.2",
"wangeditor-for-react": "^1.4.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.2.0",
@ -182,6 +183,7 @@
"port": "3007",
"devDependencies": {
"@babel/runtime": "7.0.0-beta.51",
"@hot-loader/react-dom": "^16.14.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-plugin-import": "^1.13.0",
@ -191,6 +193,7 @@
"babel-preset-stage-2": "^6.24.1",
"compression-webpack-plugin": "^1.1.12",
"concat": "^1.0.3",
"cross-env": "^7.0.3",
"happypack": "^5.0.1",
"mockjs": "^1.1.0",
"node-sass": "^4.12.0",

View File

@ -1,6 +1,5 @@
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader {
background: #24292D !important;
width: 100%;
height: 60px !important;
min-width: 1200px;

View File

@ -3971,7 +3971,9 @@ html>body #ajax-indicator {
cursor: pointer;
position: relative;
font-size: 16px;
padding:0px 20px;
margin-right: 40px;
}.head-nav ul#header-nav li:first-child{
margin-left: 20px;
}
.head-nav ul#header-nav li a {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/favicon.back.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
public/favicon.ico Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -2,10 +2,11 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>
<meta name=”Keywords” Content=”TrustieOpenSourceProject″>
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
<title>红山开源社区</title>
<meta name="keywords" content="红山开源,创客空间,群智共享">
<meta name="keywords" content="红山开源社区,开源开放,众创,论坛">
<meta name="keywords" content="issue,bug,tracker">
<meta name="description" content="红山开源是一个依托互联网群体智慧实现世界范围内资源深度融合、开放共享和协同创新的开源社区" />
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">

View File

@ -45,6 +45,21 @@ const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'),
loading: Loading,
})
// Notice项目公告
const Notice = Loadable({
loader: () => import('./military/notice'),
loading: Loading,
})
//任务/需求
const Task = Loadable({
loader: () => import('./military/task'),
loading: Loading,
})
// 专家
const Expert = Loadable({
loader: () => import('./military/expert'),
loading: Loading,
})
//403页面
const Shixunauthority = Loadable({
loader: () => import('./modules/403/Shixunauthority'),
@ -240,6 +255,21 @@ class App extends Component {
}
}
/>
{/*公告*/}
<Route
path={"/notice"}
render={
(props) => {
return (<Notice {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*任务*/}
<Route path="/task" component={Task} />
{/*专家评审*/}
<Route path="/expert" component={Expert} />
{/*403*/}
<Route path="/403" component={Shixunauthority} />

View File

@ -4,16 +4,14 @@ import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css';
let message501 = false;
broadcastChannelOnmessage('refreshPage', () => {
window.location.reload();
window.location.reload()
})
function locationurl(list) {
if (window.location.port === "3007") {
} else {
if (window.location.port !== "3007") {
window.location.href = list
}
}
@ -34,7 +32,7 @@ function clearAllCookie() {
cookie.remove('autologin_trustie', { path: '/' });
setpostcookie()
}
clearAllCookie();
// clearAllCookie();
function setpostcookie() {
const str = window.location.pathname;
if (str.indexOf("/wxcode") !== -1) {
@ -54,9 +52,12 @@ setpostcookie();
window._debugType = debugType;
export function initAxiosInterceptors(props) {
initOnlineOfflineListener();
var proxy = "http://localhost:3000";
proxy = "https://testforgeplus.trustie.net";
initOnlineOfflineListener()
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
var
proxy = "http://localhost:3000";
// proxy = "https://forge.osredm.com";
proxy = "http://117.50.100.12:49999";
const requestMap = {};
window.setfalseInRequestMap = function (keyName) {
@ -90,7 +91,6 @@ export function initAxiosInterceptors(props) {
}
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
}
return config;

View File

@ -38,62 +38,91 @@ export function getNextHalfHourOfMoment(moment) {
return moment
}
 export function formatSeconds(value) {
export function formatSeconds(value) {
        var theTime = parseInt(value);// 秒
        var middle= 0;// 分
        var hour= 0;// 小时
    
        if(theTime > 60) {
            middle= parseInt(theTime/60);
            theTime = parseInt(theTime%60);
            if(middle> 60) {
                hour= parseInt(middle/60);
                middle= parseInt(middle%60);
            }
        }
        var result = ""+parseInt(theTime)+"秒";
        if(middle > 0) {
var theTime = parseInt(value);// 秒
var middle = 0;// 分
var hour = 0;// 小时
if (theTime > 60) {
middle = parseInt(theTime / 60);
theTime = parseInt(theTime % 60);
if (middle > 60) {
hour = parseInt(middle / 60);
middle = parseInt(middle % 60);
}
}
var result = "" + parseInt(theTime) + "秒";
if (middle > 0) {
if (hour > 0) {
result = ""+parseInt(middle)+"分";
result = "" + parseInt(middle) + "分";
} else {
result = ""+parseInt(middle)+"分"+result;
result = "" + parseInt(middle) + "分" + result;
}
}
if (hour > 0) {
result = "" + parseInt(hour) + "小时" + result;
}
return result;
}
            
        }
        if(hour> 0) {
            result = ""+parseInt(hour)+"小时"+result;
        }
        return result;
    }
export function formatDuring(mss){
var days = parseInt(mss / (1000 * 60 * 60 * 24));
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
// console.log("formatDuringformatDuring");
// console.log(days);
// console.log(hours);
// console.log(minutes);
// console.log(Math.abs(days));
// console.log(Math.abs(hours));
// console.log(Math.abs(minutes));
export function formatDuring(s) {
s = Math.abs(s);
let days = Math.floor(s / (60 * 60 * 24));
let hours = Math.floor((s % (60 * 60 * 24)) / (60 * 60));
let minutes = Math.floor((s % (60 * 60)) / (60));
let second = Math.floor(s % 60);
if (days) {
if(hours){
return days + "天" + hours + "小时";
}
return days + "天";
}
if (hours) {
if(minutes){
return hours + "小时" + minutes + "分";
}
return hours + "小时" ;
}
if (minutes) {
return minutes + "分";
}
return second + "秒";
}
/*
返回多久以前
backDate以前的某个日期
*/
export function timeAgo(backDate) {
try {
days = Math.abs(days);
moment(backDate);
} catch (e) {
return;
}
try {
hours = Math.abs(hours);
} catch (e) {
let time = new Date() - moment(backDate);
var days = Math.floor(time / (1000 * 60 * 60 * 24));
var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000);
if (time <= 0) {
return "刚刚";
}
try {
minutes = Math.abs(minutes);
} catch (e) {
if (days) {
return days + "天前";
}
if (hours) {
return hours + "小时前";
}
if (minutes) {
return minutes + "分前";
}
if (seconds) {
return seconds + "秒前";
}
return days + "天" + hours + "小时" + minutes + "分";
}

View File

@ -68,7 +68,7 @@ export function appendFileSizeToUploadFile(item) {
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
}
export function appendFileSizeToUploadFileAll(fileList) {
return fileList.map(item => {
return fileList && fileList.map(item => {
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
}

View File

@ -6,12 +6,13 @@ const { Search } = Input;
const $ = window.$;
const isDev = window.location.port == 3007;
const isdev2= window.location.hostname ==='www.educoder.net'
export const TEST_HOST = "https://testforgeplus.trustie.net/"
export const TEST_HOST = "http://39.105.176.215:49999"
export function getImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net';
const local = 'http://39.105.176.215:49999';
if (isDev) {
return `${local}/${path}`
}
@ -22,7 +23,7 @@ export function getImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net/';
const local = 'http://39.105.176.215:49999';
if(path.indexOf("http://")===-1){
if (isDev) {
return `${local}/images/${path}`
@ -93,7 +94,7 @@ export function setImagesUrl(path){
}
export function getUrl(path, goTest) {
const local = 'https://testforgeplus.trustie.net'
const local = 'http://39.105.176.215:49999'
if (isDev) {
return `${local}${path?path:''}`
}
@ -162,7 +163,7 @@ export function getmyUrl(geturl) {
}
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`;
return `${getUrl()}/api/attachments.json`;
}
export function getUploadLogoActionUrl() {

View File

@ -27,7 +27,7 @@ export {
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
} from './TextUtil'
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil'
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil'
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'

View File

@ -14,7 +14,7 @@ class CloneAddress extends Component {
const { http_url, downloadUrl } = this.props;
return (
<div className="gitAddressClone">
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
<p className="addressTips"><span>版本库地址已变更请基于新地址提交代码</span></p>
{
http_url && <span>HTTP</span>
}

View File

@ -1,3 +1,5 @@
import React , { useState , useEffect } from 'react';
import { Select } from 'antd';
import axios from 'axios';
@ -57,7 +59,6 @@ const LANGUAGE = [
export default (({ language , select_language })=>{
const [ languages , setLanguage ] = useState(undefined);
// useEffect(()=>{
// const url = '/dev_ops/languages.json';
// axios.get(url).then(result=>{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

View File

@ -145,7 +145,7 @@ class CoderRootCommit extends Component{
)
})
}
{commitDatas && commitDatas.length > 0 && <Nodata _html="暂无数据"/>}
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
</div>
</div>
{

View File

@ -251,7 +251,7 @@ class CoderRootDirectory extends Component {
// readme文件内容
renderReadMeContent = (readMeContent, permission) => {
const { fileDetail, readMeFile } = this.state;
if (fileDetail) {
if (fileDetail && fileDetail.length !== 0) {
return;
}
if (readMeContent && readMeContent.length > 0) {

View File

@ -4,6 +4,7 @@ import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import '../css/index.scss'
import './list.css';
import SpecialModal from './SpecialModal';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
@ -117,19 +118,20 @@ const DevIndex = Loadable({
function checkPathname(projectsId,owner,pathname){
let name = "";
if(pathname && pathname !== `/projects/${owner}/${projectsId}`){
if(pathname.indexOf("/about")>-1){
let url = pathname.split(`/projects/${owner}/${projectsId}`)[1];
if(url.indexOf("/about")>-1){
name="about"
}else if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){
}else if(url.indexOf("/issues")>-1 ||url.indexOf("Milepost") > 0){
name = "issues";
}else if(pathname.indexOf("/pulls")>-1){
}else if(url.indexOf("/pulls")>-1){
name="pulls"
}else if(pathname.indexOf("/milestones")>-1){
}else if(url.indexOf("/milestones")>-1){
name="milestones"
}else if(pathname.indexOf("/activity")>-1){
}else if(url.indexOf("/activity")>-1){
name="activity"
}else if(pathname.indexOf("/setting")>-1){
}else if(url.indexOf("/setting")>-1){
name="setting"
}else if(pathname.indexOf(`/devops`)>-1){
}else if(url.indexOf(`/devops`)>-1){
name="devops"
}
}
@ -161,7 +163,9 @@ class Detail extends Component {
defaultBranch:undefined,
// 非本平台项目
platform:false
platform:false,
visible:false,
user_apply_signatures:[]
}
}
@ -178,6 +182,7 @@ class Detail extends Component {
}
getProject = (num) => {
const {user} = this.props;
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/simple.json`;
axios.get(url).then((result) => {
@ -187,6 +192,24 @@ class Detail extends Component {
open_devops:result.data.open_devops,
platform:result.data.platform && result.data.platform !== 'educoder'
})
let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0];
if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){
this.setState({
visible:true,
is_secret:result.data.is_secret,
user_apply_signatures:signa
})
}
// 工作流:两种状态进入的链接不同
const pathname = this.props.history.location.pathname;
if(pathname===`/projects/${owner}/${projectsId}/devops`){
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
}
}
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
@ -357,13 +380,24 @@ class Detail extends Component {
})
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
this.props.history.push('/projects');
}
render() {
const { projectDetail, watchers_count, praises_count,
forked_count, firstSync , secondSync ,
isManager, watched, praised,
project , open_devops , platform , defaultBranch } = this.state;
project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
@ -390,18 +424,19 @@ class Detail extends Component {
}
return (
<div>
<SpecialModal {...this.props} visible={visible} hideModal={this.sureModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
<p className="color-white font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{project && project.author &&
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
{project.author.name}
</Link>
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${owner}/${projectsId}`} className="font-22">{project && project.name}</Link>
<Link to={`/projects/${owner}/${projectsId}`} className="color-white font-22">{project && project.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
@ -438,15 +473,14 @@ class Detail extends Component {
<span>{watched ? '取消关注' : '关注'}</span>
</a>
{
watchers_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
{watchers_count}
</Link>
:
<span className="detail_tag_btn_count">{watchers_count}</span>
:""
}
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
@ -454,13 +488,11 @@ class Detail extends Component {
<span>{praised ? '取消点赞' : '点赞'}</span>
</a>
{
praises_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
{praises_count}
</Link>:
<span className="detail_tag_btn_count">{praises_count}</span>
:""
}
</span>
<span className="detail_tag_btn">
@ -468,14 +500,12 @@ class Detail extends Component {
<i className="iconfont icon-fork color-grey-9 mr3"></i> (Fork)
</a>
{
forked_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
:
<span className="detail_tag_btn_count">{forked_count}</span>
:""
<span className="detail_tag_btn_count">{praises_count}</span>
}
</span>
</span>
@ -483,23 +513,23 @@ class Detail extends Component {
</div>
{
firstSync ? "" :
<div className="f-wrap-between mt15">
<div className="f-wrap-between pb20">
<ul className="headerMenu-wrapper">
<li className={pathname==="about" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
<i className={ pathname === "about" ? "iconfont icon-zhuye1 color-blue mr5 font-14":"iconfont icon-zhuye1 color-white font-14 mr5"}></i>
<span>主页</span>
</Link>
</li>
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-blue mr5 font-14":"iconfont icon-daimaku color-white font-14 mr5"}></i>
<span>代码库</span>
</Link>
</li>
<li className={pathname==="issues" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
<i className={pathname==="issues" ? "iconfont icon-renwu color-blue mr5 font-14":"iconfont icon-renwu color-white font-14 mr5"}></i>
<span>易修 (Issue)</span>
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
</Link>
@ -508,32 +538,32 @@ class Detail extends Component {
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
<li className={pathname==="pulls" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-blue mr5 font-14":"iconfont icon-hebingqingqiu1 color-white font-14 mr5"}></i>
<span>合并请求</span>
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>
}
{
{/* {
platform &&
<li className={pathname==="devops" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>(beta)
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li>
}
} */}
<li className={pathname==="milestones" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-blue mr5 font-14":"iconfont icon-lichengbei color-white font-14 mr5"}></i>
<span>里程碑</span>
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
</Link>
</li>
<li className={pathname==="activity" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-blue mr5 font-14":"iconfont icon-tongzhi color-white font-14 mr5"}></i>
<span>动态</span>
</Link>
</li>
@ -541,7 +571,7 @@ class Detail extends Component {
isManager && platform &&
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>

View File

@ -1,7 +1,6 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
import { getUrl } from 'educoder';
import { Menu, Input , Spin, Pagination , Popover, Affix, } from 'antd';
import '../css/index.scss'
import './list.css';
import './Index.scss';
@ -9,7 +8,7 @@ import ListItem from './IndexItem'
import axios from 'axios';
import img_new from '../Images/new.png';
import img_array from '../Images/array.png';
import banner from '../Images/banner_list.jpg';
import banner from '../Images/banner_list.png';
const Search = Input.Search;
class Index extends Component {
@ -23,7 +22,6 @@ class Index extends Component {
sort: undefined,
total: 0,
isSpin: true,
project_type: undefined,
category_id: undefined,
typeList: undefined,
@ -37,8 +35,8 @@ class Index extends Component {
}
componentDidMount = () => {
const { page, limit, search, sort, project_type, category_id , languageId } = this.state;
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
const { page,search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort,category_id , languageId);
this.getType();
@ -73,19 +71,24 @@ class Index extends Component {
}
// 获取列表
getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
getListData = (page,search, sort,category_id,language_id) => {
const { current_user } = this.props;
const url = `/projects.json`;
if(category_id==0){
category_id=undefined;
}
if(language_id==0){
language_id=undefined;
}
axios.get(url, {
params: {
user_id: current_user && current_user.user_id,
page,
limit,
limit:15,
search,
sort_by: sort,
project_type,
category_id,
language_id:languageId
language_id
}
}).then((result) => {
if (result) {
@ -103,7 +106,11 @@ class Index extends Component {
const url = `/projects/group_type_list.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setTypeList(result.data, undefined)
result.data.unshift({
name:'全部语言',
id:0,
});
this.setTypeList(result.data, 0)
}
}).catch((error) => { })
}
@ -112,7 +119,7 @@ class Index extends Component {
this.setState({
typeList: list.map((item, key) => {
return (
<li key={key} className={active_type && active_type === item.project_type ? 'active' : ''} onClick={() => this.changeType(`${item.project_type}`, list)}>
<li key={key} className={ parseInt(active_type) === item.id ? 'active' : ''} onClick={() => this.changeType(`${item.id}`, list)}>
<p>
<span className="font-16">{item.name}</span>
<span className="color-blue">{item.projects_count}</span>
@ -123,16 +130,16 @@ class Index extends Component {
})
}
// 切换类型
changeType = (type, list) => {
// 切换语言类型
changeType = (id, list) => {
this.setState({
isSpin: true,
project_type: type,
languageId: id,
search: undefined
})
this.setTypeList(list, type)
const { page, limit, sort, category_id , languageId } = this.state;
this.getListData(page, limit, undefined, sort, type, category_id , languageId);
this.setTypeList(list, id);
const { page,sort, category_id} = this.state;
this.getListData(page,undefined, sort,category_id , id);
}
// 获取类型
@ -141,7 +148,11 @@ class Index extends Component {
axios.get(url).then((result) => {
if (result && result.data) {
this.setCategoryList(result.data, undefined);
result.data.unshift({
name:'全部类别',
id:0,
});
this.setCategoryList(result.data, 0);
}
}).catch((error) => { })
}
@ -150,7 +161,7 @@ class Index extends Component {
this.setState({
categoryList: list.map((item, key) => {
return (
<li key={key} className={active_id && parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
<li key={key} className={ parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
<p>
<span className="font-16">{item.name}</span>
<span className="color-blue">{item.projects_count}</span>
@ -167,8 +178,8 @@ class Index extends Component {
page: 1
});
this.setCategoryList(list, id)
const { limit, sort, project_type , languageId } = this.state;
this.getListData(1, limit, undefined, sort, project_type, id , languageId);
const { sort,languageId } = this.state;
this.getListData(1,undefined, sort,id , languageId);
}
// 排序
@ -179,8 +190,8 @@ class Index extends Component {
search: undefined,
isSpin: true
})
const { limit, project_type, category_id , languageId } = this.state;
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId);
const {category_id , languageId } = this.state;
this.getListData(1,undefined, e.key,category_id , languageId);
}
// 搜索
@ -192,8 +203,8 @@ class Index extends Component {
project_type: undefined,
sort: "updated_on"
})
const { limit, sort, category_id , languageId } = this.state;
this.getListData(1, limit, value, sort, undefined, category_id , languageId);
const {sort, category_id , languageId } = this.state;
this.getListData(1,value, sort,category_id , languageId);
}
changeSearchValue = (e) => {
this.setState({
@ -205,23 +216,14 @@ class Index extends Component {
this.setState({
page
})
const { limit, search, sort, project_type, category_id , languageId } = this.state;
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
const {search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort, category_id , languageId);
}
getoDetail=(login,identifier)=>{
this.props.history.push(`/projects/${login}/${identifier}`);
}
// 选择语言类别
changeLanguage=(e)=>{
this.setState({
isSpin:true,
languageId:e === 0 ?undefined:e
})
const { page, limit, sort , project_type , category_id } = this.state;
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e);
}
menu =()=> {
return(
@ -255,15 +257,14 @@ class Index extends Component {
render() {
const { current_user } = this.props;
const { projectsList , recommendList , languageList , languageId ,
isSpin, total, search, limit, page, typeList, categoryList } = this.state;
const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state;
return (
<div>
<p className="t_project_banner">
<img src={banner} width="100%" alt=""/>
</p>
{
{/* {
recommendList && recommendList.length>0 &&
<div className="recommandProjects">
{
@ -285,44 +286,29 @@ class Index extends Component {
}
</div>
}
*/}
<div className="ProjectListIndex">
<div className="list-left">
<Affix className="affix-list-left" offsetTop={90}>
<div className="affix-list-content">
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i></li>
{typeList}
<li className="MenuTitle" onClick={() => {this.getType();this.changeType(undefined, this.state.typeList);}}>
<span><i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
语言</span></li>
<div className="list-affix">{typeList}</div>
</ul>
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i></li>
{categoryList}
<li className="MenuTitle" onClick={() => {this.getCategory();this.changeCategory(undefined, this.state.categoryList);}}>
<span><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i></span></li>
<div className="list-affix">{categoryList}</div>
</ul>
</div>
</Affix>
<div className="list-right boxShandow radius-2" style={{padding:0}}>
<Spin spinning={isSpin}>
<div className="list-r-operation">
<div>
<Select
showSearch
placeholder="请选择语言"
style={{width:"150px",marginRight:"20px"}}
size={"large"}
onChange={this.changeLanguage}
value={languageId}
allowClear={true}
optionFilterProp="children"
filterOption={(input,option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
>
<Select.Option key={0} value={0}>请选择语言</Select.Option>
{
languageList && languageList.length>0 && languageList.map((item,key)=>{
return(
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
)
})
}
</Select>
<Search
placeholder="输入项目名称关键字进行搜索"
enterButton="搜索"
@ -350,7 +336,7 @@ class Index extends Component {
</Popover>
</div>
</div>
<ListItem {...this.props} {...this.state} projects={projectsList}></ListItem>
<ListItem {...this.props} {...this.state} projects={projectsList} getListData={this.getListData}></ListItem>
{this.pagination(total,limit,page)}
</Spin>
</div>

View File

@ -72,3 +72,15 @@
}
}
}
.singleBtn{
display: inline-block;
.ant-upload-list-item{
position: absolute;
bottom: 0px;
width: 100%;
left: 0px;
.ant-upload-list-item-name{
text-align: left;
}
}
}

View File

@ -6,24 +6,70 @@ import '../css/index.scss';
import Nodata from '../Nodata';
import './list.css';
import img_parise from '../Images/parise.png';
import SpecialModal from './SpecialModal';
class IndexItem extends Component {
constructor(props){
super(props);
this.state={
visible:false,
user_apply_signatures:[],
project_id:undefined
}
}
TurnToDetail = (login, url) => {
this.props.history.push({
pathname: url,
state: login
})
}
/**
* link:跳转到详情的地址
* user_apply_signatures:是否已经发送访问特殊开源项目的文件
* project_id项目id
* is_secret:是否是特殊开源许可证项目
* id创建者login
* is_member:是否是项目成员(如果是项目成员可以直接进入项目)
* */
projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{
const { user , showLoginDialog } = this.props;
if(is_secret && (!user || (user && !user.login))){
showLoginDialog();
return;
}
let signa = user_apply_signatures && user_apply_signatures[0];
if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){
this.setState({
visible:true,
user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined,
project_id
})
}else{
this.props.history.push(link);
}
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
const { getListData } = this.props;
getListData && getListData(1);
}
render() {
const { projects } = this.props;
return (
<div className="project-list minH-670">
{ projects && projects.length > 0 ? projects.map((item, key) => {
const { visible , user_apply_signatures , project_id } = this.state;
const renderList = (
projects && projects.length > 0 ? projects.map((item, key) => {
return (
<div className="p-r-Item" key={key}>
{
item.platform === "educoder" ?
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
<a style={{cursor:"default"}} className="show-user-link">
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
</a>
:
@ -33,7 +79,7 @@ class IndexItem extends Component {
}
<div className="p-r-Infos">
<div className="p-r-name">
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
<a onClick={()=>this.projectHref(`/projects/${item.author.login}/${item.identifier}`,item.user_apply_signatures, item.id,item.is_secret,item.author.login,item.is_member)} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
{item.author.name}/{item.name}
{
item.forked_from_project_id ?
@ -52,13 +98,13 @@ class IndexItem extends Component {
<i className="iconfont icon-jingxiang font-18 color-green" />
</span>:""
}
</Link>
</a>
<span className="p-r-tags">
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> {item.praises_count}</span>
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
</span>
</div>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<p className="break_word task-hide-2 mt8 color-grey-3 " style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<div className="p-r-about">
<span className="p-r-detail">
@ -71,7 +117,12 @@ class IndexItem extends Component {
</div>
</div>
)
}) : <Nodata _html="暂无数据~"></Nodata>}
}) : <Nodata _html="暂无数据~"></Nodata>
)
return (
<div className="project-list minH-670">
<SpecialModal {...this.props} visible={visible} hideModal={this.hideModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
{renderList}
</div>
)
}

View File

@ -0,0 +1,49 @@
import React , { useEffect , useState } from 'react';
import { Modal } from 'antd';
import UploadSingle from '../Upload/single';
import './Index.scss';
import axios from 'axios';
import { getUrl } from 'educoder';
function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){
const [ id ,setId ] = useState(undefined);
function loadFunc(id){
setId(id);
}
function sure(){
if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){
if(!id || (id && id.length === 0)){
showNotification("请先提交文件进行审核!");
return;
}
const url = `/apply_signatures.json`;
axios.post(url,{
attachment_id:id,
project_id:project_id
}).then(result=>{
if(result && result.data.id){
showNotification("已提交文件,正在等待审核!");
sureModal();
}
})
}else{
sureModal();
}
}
return(
<Modal title="提示" visible={visible} closable={false} onCancel={hideModal} onOk={sure}>
{
!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ?
<div style={{width:"420px",textAlign:'center',margin:"0 auto",paddingBottom:"30px",position:"relative"}}>
<div>该项目为私有项目请先<a href={getUrl(`/api/apply_signatures/template_file`)} className="color-blue">下载</a>开源协议,阅读并填写<br/>相关信息后将协议<UploadSingle size={"5"} load={loadFunc} showNotification={showNotification} className={'singleBtn'}><span className="color-blue" style={{cursor:"pointer"}}>上传</span></UploadSingle>,平台审核通过后即可进入当前项目</div>
</div>
:
<p style={{textAlign:'center'}}>您上传的文件正在审核中,通过后才能访问当前项目</p>
}
</Modal>
)
}
export default SpecialModal;

View File

@ -18,6 +18,14 @@
box-sizing: border-box;
margin-bottom: 20px;
}
.affix-list-left{
width: 26%;
box-sizing: border-box;
margin-bottom: 20px;
}
.affix-list-content{
padding-right:20px;
}
.list-right{
width:74%;
background: #fff;
@ -208,9 +216,7 @@
}
/* -----------详情------------ */
.detailHeader-wrapper{
background-color:#FAFBFC;
/* background: url(../Images/forgeBanner.jpg) no-repeat center; */
/* background-size:cover; */
background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%);
}
.headerMenu-wrapper{
font-size: 16px;
@ -222,36 +228,42 @@
text-align: center;
height: 40px;
line-height: 28px;
margin-right: 40px;
border:1px solid transparent;
}
.headerMenu-wrapper{
font-size: 16px;
display: flex;
flex-direction: row;
}
.headerMenu-wrapper li{
padding:0px 18px;
position: relative;
text-align: center;
height: 30px;
line-height: 30px;
}
.headerMenu-wrapper li a{
color: #666;
color: #fff;
display: flex;
align-items: center;
}
.headerMenu-wrapper li a > img{
margin-right: 8px;
}
.headerMenu-wrapper li a > span.num{
height: 28px;
line-height: 29px;
margin-left: 8px;
font-size: 12px;
color: #2878FF;
float: right;
.headerMenu-wrapper li a > span{
display: block;
margin-left: 5px;
font-size: 16px;
}
.headerMenu-wrapper li.active::after{
position: absolute;
bottom:0px;
height:2px;
background-color: #5091FF;
content:'';
left: 0px;
width:100%;
.headerMenu-wrapper li.active{
border-radius: 15px;
border:1px solid #71A6FF;
}
.detail_tag_btn{
height:26px;
line-height: 26px;
border-radius:5px;
border:1px solid #f1f1f1;
border:1px solid #71A6FF;
display: flex;
align-items: center;
margin-left: 30px
@ -259,19 +271,26 @@
.ant-tooltip {
max-width: fit-content!important;
}
.detail_tag_btn_name{
padding:0px 10px;
color: #666!important;
display: flex;
align-items: center;
color: #fff;
}
.detail_tag_btn_name img{
margin-right: 10px;
}
.detail_tag_btn_count{
padding:0px 10px;
background: #fff;
color: #fff !important;
background: rgba(255,255,255,0.2);
border-radius: 0px 4px 4px 0px;
font-size: 12px;
height:100%;
}
.detail_tag_btn_count:hover{
/* color: #1C91FF !important; */
background: rgba(255,255,255,0.5);
}
.files-md{
border:1px solid #eee;

View File

@ -47,7 +47,7 @@ function Files({data,history,owner,projectsId}){
<span>{item.name}</span>
</AlignCenter>
<span>
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}${item.sha ? `/branch/${truncateCommitId(item.sha)}/`:"/"}tree/${item.name}`)}}>查看文件</Button>
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
<span className="color-green">+{item.addition}</span>
<span className="color-red ml20">-{item.deletion}</span>
</span>

View File

@ -43,7 +43,9 @@ class Index extends Component {
project_language_name: undefined,
project_category_name: undefined,
license_name: undefined,
ignore_name: undefined
ignore_name: undefined,
licenseForDisabled:undefined
}
}
componentDidMount = () => {
@ -145,7 +147,7 @@ class Index extends Component {
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
}
let list = _data && _data.map((item) => (
<Option key={item.id} value={item.name}>
<Option key={item.id} value={item.name} onClick={()=>this.selectSerect(item.is_secret)}>
{item.name}
</Option>
));
@ -155,6 +157,17 @@ class Index extends Component {
}
}
selectSerect=(flag)=>{
if(flag){
this.props.form.setFieldsValue({
private:true
})
}
this.setState({
licenseForDisabled:flag
})
}
subMitFrom = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
@ -198,7 +211,8 @@ class Index extends Component {
}
ChangePlatform = (value, e, name, list) => {
this.setOptionsList(list, name, value)
this.setOptionsList(list, name, value);
this.setState({
[name + "_id"]: e.key,
[name + "_name"]: value,
@ -272,6 +286,7 @@ class Index extends Component {
project_category_list,
license_list,
ignore_list,
licenseForDisabled,
mirrorCheck
} = this.state;
@ -477,8 +492,8 @@ class Index extends Component {
style={{ margin: "0px" }}
className="privatePart"
>
{getFieldDecorator('private')(
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
{getFieldDecorator('private',{valuePropName:"checked"})(
<Checkbox value="limit" disabled={licenseForDisabled}>将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
)}
</Form.Item >
{

View File

@ -15,8 +15,8 @@ const MENU_LIST = [
function CollaboratorMember({projectsId,owner,project_id,author,showNotification,newId}){
const [ roleName , setRoleName ] = useState(undefined);
const [ search , setSearch ] = useState(undefined);
const [ page , setPage ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(false);
const [ page , setPage ] = useState(1);
const [ isSpin , setIsSpin ] = useState(true);
const [ role , setRole ] = useState(undefined);
const [ listData , setListData ] = useState(undefined);
const [ total , setTotal ] = useState(0);
@ -166,7 +166,11 @@ function CollaboratorMember({projectsId,owner,project_id,author,showNotification
<label className={get_color(item.role)}>
{operation && operation[0].name}
</label>
) : (
)
:
item.is_apply_signature ?
<label className="text-grey">外围贡献者</label>
:(
<Dropdown overlay={setRoles(`${item.id}`)} placement={"bottomCenter"}>
<span className={get_color(item.role)}>
{operation && operation[0].name}
@ -261,14 +265,8 @@ function CollaboratorMember({projectsId,owner,project_id,author,showNotification
</div>
</Spin>
{total > LIMIT ?
<div className="edu-txt-center mt20 mb20">
<Pagination
showQuickJumper
pageSize={LIMIT}
current={page}
total={total}
onChange={()=>setPage(page)}
></Pagination>
<div className="edu-txt-center mt20 pb20">
<Pagination simple current={page} pageSize={LIMIT} total={total} onChange={(page)=>setPage(page)}/>
</div>
:""}
</React.Fragment>

View File

@ -28,6 +28,10 @@ const Tags = Loadable({
loader: () => import("./new_tags"),
loading: Loading,
});
const Special = Loadable({
loader: () => import("./SpecialProject"),
loading: Loading,
});
const Manage = Loadable({
loader: () => import("./ManageWeb"),
loading: Loading,
@ -40,6 +44,7 @@ class Index extends Component {
render() {
const { projectsId , owner } = this.props.match.params;
const { pathname } = this.props.history.location;
const { projectDetail } = this.props;
const flag = pathname === `/projects/${owner}/${projectsId}/setting`;
return (
@ -87,6 +92,20 @@ class Index extends Component {
</Link>
</p>
</li>
{
projectDetail && projectDetail.permission && (projectDetail.permission === "Owner" || projectDetail.permission === "Admin") ?
<li
className={pathname.indexOf("setting/special") > -1 ? "active" : ""}
>
<p>
<Link to={`/projects/${owner}/${projectsId}/setting/special`} className="w-100">
<i className="iconfont icon-jingyan font-18 mr10"></i>
特殊开源许可证项目管理
</Link>
</p>
</li>
:""
}
{/* <li
className={
@ -112,7 +131,15 @@ class Index extends Component {
<Collaborator {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:owner/:projectsId/setting/special"
render={(props) => (
<Special {...this.props} {...props} {...this.state} />
)}
></Route>
{/* 修改仓库信息 */}
<Route
path="/projects/:owner/:projectsId/setting/tags"
render={(props) => (

View File

@ -15,6 +15,7 @@ class Setting extends Component {
CategoryList: undefined,
LanguageList: undefined,
private_check: undefined,
is_secret:false
};
}
@ -52,10 +53,11 @@ class Setting extends Component {
.then((result) => {
if (result) {
this.props.form.setFieldsValue({
...result.data,
...result.data
});
this.setState({
private_check: result.data.private,
is_secret:result.data.is_secret
});
}
})
@ -152,7 +154,7 @@ class Setting extends Component {
render() {
const { getFieldDecorator } = this.props.form;
const { CategoryList, LanguageList, private_check } = this.state;
const { CategoryList, LanguageList, private_check , is_secret } = this.state;
return (
<div>
<WhiteBack style={{paddingBottom:"20px"}}>
@ -177,6 +179,7 @@ class Setting extends Component {
<Checkbox
checked={private_check}
onChange={this.changePrivate}
disabled={is_secret}
>
将仓库设为私有
</Checkbox>

View File

@ -0,0 +1,186 @@
import React , { useEffect , useState} from 'react';
import { Input , Table , Pagination, Button , Dropdown , Menu } from 'antd';
import { Banner , WhiteBack , AlignCenterBetween } from '../Component/layout';
import axios from 'axios';
const { Search } = Input;
const LIMIT = 15;
function SpecialProject(props){
const [ page , setPage] = useState(1);
const [ searchValue , SetSearchValue ] = useState(undefined);
const [ total , setTotal ] = useState(0);
const [ list , setList ] = useState(undefined);
const [ status , setStatus ] = useState(undefined);
const [ loading ,setLoading ] = useState(true);
const { owner , projectsId} = props.match.params;
const { project_id } = props;
useEffect(()=>{
if(project_id){
setLoading(true);
Init(searchValue, status);
}
},[page,project_id]);
function Init(search,status){
const url = `/apply_signatures.json`;
axios.get(url,{
params:{
project_id,
page,limit:LIMIT,search,status
}
}).then(result=>{
setLoading(false);
if(result){
setList(result.data.apply_signatures);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
function changePage(page){
setLoading(true);
setPage(page);
}
const column = [
{
dataIndex:"column",
key:1,
width:"12%",
title:"序号",
render:(txt,item,index)=>{
return `${index+1}`
}
},
{
dataIndex:"name",
key:2,
title:"申请人",
render:(text,item,m)=>{
return item.user && <span className="task-hide" style={{maxWidth:"139px",display:"block"}}>{item.user.name}</span>
}
},
{
dataIndex:"email",
key:2,
title:"邮箱",
width:"22%",
render:(text,item,m)=>{
return item.user && <span>{item.user.email}</span>
}
},
{
dataIndex:"attachment",
key:3,
title:"附件",
width:"28%",
render:(text,item,m)=>{
return item.attachment && <a className="task-hide" style={{maxWidth:"173px",display:"block"}} href={`${item.attachment.path}`}>{item.attachment.filename}</a>
}
},
{
dataIndex:"operation",
key:4,
width:"18%",
title:"操作",
render:(text, item) =>{
return(
<React.Fragment>
{
item.status === "waiting" &&
<span>
<Button size="small" onClick={()=>operation(item.id,"unpassed")}>拒绝</Button>
<Button size="small" onClick={()=>operation(item.id,"passed")} type={"primary"} className="ml20">同意</Button>
</span>
}
{
item.status === "unpassed" &&
<span style={{color:"#ff041c"}}>已拒绝</span>
}
{
item.status === "passed" &&
<span style={{color:"#13b4f1"}}>已同意</span>
}
</React.Fragment>
)
}
}
]
// &
function operation(ids,s){
setLoading(true);
const url = `/apply_signatures/${ids}.json`;
axios.put(url,{
project_id:project_id,
status:s
}).then(result=>{
setLoading(false);
if(result){
props.showNotification(`${s==="passed"?"同意":"拒绝"}此申请已操作成功!`);
Init(searchValue,status);
}
}).catch(error=>{setLoading(false)})
}
function searchList(){
setLoading(true);
Init(searchValue,status);
}
const menu=(
<Menu onClick={chooseStatus}>
<Menu.Item key="all">全部</Menu.Item>
<Menu.Item key="waiting">审核中</Menu.Item>
<Menu.Item key="unpassed">已拒绝</Menu.Item>
<Menu.Item key="passed">已同意</Menu.Item>
</Menu>
)
function chooseStatus(e){
setStatus(e.key);
Init(searchValue, e.key);
}
return(
<WhiteBack style={{minHeight:"500px"}}>
<Banner>项目管理</Banner>
<AlignCenterBetween style={{padding:"10px 20px",textAlign:"right"}}>
<Search
placeholder="请输入用户姓名或者邮箱搜索"
allowClear
enterButton="搜索"
style={{width:400}}
size="middle"
value={searchValue}
onChange={(e)=>SetSearchValue(e.target.value)}
onSearch={searchList}
/>
<Dropdown overlay={menu} placement="bottomRight">
<span>
<span style={{color:status ? "color-blue" : "color-grey-3"}}>{status ==="waiting"?"审核中":status==="unpassed"?"已拒绝":status==="passed"?"已同意":"全部"}</span>
<i className="iconfont icon-xiajiantou color-grey-9 font-14 ml8"></i>
</span>
</Dropdown>
</AlignCenterBetween>
<Table
columns={column}
rowKey={(record) => record.id}
pagination={false}
dataSource={list}
loading={loading}
></Table>
{
total > LIMIT &&
<div className="center mt20 mb20">
<Pagination simple current={page} total={total} pageSize={LIMIT} onChange={changePage}></Pagination>
</div>
}
</WhiteBack>
)
}
export default SpecialProject;

View File

@ -139,6 +139,7 @@
.padding15-10{
padding:15px 10px;
}
.center{text-align: center;}
.w-100{width: 100%;}
.fwb{font-weight: 600;}
.text-black{color: #333;}
@ -151,6 +152,9 @@
.text-yellow{color: #FF6E21 !important;}
.text-delete{color: #BBBBBB; }
.text-delete:hover{color: #db2828; }
.text-grey{
color: #999;
}
.new-tag-div{
padding: 15px;
height: 75px;

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import { Upload, Button, Icon } from 'antd';
import { Upload , Icon } from 'antd';
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
import axios from 'axios';
@ -45,8 +45,7 @@ class Index extends Component {
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
}).then((response) => {
axios.delete(url).then((response) => {
if (response.data) {
if (response.data.status === 0) {
this.setState((state) => {
@ -71,11 +70,26 @@ class Index extends Component {
handleChange = (info) => {
const { changeIsComplete } = this.props;
changeIsComplete && changeIsComplete(true);
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = info.fileList;
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
this.fileIdList(fileList);
if ( info.file.status === 'done') {
let filelist = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1];
if(filelist && filelist.response && filelist.response.status === -1){
this.props.showNotification(filelist.response.message)
this.setState((state) => {
state.fileList.pop()
return {
fileList: state.fileList,
};
});
this.fileIdList(this.state.fileList);
}
}
}
}

View File

@ -0,0 +1,78 @@
import React, { useEffect , useState } from "react";
import { Upload } from 'antd';
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
import axios from 'axios';
function Single({ children , showNotification , className , load , size }) {
const [ fileList , setFileList ] = useState(undefined);
//
function onAttachmentRemove(file){
if (!file.percent || file.percent === 100) {
deleteAttachment(file);
return false;
}
}
function deleteAttachment(file){
let uid = file.response ? file.response.id : file.uid;
const url = `/attachments/${uid}.json`
axios.delete(url).then((response) => {
if (response.data && response.data.status === 0) {
let list = fileList.filter(item=> item.response && item.response.id !== uid);
setFileList(list);
fileIdList(list);
}
}).catch(error=>{});
}
function handleChange(info){
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = [info.file];
let list = appendFileSizeToUploadFileAll(fileList);
setFileList(list);
if ( info.file.status === 'done') {
let f = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1];
if(f && f.response && f.response.status === -1){
showNotification(f.response.message)
setFileList(f);
}
fileIdList(fileList);
}
}
}
function fileIdList(fileList){
let l = fileList && fileList.length > 0 && fileList[0];
let array = [l && l.response && l.response.id];
load && load(array);
}
function beforeUpload(file){
if(!size) return;
const isLt100M = file.size / 1024 / 1024 < size;
if (!isLt100M) {
showNotification(`文件大小必须小于${size}MB!`);
}
return isLt100M;
}
//
const upload = {
name: 'file',
fileList: fileList,
action: `${getUploadActionUrl()}`,
onChange: handleChange,
onRemove: onAttachmentRemove,
beforeUpload: beforeUpload
};
return (
<Upload {...upload} className={className}>
{children}
</Upload>
)
}
export default Single;

View File

@ -1,21 +0,0 @@
1.请求URL https://code.ihub.org.cn/api/v1/mirrors/create.json
2.请求方式: POST
3.参数:
{
"image_url": "xxx.git", #必填,且后缀必为.git,
"language": "Ruby", #必填,如数据库不存在,则会创建新的记录
}
4. 返回值: {
"status": 1,
"message": "同步成功项目ID===1806"
}
5. 返回值说明: 仅有当有返回值且返回值的status 的值为1 才是创建成功,其余均为创建失败

View File

@ -62,6 +62,9 @@
.text-yellow{
color: #FFA802 !important
}
.text-grey{
color: #999;
}
.text-gray {
color: #888888;
}

View File

@ -166,7 +166,12 @@ form{
margin-bottom: 12px;
border-radius:2px;
background-color: #fff;
&>li{
.list-affix{
min-height: 20px;
max-height: 240px;
overflow-y: auto;
}
& li{
font-size: 1rem;
padding:0px 0px 0px 20px;
box-sizing: border-box;
@ -205,7 +210,7 @@ form{
width: 6px;
content: '';
height: 33px;
background: #4CACFF;
background: #1484EF;
}
.MenuTitle{
font-size: 16px;
@ -215,6 +220,21 @@ form{
line-height: 62px;
border-bottom: 1px solid #E0E0E0;
font-weight: 400;
span{
display: block;
width: 50%;
height: 100%;
cursor: pointer;
}
span:hover{
color: #1484EF;
.iconfont{
color: #1484EF !important;
}
}
}
.ant-menu-inline{
border:none;

View File

@ -6,7 +6,6 @@ import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
import Handbook from '../Component/Handbook';
const Infos = Loadable({
loader: () => import("./Infos"),
loading: Loading,
@ -15,7 +14,6 @@ export default withRouter(
(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props)=>{
return(
<div>
<Handbook />
<Switch>
<Route
path="/users/:username"

View File

@ -1,5 +1,4 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Spin } from "antd";
import FocusButton from "../UsersList/focus_button";
@ -52,7 +51,7 @@ class Infos extends Component {
isSpin: false,
user: undefined,
project_type: undefined,
route_type: undefined
route_type: undefined,
};
}
@ -138,7 +137,7 @@ class Infos extends Component {
render() {
const { current_user, mygetHelmetapi } = this.props;
const { current_user, main_web_site_url } = this.props;
const { username } = this.props.match.params;
const { user, isSpin, project_type, route_type } = this.state;
@ -147,7 +146,7 @@ class Infos extends Component {
<Spin spinning={isSpin}>
<div className="new-content-flex">
<div className="list-left">
<div className="bgcF">
<div className="bgcF mb20">
<div className="list-l-Menu text-center pd20 ">
<Avatar
size={110}
@ -168,11 +167,7 @@ class Infos extends Component {
<Button
block
className="text-button-grey"
href={`${
mygetHelmetapi &&mygetHelmetapi.new_course&&
mygetHelmetapi.new_course.edit_account
}`}
target="_blank"
href={`${main_web_site_url || "https://osredm.com/"}users/${user.login}/profiles`}
>
{" "}
<i className="iconfont icon-shezhi4 font-15 mr5"></i>
@ -193,22 +188,22 @@ class Infos extends Component {
)}
</div>
<div className="width100 inline-block mt20">
<Link
to={`/users/${user && user.login}/watchers`}
<a
href={`/users/${user && user.login}/user_watchlist`}
className={`with50 text-center pull-left ${route_type === "watchers" ? "text-primary" : ""}`}
onClick={() =>this.route_link("watchers")}
>
<div>{current_user && user && user.login === current_user.login ? "我关注的" : "TA关注的"}</div>
<span>{user && user.watching_count}</span>
</Link>
<Link
to={`/users/${user && user.login}/fan_users`}
</a>
<a
href={`/users/${user && user.login}/user_fanslist`}
onClick={() =>this.route_link("fan_users")}
className={`with50 text-center pull-left ${route_type === "fan_users" ? "text-primary" : ""}`}
>
<div>{current_user && user && user.login === current_user.login ? "关注我的" : "关注TA的"}</div>
<span>{user && user.watched_count}</span>
</Link>
</a>
</div>
</div>
</div>
@ -230,7 +225,7 @@ class Infos extends Component {
<div className="bgcF">
<ul className="list-l-Menu">
<li className="MenuTitle" onClick={() => this.change_project_type(undefined)}>
<li className="MenuTitle" onClick={() => this.change_project_type()}>
<i className="iconfont icon-xiangmuleixing font-15 mr5"></i>
项目类型
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>

View File

@ -0,0 +1,20 @@
import { Modal } from 'antd';
export default (
handleOk,
title,
content,
handleCancel) => {
return Modal.confirm({
title: title || "警告",
content: content || "确认删除?",
okText: '确定',
cancelText: '取消',
onOk() {
handleOk && handleOk();
},
onCancel() {
handleCancel && handleCancel();
}
});
}

View File

@ -0,0 +1,90 @@
import React, { useEffect, useState } from "react";
import { Upload, Button } from 'antd';
import { appendFileSizeToUploadFileAll } from 'educoder';
import { httpUrl } from '../task/fetch';
function Uploads({ className, size, actionUrl, fileList, showNotification, load }) {
const [files, setFiles] = useState(undefined);
useEffect(() => {
if (fileList) {
init();
}
}, [fileList]);
function init() {
let f = appendFileSizeToUploadFileAll(fileList);
setFiles(f);
}
function onAttachmentRemove(file) {
if (!file.percent || file.percent === 100) {
deleteAttachment(file);
return false;
}
}
function deleteAttachment(file) {
let id = (file.response && file.response.data && file.response.data.id) || file.id;
//
let nf = files.filter(item => {
let itemId = (item.response && item.response.data && item.response.data.id) || item.id;
return itemId !== id;
});
setFiles(nf);
backFiles(nf);
}
function backFiles(fileList) {
let filesId = [];
for (const item of fileList) {
if (item) {
let itemId = (item.response && item.response.data && item.response.data.id) || item.id;
itemId && filesId.push(itemId);
}
}
load && load(fileList, filesId.join());
}
function handleChange(info) {
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = info.fileList;
setFiles(appendFileSizeToUploadFileAll(fileList));
if (info.file.response) {
for (let i = 0; i < fileList.length; i++) {
if (fileList[i].response && !fileList[i].response.data) {
fileList.splice(i, 1);
}
}
backFiles(fileList);
if (!info.file.response.data) {
info.file.response && showNotification(info.file.response.message)
}
}
}
}
function beforeUpload(file) {
const isLt100M = file.size / 1024 / 1024 < size;
if (!isLt100M) {
showNotification(`文件大小必须小于${size}MB!`);
}
return isLt100M;
}
const upload = {
name: 'file',
fileList: files,
action: (httpUrl || actionUrl) + `/busiAttachments/upload`,
onChange: handleChange,
onRemove: onAttachmentRemove,
beforeUpload: beforeUpload,
};
return (
<Upload {...upload} className={className}>
<Button type="primary">点击上传</Button>
<span className="ml10 color-grey-9">(你可以上传小于<span className="color-red">{size}MB</span>的文件)</span>
</Upload>
)
}
export default Uploads;

View File

@ -0,0 +1,28 @@
import React, { useEffect, useState,memo } from 'react';
import classNames from 'classnames';
import './index.scss';
export default memo((props) => {
const { title, options, changeOptionId, type ,size} = props;
const [option, setOption] = useState({ code: "", dicItemName: "" ,dicItemCode:""});
useEffect(() => {
changeOptionId(option, type);
}, [option])
return (
<div className={classNames({"choose-box":true,"choose-box-big":size})}>
<div className="choose-title">{title}</div>
<div className="choose-list">
<div className={classNames({ "choose-item-checked": option.dicItemCode === "", "choose-item": true })} key={"all"} onClick={() => { setOption({ dicItemCode: "", dicItemName: "" }) }}>全部</div>
{
options.map((item) => {
return <div className={classNames({ "choose-item-checked": option.dicItemCode === item.dicItemCode, "choose-item": true })} key={item.dicItemCode} onClick={() => { setOption(item) }} >{item.dicItemName}</div>
})
}
</div>
</div>
)
})

View File

@ -0,0 +1,47 @@
.nav-content {
margin:20px 0;
padding:1rem 0.2rem;
background: #fff;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05);
border-radius: 5px;
}
.choose-box {
padding: .35em 0;
display: flex;
justify-content: start;
font-size: .85rem;
}
.choose-title {
width: 6.5em;
text-align: center;
color: #333;
font-weight: 500;
flex:none;
}
.choose-box-big{
font-size: 1rem;
.choose-title{
text-align: right;
}
}
.choose-list {
display: flex;
justify-content: start;
flex-wrap: wrap;
}
.choose-item {
color:#666;
text-align: center;
padding: 0 15px ;
cursor: pointer;
&:hover{
color: #1B8FFF;
}
}
.choose-item-checked {
background: #f7f7f7;
color: #1B8FFF;
}

View File

@ -0,0 +1,25 @@
import { httpUrl } from '../task/fetch';
export const editorConfig = {
placeholder: '请输入',
uploadImgServer: httpUrl + '/busiAttachments/upload',
uploadFileName: 'file',
uploadImgHeaders: {
'X-Requested-With': 'XMLHttpRequest'
},
excludeMenus: [
'list',
'todo',
'emoticon',
'video'
],
uploadImgHooks: {
// 图片上传并返回了结果,想要自己把图片插入到编辑器中
customInsert: function (insertImgFn, result) {
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
if (result && result.data && result.data.id) {
insertImgFn(`${httpUrl}/busiAttachments/view/${result.data.id}`);
}
}
},
}

View File

@ -0,0 +1,54 @@
import React, { useEffect, useState, memo } from 'react';
import { Icon, } from 'antd';
import classNames from 'classnames';
import './index.scss';
export default memo((props) => {
const { options, changeOptionId, type } = props;
const [myOptions, setMyOptions] = useState(()=>{
return JSON.parse(JSON.stringify(options));
});
const [option, setOption] = useState({
name: '综合',
type: 'default',
});
useEffect(() => {
changeOptionId(option, type);
}, [option]);
function itemClick(activeItem) {
const newOption = {
...activeItem,
desc: !activeItem.desc
};
for (const item of myOptions) {
if (item.type === activeItem.type) {
item.desc = newOption.desc;
}
}
setOption(newOption);
setMyOptions(myOptions);
}
console.log('-----options----')
return (
<div className="sort-box">
{
myOptions.map((item) => {
return <div className={classNames({ "sort-item-checked": option.type === item.type, "sort-item": true })} key={item.type} onClick={() => { itemClick(item) }} >
{item.name}
{
item.icon && <span className="caret-up-down">
<Icon type="caret-up" className={classNames({ "caret-checked": !item.desc })} />
<Icon type="caret-down" className={classNames({ "caret-checked": item.desc })} />
</span>}
</div>
})
}
</div>
)
})

View File

@ -0,0 +1,40 @@
.sort-box {
display: flex;
justify-content: start;
align-items: center;
margin-left: 10px;
font-size: 1rem;
.sort-item {
display: flex;
align-items: center;
color: #333;
padding: 0 20px;
background-color: #fff;
&:hover {
background-color: #fff;
color: #409eff;
cursor: pointer;
}
}
.sort-item-checked {
// background-color: #409eff;
// color: #fff;
color: #409eff;
}
.caret-up-down {
display: inline-flex;
flex-flow: column nowrap;
margin-left:.25em;
font-size: .75em;
color:#ccc;
}
.caret-checked{
color: #409eff;
}
.anticon-caret-up{
margin-bottom: -.15em;
}
.anticon-caret-down{
margin-top: -.15em;
}
}

View File

@ -0,0 +1,26 @@
import React, { useEffect, useState ,memo} from 'react';
import classNames from 'classnames';
import './index.scss';
export default memo((props) => {
const { options, changeOptionId, type } = props;
const [option, setOption] = useState({ code: "", dicItemName: "" ,dicItemCode:""});
useEffect(() => {
changeOptionId(option, type);
}, [option])
return (
<div className="status-list">
<div className={classNames({ "status-item-checked": option.dicItemCode === "", "status-item": true })} key={"all"} onClick={() => { setOption({ dicItemCode: "", dicItemName: "" }) }}>全部</div>
{
options.map((item) => {
return <div className={classNames({ "status-item-checked": option.dicItemCode === item.dicItemCode, "status-item": true })} key={item.dicItemCode} onClick={() => { setOption(item) }} >{item.dicItemName}</div>
})
}
</div>
)
})

View File

@ -0,0 +1,21 @@
.status-list {
padding: 1rem 0;
display: flex;
justify-content: start;
flex-wrap: wrap;
}
.status-item {
font-size: 14px;
color: #666;
text-align: center;
padding: 3px 15px;
cursor: pointer;
&:hover {
color: #4cacff;
}
}
.status-item-checked {
background: #f7f7f7;
color: #4cacff ;
}

50
src/military/expert.js Normal file
View File

@ -0,0 +1,50 @@
import React, { Component } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import './index.scss';
const Register = Loadable({
loader: () => import("./expert/register"),
loading: Loading,
});
const Review = Loadable({
loader: () => import("./expert/review/review"),
loading: Loading,
});
class Expert extends Component {
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
<Route
path="/expert/register"
render={(props) => (
<Register {...this.props} {...props} />
)}
></Route>
<Route
path="/expert"
render={(props) => (
<Review {...this.props} {...props} />
)}
></Route>
</Switch>
</div>
);
}
}
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Expert))))
);

View File

@ -0,0 +1 @@
import fetch from './fetch';

View File

@ -0,0 +1,10 @@
import javaFetch from '../javaFetch';
let settings=JSON.parse(localStorage.chromesetting);
let actionUrl = settings.api_urls ? settings.api_urls.expert :'http://10.47.38.56:8088';
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;
export default service;

View File

@ -0,0 +1,41 @@
// 公共样式
.but41_fill, .but41_border, .butE3_border{
padding: 0 18px;
height: 36px;
border-radius: 4px;
cursor: pointer;
}
.but41_fill{
color: white;
background-color: #4154F1;
&:hover{
background-color: #5D6EFF;
}
&:active{
background-color: #374BF2;
}
}
.but41_border{
color: #4154F1;
border: 1px solid #4154F1;
&:hover{
color: #5D6EFF;
border: 1px solid #5D6EFF;
}
&:active{
color: #374BF2;
border: 1px solid #374BF2;
}
}
.butE3_border{
color: #404660;
border: 1px solid #E3E7ED;
&:hover{
background-color: #F8F8F8;
border: 1px solid #E3E7ED;
}
&:active{
background-color: #F3F3F3;
border: 1px solid #E3E7ED;
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="8px" height="8px" viewBox="0 0 8 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>必填@2x</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="3-专家资料附件样式" transform="translate(-551.000000, -189.000000)" fill="#FF3838" fill-rule="nonzero">
<g id="姓名" transform="translate(551.000000, 180.000000)">
<g id="必填" transform="translate(0.000000, 9.000000)">
<path d="M4.27654412,3.29770588 C4.65431878,3.11552402 5.02835189,2.92568336 5.39841176,2.72830147 C5.75230147,2.53817647 6.03840441,2.39605147 6.24922059,2.30852206 C6.46005882,2.22194118 6.62569853,2.17488971 6.75370588,2.17488971 C6.96452206,2.17488971 7.14525,2.24547794 7.30334559,2.39605147 C7.45394118,2.54664706 7.53677206,2.72830147 7.53677206,2.94946324 C7.53677206,3.07652206 7.49911765,3.21017647 7.42383088,3.34475735 C7.34852206,3.47936029 7.26571324,3.56688971 7.18288235,3.60641912 C6.40736029,3.93017647 5.54148529,4.16735294 4.60782353,4.30947794 C4.78098529,4.46759559 4.98430147,4.68970588 5.23275,4.96641176 C5.48124265,5.24311765 5.60922794,5.38524265 5.62429412,5.40875735 C5.71464706,5.54336029 5.84265441,5.70994853 6.00829412,5.90759559 C6.17395588,6.10524265 6.28689706,6.25581618 6.34711765,6.36593382 C6.40733824,6.477 6.44499265,6.61065441 6.44499265,6.76969853 C6.44594618,6.96841039 6.36731868,7.15923578 6.22665441,7.29959559 C6.07968409,7.45302778 5.87428811,7.53655013 5.66194853,7.52922794 C5.43606618,7.52922794 5.17252941,7.339125 4.88640441,6.96734559 C4.60030147,6.60311029 4.22382353,5.93205882 3.77205882,4.95888971 C3.31277206,5.82853676 3.00405882,6.41393382 2.85346324,6.69063971 C2.69534559,6.96734559 2.54477206,7.18005882 2.40169853,7.32311029 C2.27249489,7.45965707 2.09274292,7.53694212 1.90475735,7.53677206 C1.69176274,7.5427387 1.48730495,7.45293529 1.34759559,7.29205147 C1.21205332,7.15136352 1.13414528,6.96499497 1.12923529,6.76969853 C1.12923529,6.59558824 1.15934559,6.46852941 1.21958824,6.38194853 C1.77677206,5.59136029 2.35652206,4.894875 2.95888235,4.31794853 C2.50348809,4.24448093 2.0513352,4.15216638 1.60358824,4.04124265 C1.16806177,3.92483944 0.742549134,3.773769 0.331125,3.58947794 C0.255816176,3.550875 0.188051471,3.46334559 0.120286765,3.32876471 C0.0465462897,3.21881617 0.0072275008,3.08939438 0.00734558824,2.95700735 C0.000185417937,2.74722261 0.0855322486,2.54488078 0.240772059,2.40359559 C0.380985405,2.25952228 0.574326753,2.17952584 0.775345588,2.18241176 C0.918419118,2.18241176 1.099125,2.22946324 1.31746324,2.31699265 C1.53582353,2.41111765 1.80688235,2.53817647 2.14570588,2.71983088 C2.48452941,2.89394118 2.86100735,3.09158824 3.29018382,3.30522794 C3.214875,2.90241176 3.14711029,2.443125 3.09441176,1.92924265 C3.04169118,1.41536029 3.019125,1.05959559 3.019125,0.869470588 C3.019125,0.632294118 3.08688971,0.434647059 3.22994118,0.268058824 C3.36156326,0.0990585155 3.56543001,0.00235741925 3.77958088,0.00734558824 C3.99794118,0.00734558824 4.17864706,0.0939485294 4.32169853,0.260536765 C4.46477206,0.434647059 4.53253676,0.655830882 4.53253676,0.932536765 C4.53253676,1.01159559 4.51747059,1.16216912 4.50240441,1.38430147 C4.48736029,1.61300735 4.44970588,1.88216912 4.41205147,2.19840441 C4.366875,2.52218382 4.32169853,2.88547059 4.27652206,3.29770588 L4.27654412,3.29770588 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,241 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Button, Icon, Form, Modal, Input, Cascader } from 'antd';
import { Link } from "react-router-dom";
import { unitType, natureOfWork, highestEducation, positionLevel, professionalType, reviewArea } from '../static';
import './index.scss';
import '../index.scss';
export default Form.create()(({ match, history, showNotification, form }) => {
const { getFieldDecorator, validateFields, setFieldsValue } = form;
// form
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, validateFirst: true, getValueFromEvent: e => e.target.value.replace(/(^\s*)|(\s*$)/g, "") })(widget)}
</Form.Item>
),
[]
);
return (
<div className="centerbox detail">
<div className="navigation">
<span>专家评审系统</span>&nbsp;&gt;&nbsp;<span>登记专家资料</span>
</div>
<div className='center_flex'>
<div className='register_left'>
<button className="but41_fill">登记专家资料</button>
</div>
<div className='register_right'>
<p>专家资料</p>
<div>
<table>
<tr>
<td>
{
helper('姓名',
'readerName',
[{ required: true, message: "请输入用户姓名" }, { max: 50, message: '不能超过50字符' }],
<Input
placeholder="请输入您的姓名"
/>
)
}
</td>
<td>
{
helper('最高学历',
'companyName',
[{ required: true, message: 'Please select your habitual residence!' }],
<Cascader placeholder= "请选择" options={highestEducation}/>
)
}
</td>
</tr>
<tr>
<td>
{
helper('手机号码',
'contactInfo',
[{ required: true, message: "请输入联系方式" },
{ max: 100, message: '不能超过100字符' },
{
validator: (rule, val, callback) => {
const pattern = /^((\+)?86|((\+)?86)?)0?1[3458]\d{9}$/;
if (pattern.test(val)) {
callback();
} else {
callback('请输入正确的手机号码!');
}
}
}],
<Input
placeholder="请输入您的手机号码"
/>
)
}
</td>
<td>
{
helper('工作单位',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的工作单位"
/>
)
}
</td>
</tr>
<tr>
<td>
{
helper('单位类别',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={unitType} />
)
}
</td>
<td>
{
helper('工作性质',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={natureOfWork} />
)
}
</td>
</tr>
<tr>
<td>
{helper('专业职称',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的专业职称"
/>)}
</td>
<td>
{helper('职称职级',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={positionLevel} />)}
</td>
</tr>
<tr>
<td>
{helper('专业类别',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={professionalType} />)}
</td>
<td>
{helper('评审领域1',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={reviewArea} />)}
</td>
</tr>
<tr>
<td>
{helper('评审领域2',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={reviewArea} />)}
</td>
<td>
{helper('评审领域3',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Cascader placeholder="请选择" options={reviewArea} />)}
</td>
</tr>
<tr>
<td>
{helper('毕业院校',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的毕业院校"
/>)}
</td>
<td>
{helper('院校专业',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的专业"
/>)}
</td>
</tr>
<tr>
<td>
{helper('身份证号',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的身份证号码"
/>)}
</td>
<td>
{helper('邮箱地址',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的常用邮箱地址"
/>)}
</td>
</tr>
<tr>
<td>
{helper('开户银行',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的开户银行"
/>)}
</td>
<td>
{helper('银行账号',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入您的银行卡号"
/>)}
</td>
</tr>
<tr>
<td>
<span>个人简介</span>
<button>上传个人简介</button>
</td>
<td>
<span>职称证明</span>
<button>上传职称证明</button>
</td>
</tr>
<tr>
<td>
<span>学术成果</span>
<button>上传学术成果</button>
</td>
<td>
<span>荣誉称号</span>
<button>上传荣誉称号</button>
</td>
</tr>
</table>
</div>
<div className='buts'>
<button className="but41_fill mr20">提交资料</button>
<button className="but41_border mr20">保存资料</button>
<button className="butE3_border">取消</button>
</div>
</div>
</div>
</div>
)
})

View File

@ -0,0 +1,57 @@
.centerbox.detail{
font-size: 20px;
border: 1px solid;
& .navigation{
font-size: 0.6em;
margin: -35px 0 15px;
}
& .center_flex{
display: flex;
justify-content: space-between;
& .register_left{
height: 10em;
font-size: 0.7em;
background-color: white;
padding: 0.4vw;
}
& .register_right{
background-color: white;
&>p{
height: 5.1vh;
line-height: 5.1vh;
border-bottom: 1px solid #EEEEEE;
padding-left: 2em;
color: #181818;
font-size: 0.8em;
font-weight: bold;
}
&>div{
padding: 2em;
&>table{
& .ant-form-item-required::before{
position: relative;
top: -1px;
content: url('./image/required.svg');
}
& .ant-input{
width: 30.1em;
&:focus, &:hover{
border: 1px solid #4154F1 !important;
}
}
& tr td:first-child .ant-row.ant-form-item{
margin-right: 9em;
}
& .ant-input, .ant-input .ant-input-suffix {
background-color: #FFFFFF !important;
}
}
}
& .buts{
font-size: 0.7em;
padding: 1.5em 2em;
background-color: #f5f5f5;
}
}
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>专家icon</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1-专家注册页" transform="translate(-931.000000, -190.000000)">
<g id="编组-3" transform="translate(713.000000, 190.000000)">
<g id="专家icon" transform="translate(218.000000, 0.000000)">
<rect id="矩形" x="0" y="0" width="60" height="60"></rect>
<g id="icon" transform="translate(5.000000, 4.000000)">
<g id="组织专家评审" fill="#333333" fill-rule="nonzero">
<path d="M3.11770945,3.49761811 C3.11492271,3.36209631 3.1687138,3.23153283 3.2661718,3.1372655 C3.36622022,3.04865657 3.49325526,2.99637688 3.62672326,2.98888504 L12.4496289,2.98888504 L12.4496289,7.48269356 C12.450103,7.88563237 12.6193084,8.26997793 12.9162248,8.54255409 C13.2157443,8.82015688 13.6106392,8.97195578 14.019088,8.96649828 L30.6256628,8.96649828 C31.073504,8.98344877 31.5067222,8.80561799 31.8133616,8.47896245 C32.110278,8.2063863 32.2794834,7.82204074 32.2799576,7.41910193 L32.2799576,2.98888504 L41.1028632,2.98888504 C41.2379887,2.98855385 41.3677009,3.04193527 41.4634147,3.1372655 C41.5646992,3.23076578 41.6255588,3.360021 41.6330859,3.49761811 L41.6330859,23.3170095 C41.8573141,23.9253641 42.4372188,24.3295174 43.0858961,24.3295174 C43.7345733,24.3295174 44.314478,23.9253641 44.5387063,23.3170095 L44.5387063,3.49761811 C44.5359821,2.56148343 44.1533081,1.66652008 43.4782609,1.01754451 C42.8080709,0.379339986 41.9223724,0.0161769046 40.9968187,3.88596243e-05 L3.62672326,3.88596243e-05 C2.67828295,-0.00433465779 1.76541073,0.360612829 1.0816543,1.01754451 C0.400828118,1.66434798 0.0106943895,2.55886701 0,3.49761811 L0,47.2910539 C0.0106943895,48.229805 0.400828118,49.1243241 1.0816543,49.7711275 C1.76541073,50.4280592 2.67828295,50.7930067 3.62672326,50.7885936 L20.233298,50.7885936 C20.7954522,50.8182746 21.3272274,50.532092 21.611877,50.0466913 C21.908614,49.5811812 21.908614,48.9860022 21.611877,48.5204921 C21.3184253,48.0467686 20.7900006,47.7705143 20.233298,47.799787 L3.62672326,47.799787 C3.49325526,47.7922952 3.36622022,47.7400155 3.2661718,47.6514066 C3.16391014,47.5604711 3.10916439,47.4275905 3.11770945,47.2910539 L3.11770945,3.49761811 Z M15.5673383,5.97769166 L15.5673383,2.98888504 L29.0562036,2.98888504 L29.0562036,5.97769166 L15.5673383,5.97769166 Z" id="形状"></path>
<path d="M11.940615,18.929187 C11.3988209,18.9154194 10.8903181,19.1896982 10.6044539,19.6498921 C10.3188267,20.1261925 10.3188267,20.7209881 10.6044539,21.1972884 C10.8995061,21.6825503 11.4367887,21.9673158 12.0042418,21.9391908 L31.728526,21.9391908 C32.2885262,21.9594535 32.8157739,21.6757075 33.107105,21.1972884 C33.3939683,20.7224969 33.3919365,20.1274438 33.1018375,19.6546202 C32.8117385,19.1817966 32.2820113,18.9101518 31.728526,18.9503842 L11.940615,18.929187 Z M11.940615,29.8669474 L21.2089077,29.8669474 C21.771062,29.8372664 22.3028372,30.123449 22.5874868,30.6088497 C22.8842238,31.0743598 22.8842238,31.6695387 22.5874868,32.1350488 C22.294035,32.6087724 21.7656104,32.8850267 21.2089077,32.855754 L11.940615,32.855754 C11.4018484,32.8571795 10.8989788,32.5859393 10.6044539,32.1350488 C10.3272225,31.6640431 10.3272225,31.0798555 10.6044539,30.6088497 C10.8995061,30.1235878 11.4367887,29.8388224 12.0042418,29.8669474 L11.940615,29.8669474 Z" id="形状"></path>
</g>
<g transform="translate(25.609756, 25.395349)">
<polygon id="矩形" fill="#999999" points="3.31619216 21.8539034 21.0806678 21.8539034 21.0806678 26.2527878 3.31619216 26.2527878"></polygon>
<g id="编组-2" fill="#333333" fill-rule="nonzero">
<path d="M23.9983967,5.58180217 L12.0765574,0.075352286 C11.8689657,-0.0251174287 11.627648,-0.0251174287 11.4200563,0.075352286 L0.380907507,5.58180217 C0.158205753,5.71635527 0.0156774511,5.95380651 0.000120780161,6.21597981 C-0.00527494294,6.51710193 0.170529421,6.79137428 0.444350891,6.90882586 L6.09908726,9.61316045 C6.20487178,9.63271696 6.31327807,9.63271696 6.41906259,9.61316045 C6.32584093,10.0100205 6.27133057,10.4151944 6.25631652,10.8228473 C6.21854272,13.0286472 7.39269744,15.0734113 9.30435734,16.1309421 C7.67105786,16.6145993 6.18197665,17.5016342 4.9708984,18.7123524 C3.11044804,20.5966976 2.08679334,23.1664209 2.13525499,25.8307868 C2.13525224,26.2570916 2.47566403,26.6031122 2.89657559,26.6046512 L21.4965206,26.6046512 C21.9163538,26.601581 22.2550938,26.2560077 22.2550828,25.8307868 C22.3155355,21.3018461 19.305521,17.3202384 14.9728858,16.1979917 C16.8174399,15.1743025 17.9802127,13.2292917 18.0209266,11.099427 C18.0184384,10.5790059 17.9517192,10.0609414 17.8223212,9.55728577 C18.008209,9.63281666 18.2156991,9.63281666 18.4015869,9.55728577 L23.9515038,6.93117573 C24.2192037,6.80434797 24.3902439,6.53206782 24.3902439,6.23274221 C24.3902439,5.9334166 24.2192037,5.66113646 23.9515038,5.53430869 L23.9983967,5.58180217 Z M20.7048576,25.0597162 L3.70478913,25.0597162 C3.8620379,23.0904716 4.71159482,21.2437043 6.09908726,19.8549896 C7.7462411,18.2104918 9.97632321,17.3046193 12.2889548,17.3406289 C16.6633609,17.2681371 20.3437655,20.6438134 20.7048576,25.0597162 L20.7048576,25.0597162 Z M12.1979273,15.3933963 C9.84041013,15.3332364 7.96017332,13.3803352 7.96017332,10.9918682 C7.96017332,8.60340126 9.84041013,6.65050002 12.1979273,6.59034017 L12.2751627,6.59034017 C13.4201345,6.62385405 14.5077179,7.10551509 15.3094115,7.93412627 C16.0984799,8.76340204 16.5360487,9.87233629 16.5286279,11.0239962 C16.4757666,13.4211163 14.5649215,15.3490369 12.1979273,15.3933963 L12.1979273,15.3933963 Z M17.8857646,8.12968765 C17.7427915,8.19926945 17.6250576,8.31264673 17.5492388,8.45376081 C16.6041322,6.41679515 14.6016514,5.09753922 12.3799822,5.04819896 C10.8013913,5.02832136 9.27669212,5.62918732 8.12651713,6.72443941 C7.64858946,7.20562533 7.25247653,7.76350963 6.95419374,8.37553625 C6.90315678,8.31251581 6.84035536,8.26030218 6.7693804,8.22188088 L2.4855728,6.20480487 L11.7731325,1.57279376 L21.8495969,6.20480487 L17.8857646,8.12968765 Z" id="形状"></path>
<path d="M23.3418956,9.13822566 C22.920984,9.13976467 22.5805722,9.48578518 22.580575,9.91209 L22.580575,12.4264507 C22.5635221,12.713513 22.7050474,12.9864779 22.948058,13.1352283 C23.1910687,13.2839786 23.4954809,13.2839786 23.7384916,13.1352283 C23.9815022,12.9864779 24.1230275,12.713513 24.1059746,12.4264507 L24.1059746,9.91209 C24.1059746,9.48469653 23.7638848,9.13822566 23.3418956,9.13822566 L23.3418956,9.13822566 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,23 @@
import React from "react";
import { Link } from "react-router-dom";
import system from './image/system.svg';
import './review.scss';
import '../index.scss';
function Review(){
return(
<div className="expert_review_system centerbox">
<div className="navigation">
<span>首页</span>&nbsp;&gt;&nbsp;<span>专家评审系统</span>
</div>
<div className="notExpert center_flex">
<img src={system} />
<p className="ne_title">红山开源平台专家评审系统</p>
<p className="ne_tips">您尚未被入选本平台专家团队可提交专家资料进行注册申请加入专家团队</p>
<p className="ne_bar"></p>
<Link to='/expert/register'><button className="but41_fill">专家注册</button></Link>
</div>
</div>)
}
export default Review;

View File

@ -0,0 +1,40 @@
.expert_review_system{
height: 500px;
font-size: 20px;
& .center_flex{
display: flex;
align-items: center;
justify-content: center;
}
& .navigation{
font-size: 0.6em;
margin: -35px 0 15px;
}
& .notExpert{
height: 80%;
flex-direction: column;
background: #FAFCFF;
border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23);
&>img{
width: 5.5vw;
}
& .ne_title{
font-size: 1em;
font-weight: bold;
color: #181818;
}
& .ne_tips{
font-size: 0.75em;
color: #595959;
}
& .ne_bar{
width: 30vw;
border-top: 1px solid #EEEEEE;
margin: 50px 0 30px !important;
}
& .but41_fill{
font-size: 0.7em;
}
}
}

View File

@ -0,0 +1,54 @@
// 专家注册页面需要的静态数据
export const unitType = [
{ value: "企业", label: "企业" },
{ value: "科研院所", label: "科研院所" },
{ value: "高等院校", label: "高等院校" },
{ value: "医疗机构", label: "医疗机构" },
{ value: "行政机关", label: "行政机关" },
{ value: "社会团体", label: "社会团体" },
{ value: "其他", label: "其他" }
];
export const natureOfWork = [
{ value: "研究", label: "研究" },
{ value: "管理", label: "管理" },
{ value: "开发", label: "开发" },
{ value: "服务", label: "服务" },
{ value: "其他", label: "其他" }
];
export const highestEducation = [
{ value: "博士", label: "博士" },
{ value: "硕士", label: "硕士" },
{ value: "本科", label: "本科" },
{ value: "大专", label: "大专" },
{ value: "其他", label: "其他" }
];
export const positionLevel = [
{ value: "正高级", label: "正高级" },
{ value: "副高级", label: "副高级" },
{ value: "中级", label: "中级" },
{ value: "初级", label: "初级" },
{ value: "未取得", label: "未取得" }
];
export const professionalType = [
{ value: "技术类", label: "技术类" },
{ value: "经济类", label: "经济类" },
{ value: "管理类", label: "管理类" }
];
export const reviewArea = [
{ value: "军事理论", label: "军事理论" },
{ value: "政策法规", label: "政策法规" },
{ value: "医学", label: "医学" },
{ value: "电子", label: "电子" },
{ value: "通信", label: "通信" },
{ value: "计算机科学", label: "计算机科学" },
{ value: "软件工程", label: "软件工程" },
{ value: "有机化学", label: "有机化学" },
{ value: "人工智能", label: "人工智能" },
{ value: "文学交流", label: "文学交流" },
{ value: "体育活动", label: "体育活动" }
];

231
src/military/index.scss Normal file
View File

@ -0,0 +1,231 @@
// 本模块公共样式
.color-grey3 {
color: #333;
}
.color-grey9 {
color: #999;
}
.color-orange {
color: #ff6800;
}
.color-deep-blue {
color: #1b8fff;
}
.centerbox {
width: 1200px;
margin: 40px auto;
position: relative;
}
.head-navigation {
position: absolute;
top: -2.3em;
// width: 80vw;
// max-width: 1280px;
// margin: 40px auto;
// position: relative;
span {
display: inline-flex;
align-items: center;
&:hover {
color: #409eff;
}
}
}
.center-content {
background: #fff;
border: 1px solid #dedede;
box-shadow: #eee 0px 1px 1px 3px;
}
.centerScreen {
display: flex;
justify-content: space-between;
height: 46px;
background-color: #fff;
border-bottom: 1px solid #dedede;
}
// 内容标题左侧样式
.center-left-but {
display: flex;
justify-content: start;
align-items: center;
margin-left: 20px;
font-size: 16px;
font-weight: 600;
}
.center-left-butD {
height: 24px;
font-size: 14px;
font-weight: 500;
line-height: 24px;
color: #333;
padding: 0 10px;
background-color: #fff;
border: 1px solid #dedede;
}
.center-left-butD:hover {
background-color: #fff;
color: #409eff;
cursor: pointer;
}
.center-left-butDACT {
background-color: #409eff;
color: #fff;
}
// 内容标题左侧样式
.center-left-but {
display: flex;
justify-content: start;
align-items: center;
margin-left: 20px;
font-size: 16px;
font-weight: 600;
}
// 内容标题右侧样式
.center-right-but {
display: flex;
align-items: center;
}
.center-right-but > span {
margin: 0 10px;
font-size: 16px;
color: #0089ff;
cursor: pointer;
}
// 文件预览modal样式
.file-modal {
width: 800px !important;
.ant-modal-body {
padding-top: 40px;
.pdf-box {
height: 70vh;
overflow-y: scroll;
}
}
.ant-modal-close {
top: 0 !important;
}
.show-img {
width: 100%;
}
.react-pdf__Page__canvas,
.react-pdf__Page__textContent {
margin: 0 auto;
max-width: 100%;
}
}
.edit-input {
max-width: 500px;
}
.link {
color: #0089ff;
cursor: pointer;
&:hover {
color: #509eff;
}
}
.color-grey-a {
color: #aaa;
}
.greater {
position: relative;
top: -1px;
}
.none_panels {
display: flex;
justify-content: center;
align-items: center;
flex-flow: column nowrap;
height: 40vh;
}
.newFooter .footerInfos > ul {
padding: 0 40px;
box-sizing: border-box;
max-width: 25%;
text-align: left;
}
.ant-modal-footer {
text-align: center;
border: 0;
}
// 头像
.head-log-big {
width: 4rem;
height: 4rem;
margin-right: 0.5rem;
border-radius: 50%;
}
.head-log-middle {
width: 3rem;
height: 3rem;
margin-right: 0.35rem;
border-radius: 50%;
}
.head-log-small {
width: 1.25rem;
height: 1.25rem;
margin-right: 0.35rem;
border-radius: 50%;
}
// 富文本样式
.w-e-text table td,
.w-e-text table th {
height: 30px;
}
.editor-w-text {
table td,
table th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
padding: 3px 5px;
height: 30px;
min-height: 30px;
}
table th {
border-bottom: 2px solid #ccc;
text-align: center;
background-color: #f1f1f1;
}
table {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
blockquote {
display: block;
border-left: 8px solid #d0e5f2;
padding: 5px 10px;
margin: 10px 0;
line-height: 1.4;
font-size: 100%;
background-color: #f1f1f1;
}
a {
color: #409eff;
cursor: pointer;
}
}
.text-center{
text-align: center;
}
@media screen and (max-width: 1200px) {
.centerbox {
width: 98%;
}
}

110
src/military/javaFetch.js Normal file
View File

@ -0,0 +1,110 @@
import { notification} from 'antd';
import axios from 'axios';
import cookie from 'react-cookies';
export const TokenKey = 'autologin_forge_military';
export default function javaFetch(actionUrl){
if (window.location.href.indexOf('localhost') < 0) {
axios.defaults.withCredentials = true;
}
// 创建axios实例
const service = axios.create({
baseURL: actionUrl,
timeout: 1800000, // 请求超时时间
});
// request拦截器
service.interceptors.request.use(config => {
if (cookie.load(TokenKey)) {
console.log(cookie.load(TokenKey));
config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
}
if (window.location.port === "3007") {
// 模拟token为登录用户
const osredmToken = sessionStorage.osredmToken;
if (config.url.indexOf('?') === -1) {
config.url = `${config.url}?token=${osredmToken}`;
} else {
config.url = `${config.url}&token=${osredmToken}`;
}
}
return config;
}, error => {
// Do something with request error
console.log(error); // for debug
Promise.reject(error);
});
// respone拦截器
service.interceptors.response.use(
response => {
const res = response;
if (res.status === 400) {
notification.open({
message: "提示",
description: res.data.message || '验证失败',
});
return Promise.reject('error');
}
if (res.status === 401) {
notification.open({
message: "提示",
description: res.data.message || '未授权,请登录!',
});
return Promise.reject('error');
}
if (res.status === 403) {
notification.open({
message: "提示",
description: res.data.message || '无权限',
});
return Promise.reject('error');
}
if (res.status === 40001) {
notification.open({
message: "提示",
description: '账户或密码错误!',
});
return Promise.reject('error');
}
if (response.status !== 200 && res.status !== 200) {
notification.open({
message: "提示",
description: res.message,
});
} else {
return response.data;
}
},
error => {
console.log(error);
let res = error.response||{};
if (res.status === 400) {
notification.open({
message: "提示",
description: res.data.message || '操作失败',
});
return Promise.reject('error');
}
if (res.status === 401) {
notification.open({
message: "提示",
description: res.data.message || '登录信息已过期',
});
return Promise.reject('error');
}
if (res.status === 403) {
notification.open({
message: "提示",
description: res.data.message || '无权限!',
});
window.location.href="/403";
return Promise.reject('error');
}
return Promise.reject(error);
}
);
return service;
}

53
src/military/notice.js Normal file
View File

@ -0,0 +1,53 @@
import React, { Component } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import './index.scss';
const NoticeList = Loadable({
loader: () => import("./notice/noticeList"),
loading: Loading,
});
const NoticeDetail = Loadable({
loader: () => import("./notice/noticeDetail"),
loading: Loading,
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
<Route
path="/notice/noticeDetail/:noticeId"
render={(props) => (
<NoticeDetail {...this.props} {...props} />
)}
></Route>
<Route
path="/notice"
render={(props) => (
<NoticeList {...this.props} {...props} />
)}
></Route>
</Switch>
</div>
);
}
}
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
);

View File

@ -0,0 +1,49 @@
import fetch from './fetch';
import { notification } from 'antd';
// 公告列表查询
export async function getNoticeList(params) {
let res = await fetch({
url: '/api/announcements/',
method: 'get',
params,
});
if (res.message === 'success') {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 公告详情查询
export async function getNoticeDetail(id) {
let res = await fetch({
url: '/api/announcements/' + id,
method: 'get',
params:{flag:1}
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
//新增加密公告申请人
export function addReader(data) {
return fetch({
url: '/api/request_contact_reader_info/',
method: 'post',
data: data
});
}

View File

@ -0,0 +1,23 @@
import React from 'react';
import { NewSvg } from '../../svg';
import './index.scss';
export default (props) => {
const { list, itemClick, } = props;
return (
list.map(item => {
return (
<div className="list-box" key={item.id}>
<div className="list-title" onClick={() => { itemClick(item.id) }}>
{item.achievementName || item.title} {item.new && <NewSvg color="#ffb300"/>}
</div>
<div className="list-other">
{item.publisher && <p>发布单位{item.publisher}</p>}
<p>发布时间{(item.publishDate && item.publishDate.split(' ')[0]) || (item.createTime && item.createTime.split(' ')[0])}</p>
<p><i className="iconfont icon-dianjiliang mr5 font-12" />{item.visits || 0}</p>
</div>
</div>
)
})
)
}

View File

@ -0,0 +1,47 @@
.list-box {
position: relative;
padding: 17px 20px;
background: #fff;
border-bottom: 1px dashed #dedede;
}
.list-title {
font-size: 1rem;
color: #000;
cursor: pointer;
display: flex;
align-items: center;
svg {
margin-left: 0.5rem;
}
}
.list-title:hover {
color: #409eff;
}
.list-title span {
padding: 3px 5px;
margin-left: 0.5em;
background: #f8c753;
font-size: 13px;
color: #fff;
border-radius: 3px;
}
.list-other {
margin-top: 0.5rem;
display: flex;
align-items: center;
& > p {
display: inline-block;
font-size: 0.875rem;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
p:first-child{
width: 50%;
}
p:nth-child(2){
width: 40%;
}
}

View File

@ -0,0 +1,10 @@
import javaFetch from '../javaFetch';
let settings=JSON.parse(localStorage.chromesetting);
let actionUrl = settings.api_urls? settings.api_urls.notice :'https://info.osredm.com';
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;
export default service;

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -0,0 +1,172 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Button, Icon, Form, Modal, Input } from 'antd';
import { Link } from "react-router-dom";
import { getNoticeDetail, addReader } from '../api';
import { noticeType } from '../static';
import './index.scss';
const noticeTypeArr = [];
for (const item of noticeType) {
noticeTypeArr[item.code] = item.name;
}
export default Form.create()(({ match, history, showNotification, form }) => {
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [reload, setReload] = useState(0);
const [noticeData, setNoticeData] = useState({});
const [visible, setVisible] = useState(false);
const [readerName,setReaderName]=useState('');
const id = match.params.noticeId;
useEffect(() => {
id && getNoticeDetail(id).then(data => {
if (data) {
data.publishDate = data.publishDate.split(' ')[0];
data.createdAt = data.createdAt.split(' ')[0];
data.closingDate = data.closingDate.split(' ')[0];
}
setNoticeData(data || {});
})
}, [id, reload]);
// form
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, validateFirst: true ,getValueFromEvent: e=>e.target.value.replace(/(^\s*)|(\s*$)/g, "") })(widget)}
</Form.Item>
),
[]
);
function pushInfo() {
validateFields((err, values) => {
if (!err) {
addReader({
...values,
annId: noticeData.id,
}).then(res => {
if (res.message === "success") {
setVisible(false);
setReload(Math.random());
} else {
res && Modal.error({ content: res.message });
}
})
}
});
}
return (
<div className="centerbox notice-detail">
<div className="head-navigation">
<Link to="/">首页<span className="greater">&nbsp;&gt;&nbsp;</span></Link>
<Link to="/notice">公告<span className="greater">&nbsp;&gt;&nbsp;</span></Link>
<span>公告详情</span>
</div>
<div className="center-content">
{/* <div className="notice-center-content"> */}
<div className="notice-title">
{noticeData.title}
</div>
<div className="notice-detail-content">
<div className="center-author">
<p key={0}>公告类型{noticeTypeArr[noticeData.type]}</p>
{noticeData.publisher && <p key={1}>发布单位{noticeData.publisher}</p>}
<p key={2}>发布时间{noticeData.publishDate || noticeData.createdAt}</p>
<p key={3}>截止时间{noticeData.closingDate}</p>
<p key={4}>浏览{noticeData.visits || 0}</p>
</div>
<div className="content-text">
<div className="notice-content-title"><Icon type="caret-right" />公告主要内容</div>
<div className="editor-w-text" dangerouslySetInnerHTML={{ __html: noticeData.text }}>
</div>
</div>
{
noticeData.contactInfo ? <React.Fragment>
<div className="notice-content-title"><Icon type="caret-right" />联系方式</div>
<div className="content-secret" dangerouslySetInnerHTML={{ __html: noticeData.contactInfo && noticeData.contactInfo.replace(/\n/g, '</br>') }}>
</div>
{
noticeData.blockedView && <Button type="primary" onClick={() => { setVisible(true) }}>申请查看加密内容</Button>
}
</React.Fragment> : ''
}
{
noticeData.fileDownloadPath &&
<React.Fragment>
<div className="notice-content-title"><Icon type="caret-right" />公告附件</div>
<p className="notice-content-download" >
<span onClick={() => { window.open(noticeData.fileDownloadPath) }}>
<i className="iconfont icon-fujian color-green font-14 mr3"></i>{noticeData.fileName}
</span>
<span className="link" onClick={() => { window.open(noticeData.fileDownloadPath) }}>下载</span>
</p>
</React.Fragment>
}
</div>
</div>
<Modal
title="提交信息"
visible={visible}
onOk={pushInfo}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
{
helper('用户姓名',
'readerName',
[{ required: true, message: "请输入用户姓名" }, { max: 50, message: '不能超过50字符' }],
<Input
placeholder="请输入用户姓名"
/>
)
}
{
helper('公司名称',
'companyName',
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
<Input
placeholder="请输入公司名称"
/>
)
}
{
helper('联系方式',
'contactInfo',
[{ required: true, message: "请输入联系方式" },
{ max: 100, message: '不能超过100字符' },
{ validator: (rule,val,callback) =>{
const pattern = /^((\+)?86|((\+)?86)?)0?1[3458]\d{9}$/;
if(pattern.test(val)){
callback();
}else {
callback('请输入正确的手机号码!');
}
}}],
<Input
placeholder="请输入联系方式"
/>
)
}
</Modal>
</div>
)
}
)

View File

@ -0,0 +1,102 @@
.centerbox {
position: relative;
}
.notice-detail {
margin-top: 3.5rem;
.head-navigation {
top: -2.5rem;
}
.center-content {
overflow: auto;
border: 0;
}
}
.notice-detail-content {
padding: 2rem 2.5rem 3rem;
.anticon-caret-right {
color: #1890ff;
font-size: 1rem;
}
}
.notice-title {
margin: 3rem auto 0;
text-align: center;
font-size: 1.375rem;
font-weight: bold;
line-height: 1.375rem;
color: #000000;
}
// 内容详情
.item-content {
padding: 10px 10px 0 30px;
}
.content-notice {
padding: 20px;
}
.center-author {
display: flex;
flex-flow:row wrap-reverse;
justify-content: space-around;
align-items: center;
padding: .5rem;
background: #f9f9f9;
color: #333;
p {
padding: 0 .5rem;
}
}
.content-text {
margin: 1.25rem 0;
min-height: 30vh;
}
.content-secret{
min-height: 2em;
}
.notice-content-title {
margin: 0.5rem 0;
font-size: 1rem;
font-weight: bold;
}
.notice-content-download {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem !important;
padding: 0 1rem;
background: #f9f9f9;
span:hover{
cursor: pointer;
color: #1890ff;
}
}
.form-edit-modal {
.ant-form-item{
display: flex;
}
.ant-form-item-label{
min-width: 5rem;
}
.ant-form-item-control-wrapper{
width: 75%;
display: inline-block;
}
.ant-input-number{
width: 50%;
}
.ant-modal-footer{
border-top: 0;
text-align: center;
}
}

View File

@ -0,0 +1,267 @@
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import { Pagination, Icon, Input, Affix, } from 'antd';
import ItemList from '../components/itemList';
import Nodata from '../../../forge/Nodata';
import Loading from "../../../Loading";
import noticePng from '../image/banner.png';
import { getNoticeList } from '../api';
import './index.scss';
const Search = Input.Search;
export default (props) => {
const [tab, setTab] = useState('0');
const [loading, setLoading] = useState(false);
const [title, setTitle] = useState(undefined);
const [orderBy, setOrderBy] = useState('publishDateDesc');
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [noticeList, setNoticeList] = useState([]);
const [callList, setCallList] = useState([]);
const [changeList, setChangeList] = useState([]);
const [checkList, setCheckList] = useState([]);
const [abandonList, setAbandonList] = useState([]);
const [technologyList, setTechnologyList] = useState([]);
const [dealList, setDealList] = useState([]);
useEffect(() => {
setLoading(true);
if (tab === '0' || tab === '7') {
const params = {
orderBy,
curPage: 1,
isChecked: 1,
pageSize: 5,
status: 1,
type: 1,
title,
flag: 1, //21
};
getNoticeList(params).then(data => {
setChangeList(data.rows);
});
getNoticeList({ ...params, type: 4 }).then(data => {
setCallList(data.rows);
setLoading(false);
});
getNoticeList({ ...params, type: 2 }).then(data => {
setCheckList(data.rows);
});
getNoticeList({ ...params, type: 3 }).then(data => {
setAbandonList(data.rows);
setLoading(false);
});
getNoticeList({ ...params, type: 5 }).then(data => {
setTechnologyList(data.rows);
});
getNoticeList({ ...params, type: 6 }).then(data => {
setDealList(data.rows);
setLoading(false);
});
} else {
const params = {
orderBy,
curPage,
isChecked: 1,
pageSize: 10,
status: 1,
title,
type: tab,
flag: 1, //21
};
getNoticeList(params).then(data => {
setNoticeList(data.rows);
setTotal(data.total);
setLoading(false);
})
}
}, [tab, title, orderBy, curPage]);
function changeSort(sortType) {
setOrderBy(sortType);
setCurPage(1);
}
function noticeClick(id) {
props.history.push(`/notice/noticeDetail/${id}`);
}
function sortNav() {
return <div className="notice-sort-nav">
<Search
size="large"
maxLength={20}
style={{ width: "56%" }}
placeholder="输入标题关键字不能超过20字符"
enterButton={<span><Icon type="search" className="mr5" /> 搜索</span>}
onSearch={(value) => setTitle(value)} />
<div className="center-right-but">
<div className={classNames({ sortLink: true, active: orderBy === 'publishDateDesc' })} onClick={() => { changeSort('publishDateDesc') }}>时间降序<Icon type="arrow-down" /></div>
<span className="piece">|</span>
<div className={classNames({ sortLink: true, active: orderBy === 'publishDateAsc' })} onClick={() => { changeSort('publishDateAsc') }}>时间升序<Icon type="arrow-up" /></div>
</div>
</div>
}
function handleClick(e) {
setTab(e.key);
setCurPage(1);
setTitle('');
setOrderBy('publishDateDesc');
}
function click(e){
console.log("aa");
console.log(e);
setTab(e);
setCurPage(1);
setTitle('');
setOrderBy('publishDateDesc');
}
function cont(param, titleStr, key, svgStr) {
return <React.Fragment>
<div className="item-head-title">
<div className="item-head-title-content">
<i className={svgStr}></i>
<span>{titleStr}</span>
</div>
{param.length === 5 && <span className="link" onClick={() => { handleClick({ key: key }) }}>查看更多 <Icon type="arrow-right" /></span>}
</div>
{param.length > 0 ? <ItemList
list={param}
itemClick={noticeClick}
/> : <Nodata _html="暂无数据" />}
{/* <ItemList
list={param}
itemClick={noticeClick}
/> */}
</React.Fragment>
}
function content() {
if (tab === '0') {
if(callList.length === 0 && changeList.length === 0 && checkList.length === 0 && abandonList.length === 0){
return <React.Fragment><Nodata _html="暂无数据" /></React.Fragment>
}else{
return <React.Fragment>
{cont(callList, "招标公告", '4', "iconfont icon-zhaobiaogonggao")}
{cont(changeList, "更正公告", '1', "iconfont icon-gengzhenggonggao")}
{cont(checkList, "中标公告", '2', "iconfont icon-zhongbiaogonggao")}
{cont(abandonList, "废标公告", '3', "iconfont icon-feibiaogonggao")}
</React.Fragment>
}
} else if (tab === '7') {
{/* {technologyList.length <= 0 && dealList.length <= 0 ? <Nodata _html="暂无数据" /> : ""} */}
{/* {technologyList.length > 0 && cont(technologyList, "技术资产", '5',"iconfont icon-jishuzichan")} */}
if(technologyList.length === 0 && dealList.length === 0){
return <React.Fragment><Nodata _html="暂无数据" /></React.Fragment>
}else{
return <React.Fragment>
{cont(technologyList, "技术资产", '5', "iconfont icon-jishuzichan")}
{cont(dealList, "成交公告", '6', "iconfont icon-chengjiaogonggao")}
</React.Fragment>
}
} else if (tab === '8') {
return <div></div>
} else {
let titleStr;
let svgStr;
switch (tab) {
case '1':
titleStr = "更正公告";
svgStr = "iconfont icon-gengzhenggonggao"
break;
case '2':
titleStr = "中标公告";
svgStr = "iconfont icon-zhongbiaogonggao"
break;
case '3':
titleStr = "废标公告";
svgStr = "iconfont icon-feibiaogonggao"
break;
case '4':
titleStr = "招标公告";
svgStr = "iconfont icon-zhaobiaogonggao"
break;
case '5':
titleStr = "技术资产";
svgStr = "iconfont icon-jishuzichan"
break;
default:
titleStr = "成交公告";
svgStr = "iconfont icon-chengjiaogonggao"
}
return <React.Fragment>
<div className="item-head-title">
<div className="item-head-title-content">
<i className={svgStr}></i>
<span>{titleStr}</span>
</div>
</div>
<ItemList
list={noticeList}
itemClick={noticeClick}
/>
{/* {noticeList.length === 10 && <div className="edu-txt-center mt30 mb30">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>
</div>} */}
{total > 0 ? total> 10 ? <div className="edu-txt-center mt30 mb30">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>
</div> : "" : <Nodata _html="暂无数据" />}
</React.Fragment>
}
}
return (
<React.Fragment>
<img alt="图片加载失败" src={noticePng} width="100%"></img>
<div className="centerbox notice-list clearfix">
{/* <div className="head-navigation">
<Link to="/">首页<span className="greater">&nbsp;&gt;&nbsp;</span></Link>
<span>公告</span>
</div> */}
<div className="body">
<Affix className="affix-list-left" offsetTop={90}>
{/* <div className="affix-list-content"> */}
<div className="navigationMenu">
<ul className="menu-ul">
<li className="MenuTitle" onClick={()=>click('0')}><span><i className="iconfont icon-xiangmugonggao"></i>项目公告</span></li>
<li className={tab === '4' ? "active" : ""} onClick={()=>click('4')}><span>招标公告</span></li>
<li className={tab === '1' ? "active" : ""} onClick={()=>click('1')}><span>更正公告</span></li>
<li className={tab === '2' ? "active" : ""} onClick={()=>click('2')}><span>中标公告</span></li>
<li className={tab === '3' ? "active" : ""} onClick={()=>click('3')}><span>废标公告</span></li>
</ul>
<ul className="menu-ul">
<li className="MenuTitle" onClick={()=>click('7')}><span><i className="iconfont icon-chengguo"></i>成果转化</span></li>
<li className={tab === '5' ? "active" : ""} onClick={()=>click('5')}><span>技术资产</span></li>
<li className={tab === '6' ? "active" : ""} onClick={()=>click('6')}><span>成交公告</span></li>
</ul>
</div>
</Affix>
<div className="notice-center-content">
{sortNav()}
{loading ? <Loading /> : content()}
</div>
</div>
</div>
</React.Fragment>
)
}

View File

@ -0,0 +1,188 @@
.notice-list{
.ant-tabs {
.ant-tabs-left-bar{
border: 1px solid #E5E5E5;
.ant-tabs-nav-container{
margin-right: 0;
}
.ant-tabs-nav-wrap{
margin-right: 0;
}
svg{
margin-right:.75em;
}
}
.ant-tabs-tab{
display: flex;
justify-content: start;
align-items: center;
margin-bottom: 0.5rem;
width: 13.5rem;
height: 2.8125rem;
background: #fff;
font-size: 1.125rem;
}
.ant-tabs-left-content{
border: 0;
}
.ant-tabs-tab-active{
background: #1890FF;
color: #fff;
}
.ant-tabs-ink-bar{
display: none !important;
}
}
.notice-sort-nav{
display: flex;
justify-content: space-between;
padding: .3rem 2rem 1.5rem;
margin: 0px -1.25rem;
// border: 1px solid;
border-bottom: 1px solid #E0E0E0;
// background: #f5f5f5;
}
.notice-center-content{
padding:1.25rem;
background: #fff;
flex: auto;
}
.item-head-title{
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.25rem 0 .6rem 0;
.item-head-title-content{
display: flex;
align-items: center;
font-size: 1rem;
span{
font-weight: bold;
}
i{
margin-right: .25em;
color: #1890FF;
}
}
}
.ant-input-group-addon{
border: 0 !important;
}
.item-head-title{
border-bottom: 1px solid #E5E5E5;
}
}
.center-right-but{
caret-color: rgba(0, 0, 0, 0);
.piece{
margin:0 .8rem;
color: #aaa;
}
.sortLink{
color: #333;
cursor: pointer;
&:hover{
color: #1890FF;
}
&.active{
color: #1890FF;
}
}
}
.body{
display: flex;
justify-content: space-between;
margin-top: -20px;
.navigationMenu{
margin-right: 20px;
width: 20.8em;
caret-color: rgba(0, 0, 0, 0);
}
.none_p_title{
text-align: center;
}
}
.menu-ul{
background-color: white;
margin-bottom: 12px;
border-radius:2px;
.MenuTitle{
border-bottom: 1px solid #E0E0E0;
span{
display: block;
width: 50%;
height: 100%;
cursor: pointer;
border-bottom: 0px solid;
i{
color: #afaaae;
}
}
span:hover{
color: #1484EF;
.iconfont{
color: #1484EF !important;
}
}
}
li{
padding:0px 0px 0px 20px;
position: relative;
height: 62px;
line-height: 62px;
font-size: 16px;
color: #333;
span{
display: block;
height: 62px;
cursor: pointer;
border-bottom: 1px solid #eee;
}
&:last-child > span{
border-bottom: none;
}
}
li:hover{
background: #fafafa;
}
.active{
background-color: #fafafa;
& ::before{
position: absolute;
left: 0px;
top: 15px;
width: 6px;
content: '';
height: 30px;
background: #1484EF;
}
}
& i{
margin-right: 5px;
}
}
.ant-input-group-addon .ant-btn-lg {
height: 40px;
}

View File

@ -0,0 +1,22 @@
// 公告开始
export const noticeStatus = [
{ code: 0, name: "关闭", dicItemName: '关闭' },
{ code: 1, name: "正常", dicItemName: '正常' },
{ code: 2, name: "草稿", dicItemName: '草稿' },
];
export const noticeType = [
{ code: 1, name: "更正公告", dicItemName: "更正" },
{ code: 2, name: "中标公告", dicItemName: "中标" },
{ code: 3, name: "废标公告", dicItemName: "废标" },
{ code: 4, name: "招标公告", dicItemName: "招标" },
{ code: 5, name: "技术资产", dicItemName: "技术" },
{ code: 6, name: "成交公告", dicItemName: "成交" },
];
export const noticeChecked = [
{ code: 0, name: "未通过", dicItemName: "未通过" },
{ code: 1, name: "通过", dicItemName: "通过" },
{ code: 2, name: "未处理", dicItemName: "未处理" },
];
//公告结束

View File

@ -0,0 +1,73 @@
import React from 'react';
export function AbandonSvg({ color }) {
return <svg width="16" height="15.198" viewBox="0 0 16 15.198">
<g id="组_96" data-name="组 96" transform="translate(-54.703 -1778.755)">
<g id="组_87" data-name="组 87" transform="translate(63.014 1786.264)">
<path id="路径_334" data-name="路径 334" d="M365.033,2110.025H361.89a.591.591,0,1,1,0-1.183h3.143a.591.591,0,1,1,0,1.183Z" transform="translate(-359.618 -2105.589)" fill={color} />
<path id="路径_335" data-name="路径 335" d="M316.429,2010.462a3.844,3.844,0,1,0,1.126,2.718A3.819,3.819,0,0,0,316.429,2010.462Zm-.739,4.7a2.8,2.8,0,1,1,0-3.959A2.79,2.79,0,0,1,315.69,2015.16Z" transform="translate(-309.866 -2009.336)" fill={color} />
</g>
<g id="组_88" data-name="组 88" transform="translate(54.703 1778.755)">
<path id="路径_336" data-name="路径 336" d="M61.441,1790.478a5.6,5.6,0,0,1,5.545-5.651,5.476,5.476,0,0,1,1.02.1v-4.368a1.808,1.808,0,0,0-1.8-1.8H56.507a1.808,1.808,0,0,0-1.8,1.8v11.02a1.808,1.808,0,0,0,1.8,1.8h5.718A5.705,5.705,0,0,1,61.441,1790.478Zm-4.155-8.229a.7.7,0,0,1,.728-.666h6.692a.7.7,0,0,1,.728.666h0a.7.7,0,0,1-.728.666H58.014a.7.7,0,0,1-.728-.666Zm3.077,7.351h-2.5a.673.673,0,0,1,0-1.332h2.5a.673.673,0,0,1,0,1.332Zm-2.349-3.44a.7.7,0,0,1-.728-.666h0a.7.7,0,0,1,.728-.666h3.18a.7.7,0,0,1,.728.666h0a.7.7,0,0,1-.728.666Z" transform="translate(-54.703 -1778.755)" fill={color} />
</g>
</g>
</svg>
}
export function AllSvg({ color }) {
return <svg width="16" height="15.198" viewBox="0 0 16 15.198">
<g id="组_93" data-name="组 93" transform="translate(696.223 -1778.755)">
<path id="路径_337" data-name="路径 337" d="M-365.778,2071.537l-1.4.948h-.467a.313.313,0,0,0-.311.315v1.263a.314.314,0,0,0,.311.316h.467l1.4.947a.315.315,0,0,0,.221-.094.314.314,0,0,0,.09-.222v-3.157A.314.314,0,0,0-365.778,2071.537Z" transform="translate(-317.611 -283.396)" fill={color} />
<g id="组_90" data-name="组 90" transform="translate(-688.125 1786.051)">
<path id="路径_338" data-name="路径 338" d="M-434.315,2010.493a3.925,3.925,0,0,0-2.794-1.157,3.925,3.925,0,0,0-2.794,1.157,3.925,3.925,0,0,0-1.157,2.794,3.925,3.925,0,0,0,1.157,2.794,3.926,3.926,0,0,0,2.794,1.157,3.926,3.926,0,0,0,2.794-1.157,3.925,3.925,0,0,0,1.157-2.794A3.925,3.925,0,0,0-434.315,2010.493Zm-.76,4.828a2.867,2.867,0,0,1-2.034.841,2.868,2.868,0,0,1-2.034-.841,2.858,2.858,0,0,1-.843-2.034,2.858,2.858,0,0,1,.843-2.034,2.858,2.858,0,0,1,2.034-.843,2.858,2.858,0,0,1,2.034.843A2.88,2.88,0,0,1-435.075,2015.321Z" transform="translate(441.06 -2009.336)" fill={color} />
</g>
<g id="组_91" data-name="组 91" transform="translate(-696.223 1778.755)">
<path id="路径_339" data-name="路径 339" d="M-689.3,1790.466a5.672,5.672,0,0,1,5.7-5.645,5.79,5.79,0,0,1,1.048.1v-4.363a1.832,1.832,0,0,0-1.854-1.8h-9.964a1.832,1.832,0,0,0-1.854,1.8v11.008a1.833,1.833,0,0,0,1.854,1.8h5.877A5.577,5.577,0,0,1-689.3,1790.466Zm-4.27-8.22a.712.712,0,0,1,.748-.665h6.878a.713.713,0,0,1,.748.665h0a.713.713,0,0,1-.748.665h-6.878a.713.713,0,0,1-.748-.665Zm3.163,7.343h-2.573a.633.633,0,0,1-.589-.665.633.633,0,0,1,.589-.665h2.573a.633.633,0,0,1,.589.665A.632.632,0,0,1-690.406,1789.588Zm-2.414-3.437a.713.713,0,0,1-.748-.665h0a.713.713,0,0,1,.748-.665h3.268a.713.713,0,0,1,.748.665h0a.713.713,0,0,1-.748.665Z" transform="translate(696.223 -1778.755)" fill={color} />
</g>
</g>
</svg>
}
export function ChangeSvg({ color }) {
return <svg width="16" height="15.176" viewBox="0 0 16 15.176">
<g id="组_94" data-name="组 94" transform="translate(-703.372 -1778.755)">
<path id="路径_331" data-name="路径 331" d="M1034.307,2069.547a1.2,1.2,0,0,0-1.2.934,1.17,1.17,0,0,0,.707,1.326c.044.219.063.475-.073.573a1.129,1.129,0,0,0-.885.486v.422h2.865v-.393a1.414,1.414,0,0,0-.949-.523.751.751,0,0,1-.032-.554,1.172,1.172,0,0,0,.739-1.309,1.2,1.2,0,0,0-1.175-.961Z" transform="translate(-318.75 -281.318)" fill={color} />
<path id="路径_332" data-name="路径 332" d="M965.772,2010.458a3.832,3.832,0,1,0,1.122,2.709A3.807,3.807,0,0,0,965.772,2010.458Zm-.737,4.682a2.79,2.79,0,1,1,0-3.946A2.781,2.781,0,0,1,965.035,2015.141Z" transform="translate(-247.522 -223.068)" fill={color} />
<g id="组_85" data-name="组 85" transform="translate(703.372 1778.755)">
<path id="路径_333" data-name="路径 333" d="M710.088,1790.463a5.586,5.586,0,0,1,5.527-5.643,5.441,5.441,0,0,1,1.017.1v-4.362a1.8,1.8,0,0,0-1.8-1.8H705.17a1.8,1.8,0,0,0-1.8,1.8v11.005a1.8,1.8,0,0,0,1.8,1.8h5.7A5.705,5.705,0,0,1,710.088,1790.463Zm-4.141-8.218a.7.7,0,0,1,.726-.665h6.67a.7.7,0,0,1,.726.665h0a.7.7,0,0,1-.726.665h-6.67a.7.7,0,0,1-.726-.665Zm3.067,7.341h-2.5a.673.673,0,0,1,0-1.33h2.5a.673.673,0,0,1,0,1.33Zm-2.341-3.436a.7.7,0,0,1-.726-.665h0a.7.7,0,0,1,.726-.665h3.169a.7.7,0,0,1,.726.665h0a.7.7,0,0,1-.726.665Z" transform="translate(-703.372 -1778.755)" fill={color} />
</g>
</g>
</svg>
}
export function CheckSvg({ color }) {
return <svg width="16" height="14.548" viewBox="0 0 16 14.548">
<g id="组_95" data-name="组 95" transform="translate(-1325.073 -1778.755)">
<path id="路径_325" data-name="路径 325" d="M1655.311,1844.214" transform="translate(-319.943 -63.419)" fill={color} />
<path id="路径_326" data-name="路径 326" d="M1680.948,2109.083a.659.659,0,1,0-.407.609.659.659,0,0,0,.407-.609Z" transform="translate(-343.504 -319.392)" fill={color} />
<g id="组_82" data-name="组 82" transform="translate(1333.053 1785.974)">
<path id="路径_327" data-name="路径 327" d="M1587.227,2013.456a2.664,2.664,0,1,1-1.177-1.812l.058-.378.585-.39a3.665,3.665,0,1,0,1.565,3,3.7,3.7,0,0,0-.064-.686l-.541.361Z" transform="translate(-1580.931 -2010.216)" fill={color} />
<path id="路径_328" data-name="路径 328" d="M1645.528,2074.812a1.261,1.261,0,1,1-.58-2.115l.479-.319a1.734,1.734,0,1,0,.941,1.542c0-.008,0-.016,0-.023l-.514.349A1.254,1.254,0,0,1,1645.528,2074.812Z" transform="translate(-1640.971 -2070.255)" fill={color} />
</g>
<g id="组_83" data-name="组 83" transform="translate(1337.198 1786.341)">
<path id="路径_329" data-name="路径 329" d="M1717.735,2023.462h-.009l-.741-.124h0a.373.373,0,0,1-.271-.406v0l.186-.693,0-.01a.092.092,0,0,0-.05-.125l-.01,0-.009-.006a.132.132,0,0,0-.074-.023.134.134,0,0,0-.075.023l-1.335.89-.133.628-1.246.831.005,0a1.024,1.024,0,0,1,.608.916l1.238-.84.628.121,1.34-.893.005,0c.04-.02.049-.053.05-.148C1717.805,2023.516,1717.773,2023.462,1717.735,2023.462Z" transform="translate(-1713.97 -2022.066)" fill={color} />
</g>
<path id="路径_330" data-name="路径 330" d="M1331.495,1789.957a5.343,5.343,0,0,1,5.285-5.4,5.206,5.206,0,0,1,.972.091v-4.174a1.725,1.725,0,0,0-1.719-1.72h-9.24a1.725,1.725,0,0,0-1.719,1.72v10.53a1.725,1.725,0,0,0,1.719,1.72h5.45A5.462,5.462,0,0,1,1331.495,1789.957Zm-3.96-7.863a.669.669,0,0,1,.694-.636h6.378a.669.669,0,0,1,.694.636h0a.669.669,0,0,1-.694.636h-6.378a.669.669,0,0,1-.694-.636Zm2.933,7.024h-2.386a.644.644,0,0,1,0-1.272h2.386a.644.644,0,0,1,0,1.272Zm-2.239-3.287a.669.669,0,0,1-.694-.636h0a.669.669,0,0,1,.694-.636h3.031a.669.669,0,0,1,.694.636h0a.669.669,0,0,1-.694.636Z" transform="translate(0 0)" fill={color} />
</g>
</svg>
}
export function NewSvg({ color }) {
return <svg width="33.091" height="14" viewBox="0 0 33.091 14">
<g id="组_137" data-name="组 137" transform="translate(-294 -259)">
<path id="路径_346" data-name="路径 346" d="M324.546,259h-28A2.553,2.553,0,0,0,294,261.545v8.909A2.553,2.553,0,0,0,296.545,273h28a2.553,2.553,0,0,0,2.545-2.545v-8.909A2.553,2.553,0,0,0,324.546,259ZM302.9,269.818a.642.642,0,0,1-.445.611.983.983,0,0,1-.191.025.664.664,0,0,1-.535-.28l-3.907-5.893v5.524a.636.636,0,1,1-1.273.013v-7.636a.632.632,0,0,1,1.158-.356l3.92,5.88v-5.524a.636.636,0,1,1,1.273,0Zm8.285-4.455a.636.636,0,1,1,0,1.273h-4.455v2.546h4.455a.636.636,0,1,1,0,1.273h-5.091a.63.63,0,0,1-.636-.636v-7.636a.63.63,0,0,1,.636-.636h5.091a.636.636,0,0,1,0,1.273h-4.455v2.545Zm13.211-3.029-2.52,7.522a.63.63,0,0,1-1.2,0l-1.922-5.74-1.922,5.74a.659.659,0,0,1-1.2,0l-2.52-7.522a.636.636,0,0,1,1.209-.395l1.922,5.74,1.922-5.74a.659.659,0,0,1,1.2,0l1.922,5.74,1.922-5.74a.624.624,0,1,1,1.184.395Zm0,0" fill={color} />
</g>
</svg>
}
export function CallSvg({ color }) {
return <svg width="13.925" height="16" viewBox="0 0 13.925 16">
<path id="路径_350" data-name="路径 350" d="M1822.1,2425.528h-1.478a1.674,1.674,0,0,1-1.68,1.68h-5.371a1.674,1.674,0,0,1-1.68-1.68h-1.461a1.122,1.122,0,0,0-1.117,1.117v12.485a1.122,1.122,0,0,0,1.117,1.117h11.691a1.122,1.122,0,0,0,1.117-1.117v-12.481A1.155,1.155,0,0,0,1822.1,2425.528Zm-10.052,4.009h4.306a.77.77,0,1,1,0,1.539h-4.306a.77.77,0,1,1,0-1.539Zm0,3.463h4.306a.77.77,0,1,1,0,1.54h-4.306a.77.77,0,0,1,0-1.54Zm5.358,4.781h-5.382a.77.77,0,0,1,0-1.54h5.382a.77.77,0,0,1,0,1.54Zm2.92.052a.822.822,0,1,1,.822-.822A.822.822,0,0,1,1820.33,2437.833Zm.028-4.967-1.245.953v-3.9a.362.362,0,0,1,.331-.382h1.816a.362.362,0,0,1,.331.382l.01,3.9Zm-1.673-6.569h-4.871a1.034,1.034,0,0,1-1.025-1.025,1.045,1.045,0,0,1,1.025-1.025h4.871a1.025,1.025,0,0,1,0,2.049Zm0,0" transform="translate(-1809.317 -2424.247)" fill={color} />
</svg>
}

118
src/military/task.js Normal file
View File

@ -0,0 +1,118 @@
import React, { Component, useEffect, useState } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../Loading";
import { getUserInfo } from './task/api';
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import './index.scss';
const TaskList = Loadable({
loader: () => import("./task/taskList"),
loading: Loading,
});
const TaskDetail = Loadable({
loader: () => import("./task/taskDetail"),
loading: Loading,
});
const TaskEdit = Loadable({
loader: () => import("./task/taskEdit"),
loading: Loading,
});
const MyTask = Loadable({
loader: () => import("./task/myTask"),
loading: Loading,
});
const TaskAdminRouter = Loadable({
loader: () => import("./task/taskAdminRouter"),
loading: Loading,
});
const Index = (propsTransmit) => {
// 开发时,从代理的位置获取用户信息
const [currentUser, setCurrentUser] = useState(propsTransmit.current_user);
// const isDev = window.location.href.indexOf('3007') > -1 ? true : false;
useEffect(() => {
getUserInfo().then(res => {
if (res && res.data) {
setCurrentUser(res.data);
}
})
}, [])
let propsF = { ...propsTransmit };
propsF.current_user = currentUser;
return (
<div className="newMain clearfix">
<Switch {...propsF}>
{/* 任务详情 */}
<Route
path="/task/taskDetail/:taskId"
render={(props) => (
<TaskDetail {...propsF} {...props} />
)}
></Route>
{/* 新增任务 */}
<Route
path="/task/taskAdd"
render={(props) => (
<TaskEdit {...propsF} {...props} />
)}
></Route>
{/* 编辑任务 */}
<Route
path="/task/taskEdit/:taskId"
render={(props) => (
<TaskEdit {...propsF} {...props} />
)}
></Route>
{/* 我的任务 */}
<Route
path="/task/myTask"
render={(props) => (
<MyTask {...propsF} {...props} />
)}
></Route>
{/* 管理员管理 */}
<Route
path="/task/:admin"
render={(props) => (
<TaskAdminRouter {...propsF} {...props} />
)}
></Route>
{/* 任务列表 */}
<Route
path="/task"
render={(props) => (
<TaskList {...propsF} {...props} />
)}
></Route>
</Switch>
</div>
);
}
// }
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
);

View File

@ -0,0 +1,206 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Input, Button, Form, Select } from 'antd';
import ItemAgreementManage from '../components/itemAgreementManage';
import StatusNav from '../../components/statusNav';
import { agreementArr } from '../static';
import { agreementList } from '../api';
import '../index.scss';
const Option = Select.Option;
const agreementOptionArr = agreementArr.slice(0, 2);
export default Form.create()(({ form, showNotification, match, history }) => {
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [approve, setApprove] = useState(1);
const [loading, setLoading] = useState(false);
const [searchObj, setSearchObj] = useState({});
const [status, setStatus] = useState('2');
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [taskList, setTaskList] = useState([]);
const [type, setType] = useState('1');
const [reload, setReload] = useState(0);
const [loadPaper, setLoadPaper] = useState(0);
// 加载审核协议列表
useEffect(() => {
const params = {
...searchObj,
status,
type,
currentPage: curPage,
pageSize: 10,
};
setLoading(true);
agreementList(params).then(data => {
if (data) {
if (loadPaper === 0 && data.rows.length === 0) {
setLoadPaper(1);
} else {
setLoadPaper(2);
}
setTaskList(data.rows);
setTotal(data.total);
}
setLoading(false);
});
}, [reload, status, curPage, searchObj, type]);
// 如果第一次加载任务协议审核发现没有数据,那么切换成审核成果协议列表
useEffect(() => {
if (loadPaper === 1) {
const params = {
status: '2',
type: '2',
currentPage: 1,
pageSize: 10,
};
setLoading(true);
agreementList(params).then(data => {
if (data && data.rows.length > 0) {
setTaskList(data.rows);
setTotal(data.total);
setType('2');
setLoadPaper(2);
}
setLoading(false);
});
}
}, [loadPaper]);
// form表单公共处理函数
const helper = useCallback(
(name, rules, widget, initialValue) => (
<Form.Item>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
</Form.Item>
), []);
function onSearch() {
validateFields((err, values) => {
if (!err) {
setSearchObj(values);
}
});
}
// 修改选项
const changeOptionId = useCallback((option) => {
setStatus(option.dicItemCode.toString() || '0,1');
setCurPage(1);
}, []);
// 修改状态
function changeApprove(approve) {
setApprove(approve);
setCurPage(1);
if (approve === 1) {
setStatus('2');
} else {
setStatus('0,1');
}
}
// 清除查询内容
function clearSearch() {
setFieldsValue({
taskNumber: '',
taskName: '',
userName: ''
});
setSearchObj({});
}
// 刷新数据
const reloadList = useCallback(() => {
setReload(Math.random());
}, []);
return (
<div className="centerbox task-manage">
<div className="center-screen" >
<div className="center-left-but">
{helper(
"type",
[],
<Select
showArrow
placeholder="请选择协议"
onChange={(type) => { setType(type) }}
>
<Option key={'1'}>委托协议</Option>
<Option key={'2'}>成果协议</Option>
</Select>,
type
)}
<Button className="circle-button" type={approve === 1 ? 'primary' : ''} onClick={() => { changeApprove(1) }}>待审批</Button>
<Button className="circle-button" type={approve === 2 ? 'primary' : ''} onClick={() => { changeApprove(2) }}>已审批</Button>
</div>
<div className="center-right-but">
{helper(
"taskNumber",
[{ max: 20, message: '长度不能超过20个字符' }],
<Input
placeholder="输入任务编号进行检索"
/>
)}
{helper(
"taskName",
[{ max: 20, message: '长度不能超过20个字符' }],
<Input
placeholder="输入任务名称进行检索"
/>
)}
{helper(
"userName",
[{ max: 20, message: '长度不能超过20个字符' }],
<Input
placeholder="输入发布人名称进行检索"
/>
)}
<Button className="mr10" type="primary" onClick={onSearch}>搜索</Button>
<Button className="mr10" type="" onClick={clearSearch}>清除</Button>
</div>
</div>
<div className="center-content">
{
approve === 2 && <StatusNav
key={'status'}
type={'status'}
options={agreementOptionArr}
changeOptionId={changeOptionId}
/>
}
<ItemAgreementManage
list={taskList}
curPage={curPage}
total={total}
changePage={(page) => { setCurPage(page) }}
loading={loading}
showNotification={showNotification}
reloadList={reloadList}
/>
</div>
</div>
)
}
)

577
src/military/task/api.js Normal file
View File

@ -0,0 +1,577 @@
import fetch, { } from './fetch';
import { notification } from 'antd';
// 获取字典分类列表
export function getDictionary(id) {
return fetch({
url: '/dicItem/getData?dicTypeCode=' + id,
method: 'get'
});
}
// 获取用户信息
export function getUserInfo() {
return fetch({
url: '/user/getUserInfo',
method: 'get'
});
}
// 获取用户企业信息
export function getCompanyInfo() {
return fetch({
url: '/api/tasks/getEnterpriseUserInfo',
method: 'get'
});
}
// 获取任务领域
export async function getTaskCategory() {
let res = await fetch({
url: '/api/taskCategory/getTaskCategory',
method: 'get',
});
if (Array.isArray(res.data.rows)) {
return res.data.rows;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 任务列表查询
export async function getTaskList(params) {
let res = await fetch({
url: '/api/tasks/',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 管理员任务列表查询
export async function getTaskAdminList(params) {
let res = await fetch({
url: '/api/tasks/backend/list',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 我的任务列表查询
export async function getMyTaskList(params) {
let res = await fetch({
url: '/api/myTasks/',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 我参与的任务列表查询
export async function getJoinTaskList(params) {
let res = await fetch({
url: '/api/myTasks/myPapers',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 详情查询
export async function getTaskDetail(id) {
let res = await fetch({
url: '/api/tasks/getTask/' + id,
method: 'get',
});
if (res.data) {
return res.data;
} else {
if(res.message&&res.message.indexOf('exist')>-1){
notification.open({
message: "提示",
description: "未查到该任务",
});
}else{
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
}
//新增任务
export function addTask(data) {
return fetch({
url: '/api/tasks/add',
method: 'post',
data: data
});
}
//更新任务
export function updateTask(data) {
return fetch({
url: '/api/tasks/',
method: 'PUT',
data: data
});
}
//删除
export function deleteTask(id, isDelete) {
return fetch({
url: '/api/tasks/' + id + '?isDelete=' + isDelete,
method: 'DELETE',
});
}
//新增成果
export function addPaper(data) {
return fetch({
url: '/api/paper/',
method: 'post',
data: data
});
}
// 任务成果
export async function getTaskPaper(params) {
let res = await fetch({
url: '/api/paper/',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 审核任务成果
export async function readyCheckPapers(params) {
let res = await fetch({
url: '/api/paper/admin/readyCheckPapers',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 我的成果
export async function myPapers(params) {
let res = await fetch({
url: '/api/paper/my',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
//更新成果
export function updatePaper(data) {
return fetch({
url: '/api/paper/',
method: 'put',
data: data
});
}
// 删除
export function deletePaper(id) {
return fetch({
url: `api/paper/${id}`,
method: 'delete',
});
}
//应征者名单公示
export function makePublic(id) {
return fetch({
url: `/api/tasks/makeApplicantListPublic/${id}`,
method: 'put',
});
}
//举报成果
export function reportPaper(data) {
return fetch({
url: `/api/paper/${data.paperId}/paperReport`,
method: 'post',
data: data
});
}
//点赞成果
export function thumbUpPaper(id) {
return fetch({
url: `/api/paper/${id}/thumbUp`,
method: 'post',
data: { paperId: id }
});
}
// 检查用户是否同意协议
export function checkAgreement(taskId) {
return fetch({
url: `/api/paper/${taskId}/agreement`,
method: 'get'
});
}
// 检查用户是否提交了成果
export function checkHavePaper(taskId) {
return fetch({
url: `/api/paper/${taskId}/check`,
method: 'get'
});
}
// 获取协议
export function getAgreement() {
return fetch({
url: '/api/paper/agreementSettings/1',
method: 'get'
});
}
// 同意协议
export function agreement(taskId) {
return fetch({
url: `/api/paper/${taskId}/agreement`,
method: 'post',
data: { taskId }
});
}
// 新增评论
export function commentAdd(data) {
return fetch({
url: `/api/paper/${data.paperId}/comment`,
method: 'post',
data,
});
}
//管理员审核任务
export function checkTask(data) {
return fetch({
url: `/api/tasks/backend/adminCheck`,
method: 'post',
data: data
});
}
// 审核成果/评论
export function checkPaper(data) {
return fetch({
url: `/api/paper/admin/complainPaper/${data.paperId}`,
method: 'post',
data: data.auditingVo
});
}
// 成果申诉
export function complainPaper(data) {
return fetch({
url: `/api/paper/complainInfo/${data.paperId}`,
method: 'post',
data: data.params
});
}
// 审核申诉材料列表查询
export async function complainPaperList(params) {
let res = await fetch({
url: '/api/paper/admin/readyComplaintPapers',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 审核申诉材料
export function checkComplain(data) {
return fetch({
url: `/api/paper/admin/complainMaterial/${data.paperId}`,
method: 'post',
data: data.auditingVo
});
}
// 佐证上传
export function proofAdd(data) {
return fetch({
url: `/api/taskResultProof/addTaskResultProof`,
method: 'post',
data,
});
}
// 审核佐证材料列表查询
export async function proofList(params) {
let res = await fetch({
url: '/api/tasks/backend/proofList',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 审核佐证
export function checkProof(data) {
return fetch({
url: `/api/taskResultProof/adminCheckResultAndProof`,
method: 'post',
data,
});
}
// 应征者公示期申诉
export function publicityComplain(data) {
return fetch({
url: `/api/myTasks/applicantComplaintDuringPublicity`,
method: 'post',
data,
});
}
// 审核公示期申诉列表查询
export async function publicityComplainList(params) {
let res = await fetch({
url: '/api/tasks/backend/complaintMaterialList',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 审核公示期申诉
export function checkPublicity(data) {
return fetch({
url: `/api/tasks/backend/adminCheck/complaintMaterialDuringPublicity`,
method: 'post',
data,
});
}
// 选择签订协议的方式
export function signMethod(data) {
return fetch({
url: `/api/sign/method/${data.taskId}/${data.method}`,
method: 'post',
});
}
// 上传委托协议
export function uploadAgreeRequire(data) {
return fetch({
url: `/api/sign/task/contract/${data.taskId}`,
method: 'post',
data: data.params
});
}
// 审核委托协议列表
export async function agreementList(params) {
let res = await fetch({
url: '/api/sign/task/contract',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 审核协议
export function adminCheckAgreement(data) {
return fetch({
url: `/api/sign/admin/${data.type === 1 ? 'task' : 'paper'}/contract/${data.agreementId}`,
method: 'post',
data: data.params
});
}
// 上传委托协议
export function uploadAgreePaper(data) {
return fetch({
url: `/api/sign/paper/contract/${data.paperId}`,
method: 'post',
data: data.params
});
}
// 上传凭证列表查询
export async function uploadPayProofList(params) {
let res = await fetch({
url: '/api/sign/admin/paper/payOrders',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 管理员上传支付凭证
export function uploadPayProof(data) {
return fetch({
url: `/api/sign/admin/paper/payment/${data.paperId}`,
method: 'post',
data: data.params
});
}
// 胜出者确认收款
export function confirmReceipt(paperId) {
return fetch({
url: `/api/sign/paper/money/${paperId}`,
method: 'post',
});
}
// 下载协议签订凭证
export function downAgreement(params) {
return fetch({
url: `/api/myTasks/getWinnersContractsByTaskId`,
method: 'get',
params,
});
}
// 管理员修改任务公示方式
export function changeShowUserMode(data) {
return fetch({
url: `/api/tasks/backend/changeShowUserMode`,
method: 'post',
data,
});
}
// 延期列表查询
export async function delayList(params) {
let res = await fetch({
url: '/api/tasks/backend/admin/delayList',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
// 延期
export function delayTask(data) {
return fetch({
url: `/api/tasks/backend/admin/task/delay/${data.taskId}`,
method: 'post',
data: data.params,
});
}
// 关闭
export function closeTask(taskId) {
return fetch({
url: `/api/tasks/backend/admin/task/close/${taskId}`,
method: 'post',
});
}

View File

@ -0,0 +1,136 @@
import React, { useMemo } from 'react';
import { Menu, Dropdown, } from 'antd';
import { current_main_site_url,main_web_site_url} from '../../static';
import './index.scss';
const { SubMenu } = Menu;
export default props => {
const projectMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${current_main_site_url}/admins`}>项目管理后台</a></Menu.Item>
</Menu>
});
const taskMenu = useMemo(() => {
return <Menu>
<SubMenu title="基础数据" >
<Menu.Item><a href={`${main_web_site_url}/admin/categories/list`}>任务领域</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/industries/list`}>行业信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/placements/list`}>职位信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/task_templates/list`}>需求导入模板</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/agreement_setting`}>签订协议内容</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/sign_agreement_setting`}>应征投稿协议内容</a></Menu.Item>
</SubMenu>
<SubMenu title="代办事项" >
<Menu.Item><a href={`/task/delayManage`}>延期任务处理</a></Menu.Item>
{/* <Menu.Item><a href={`${main_web_site_url}/admin/audit_files`}>协议签订凭证上传</a></Menu.Item> */}
<Menu.Item><a href="/task/payProof">支付报酬凭证上传</a></Menu.Item>
</SubMenu>
<Menu.Item><a href="/task/taskAdmin">任务列表</a></Menu.Item>
<Menu.Item><a href="/task/paperManage">创意征集评论</a></Menu.Item>
</Menu>
});
const competitionMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/competitions/list`}>竞赛列表</a></Menu.Item>
</Menu>
});
const userMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/users`}>用户列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/entities`}>主体信息列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/users_trial`}>试用授权列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/auto_users_trial`}>自动授权列表</a></Menu.Item>
</Menu>
});
const forumMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/messages_list`}>帖子</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/apply_destroy_memos`}>申请删帖</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/memo_reply_list`}>回复</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/forum_sections`}>版块配置</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/banned_users`}>禁言列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/forum_applies`}>版主审批</a></Menu.Item>
</Menu>
});
const checkMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/enterprise_authentication`}>企业认证</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/reviews/projects_list`}>开源项目</a></Menu.Item>
<Menu.Item><a href="/task/taskManage/1">统筹任务发布审批</a></Menu.Item>
<Menu.Item><a href="/task/taskManage/0">自主任务发布审批</a></Menu.Item>
<Menu.Item><a href="/task/paperComplain">成果上传申诉审批</a></Menu.Item>
<Menu.Item><a href="/task/publicityComplain">公示期成果申诉审批</a></Menu.Item>
<Menu.Item><a href="/task/agreementManage">协议审批</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/tasks/report_result_tasks`}>成果举报申诉</a></Menu.Item>
<Menu.Item><a href="/task/proofManage">评选佐证材料</a></Menu.Item>
</Menu>
});
const limitsMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/user_admin_roles`}>权限组配置</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/admin_role_permissions`}>权限操作配置</a></Menu.Item>
</Menu>
});
const configMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/about_infos/new"`}>关于我们</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/home_sections"`}>首页版块</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/partners`}>合作伙伴</a></Menu.Item>
</Menu>
});
return (
<div className="centerbox managements_menus clearfix">
<Dropdown key={'projectMenu'} overlay={projectMenu} placement="bottomLeft">
<div className="drop-div">
项目
</div>
</Dropdown>
<Dropdown key={'taskMenu'} overlay={taskMenu} placement="bottomLeft">
<div className="drop-div">
创客
</div>
</Dropdown>
<Dropdown key={'competitionMenu'} overlay={competitionMenu} placement="bottomLeft">
<div className="drop-div">竞赛</div>
</Dropdown>
<Dropdown key={'userMenu'} overlay={userMenu} placement="bottomLeft">
<div className="drop-div">用户</div>
</Dropdown>
<Dropdown key={'forumMenu'} overlay={forumMenu} placement="bottomLeft">
<div className="drop-div">论坛交流</div>
</Dropdown>
<Dropdown key={'checkMenu'} overlay={checkMenu} placement="bottomLeft">
<div className="drop-div">审批</div>
</Dropdown>
<Dropdown key={'limitsMenu'} overlay={limitsMenu} placement="bottomLeft">
<div className="drop-div">权限管理</div>
</Dropdown>
<Dropdown key={'configMenu'} overlay={configMenu} placement="bottomLeft">
<div className="drop-div">网站配置</div>
</Dropdown>
</div>
)
}

View File

@ -0,0 +1,24 @@
.managements_menus {
background: #fff;
border: 1px solid #eee;
.drop-div {
position: relative;
float: left;
width: 108px;
text-align: center;
padding: 15px 0px;
box-sizing: border-box;
position: relative;
cursor: pointer;
&::after {
content: "";
position: absolute;
right: 1px;
top: 20px;
width: 1px;
height: 20px;
background-color: #ddd;
}
}
}

View File

@ -0,0 +1,75 @@
import React, { useState, } from 'react';
import { Modal, Form, Input, } from 'antd';
import Upload from 'military/components/Upload';
import { uploadAgreePaper } from "../../api";
import '../../index.scss';
export default Form.create()(props => {
const { visible, setVisible, checkedItem, form, showNotification ,reloadList } = props;
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [fileList, setFileList] = useState([]);
//
function uploadFunc(fileList, files) {
setFileList(fileList);
setFieldsValue({
files,
});
}
function uploadAgree() {
validateFields((err, values) => {
if (!err) {
uploadAgreePaper({
paperId: checkedItem.id,
params: {
files: values.files,
}
}).then(res => {
if (res.message === 'success') {
setFieldsValue({
files: '',
});
setVisible(false);
showNotification("上传协议成功!");
reloadList();
} else {
showNotification(res.message || "上传协议失败")
}
})
}
})
}
return (
<Modal
title="签订协议"
visible={visible}
onOk={uploadAgree}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
<div className="task-popup-content">
{/* paperAuditing */}
{checkedItem.paperAuditing && <p className=" mb10 color-orange task_tip">审核意见{checkedItem.paperAuditing.message}</p>}
<a href="https://task.osredm.com/busiAttachments/download/121" className="icon icon-attachment font-13 color-blue" length="32">协议样板.word</a>
<Form.Item className="upload-form" label="附件上传" required={true}>
<Upload
load={uploadFunc}
size={50}
showNotification={showNotification}
fileList={fileList}
/>
{getFieldDecorator('files', {
rules: [{ required: visible, message: "请上传文件" }],
validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
</div>
</Modal>
)
}
)

View File

@ -0,0 +1,109 @@
import React, { useState, useCallback, useMemo} from 'react';
import { Modal, Form, Input, } from 'antd';
import Upload from 'military/components/Upload';
import { complainPaper, publicityComplain, } from "../../api";
import '../../index.scss';
const { TextArea } = Input;
export default Form.create()(props => {
const { visible, setVisible, checkedItem, detailStatus, form, showNotification, reloadList } = props;
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [fileList, setFileList] = useState([]);
//
function uploadFunc(fileList, files) {
setFileList(fileList);
setFieldsValue({
files,
});
}
const helper = useCallback(
(name, rules, widget) => (
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
function complain() {
validateFields((error, values) => {
if (!error) {
if (detailStatus === 5) {
publicityComplain({
content: values.complainValue,
files: values.files,
paperId: checkedItem.id,
}).then(res => {
complainDeal(res);
});
} else {
complainPaper({
paperId: checkedItem.id,
params: {
content: values.complainValue,
files: values.files,
}
}).then(res => {
complainDeal(res);
});
}
}
});
}
function complainDeal(res) {
if (res && res.message === 'success') {
showNotification('申诉提交成功');
setVisible(false);
setFileList(null);
setFieldsValue({
files: ''
});
reloadList();
}
}
return (
<Modal
title="申诉"
visible={visible}
onOk={complain}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
{checkedItem.checkStatus == 2 && detailStatus === 3 && <p className=" mb10 color-orange task_tip">审核意见{checkedItem.auditing.message}</p>}
<p className="edu-txt-center lineh-20 mb10">你的申诉信息将发送给平台管理员</p>
<p className="edu-txt-center lineh-20">请如实填写有效的申诉原由我们将尽快完成审核</p>
{
helper('complainValue', [{ required: visible, message: "(必填)请在此输入发起申诉的原因最大限制100个字符" },
{ max: 100, message: '长度不能超过100个字符' }],
<TextArea
placeholder="(必填)请在此输入发起申诉的原因最大限制100个字符"
autoSize={{ minRows: 6 }}
className="applyText"
/>
)
}
<Form.Item className="upload-form" label="附件上传" required={true}>
<Upload
className="commentStyle"
load={uploadFunc}
size={50}
showNotification={showNotification}
fileList={fileList}
/>
{getFieldDecorator('files', {
rules: [{ required: visible, message: "请上传文件" }],
validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
</Modal>
)
}
)

View File

@ -0,0 +1,204 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Pagination, Modal, Input, Form, } from 'antd';
import { Link } from "react-router-dom";
import Nodata from 'forge/Nodata';
import Loading from "src/Loading";
import { timeAgo, getImageUrl } from 'educoder';
import { adminCheckAgreement } from '../../api';
import { httpUrl } from '../../fetch';
import './index.scss';
const { TextArea } = Input;
export default Form.create()((props) => {
const { form, list, curPage, total, changePage, loading, showNotification, reloadList } = props;
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [checkedItem, setCheckedItem] = useState({});
const [visible, setVisible] = useState(false);
const pageSize = props.pageSize || 10;
function refuseClick(item) {
setCheckedItem(item);
setVisible(true);
}
function dealAction() {
validateFields((error, values) => {
if (!error) {
adminCheckAgreement({
agreementId: checkedItem.id,
type: checkedItem.type,
params: {
pass: 0,
message: values.message
}
}).then(res => {
if (res && res.message === 'success') {
showNotification('操作成功');
reloadList();
setFieldsValue({
message: '',
});
setVisible(false);
}
});
}
});
}
function agreeClick(item) {
Modal.confirm({
title: '确认审批通过?',
onOk() {
adminCheckAgreement({
agreementId: item.id,
type: item.type,
params: {
pass: 1,
}
}).then(res => {
if (res && res.message === 'success') {
showNotification('操作成功');
reloadList();
}
})
}
});
}
function goUser(login) {
window.location.href = `/users/${login}`;
}
function goUserMes(login) {
window.location.href = `/users/${login}/message_detail`;
}
function downFile(item) {
let url = httpUrl + '/busiAttachments/download/' + item.id;
window.open(url);
}
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
return (
loading ? <Loading /> :
<React.Fragment>
{
list.map(item => {
return (
<div className="list-box" key={item.id}>
<img alt="" className="radius mr15" height="50px" src={item.user && getImageUrl(item.user.logo)} width="50px" />
<div className="flex1">
<li className="clearfix mb20">
<a className="user-box fl mr15 color-grey-3 font-16" onClick={() => { goUser(item.user.login) }}>{item.user && (item.user.nickname || item.user.login)}</a>
<span className="fl color-grey-9 mt3 mr15">{timeAgo(item.createdAt)}</span>
<span className="fr">
{item.status === 1 && <span className="spanTitle color-grey-6 fl ml20">已同意</span>}
{item.status === 0 && <span className="spanTitle color-red fl ml20">已驳回</span>}
{
item.status === 2 && <React.Fragment>
<a className="edu-default-btn edu-orangeline-btn ml20 fl" onClick={() => { goUserMes(item.user.login) }}>私信</a>
<a className="edu-default-btn edu-blueline-btn ml20 fl" onClick={() => { agreeClick(item) }}>同意</a>
<a className="edu-default-btn edu-greyline-btn ml20 fl" onClick={() => { refuseClick(item) }}>驳回</a>
</React.Fragment>
}
</span>
</li>
<div className="clearfix">
<div className="width100 lineh-35">
<span className="color-grey-9 fl">任务名称</span>
<span className="fl lineh-35 ml5">
<Link className="primary-link" to={`/task/taskDetail/${item.containerId}`}>{item.taskName}</Link>
</span>
</div>
<div className="clearfix"></div>
<div className="width100 lineh-35">
<span className="color-grey-9 fl">任务编号</span>
<span className="fl lineh-35 ml5">
{item.taskNumber}
</span>
</div>
<div className="clearfix"></div>
{
item.paperNumber && <React.Fragment>
<div className="width100 lineh-35">
<span className="color-grey-9 fl">成果编号</span>
<span className="fl lineh-35 ml5">
{item.paperNumber}
</span>
</div>
<div className="clearfix"></div>
</React.Fragment>
}
<div className="width100 lineh-35 clearfix">
<span className="color-grey-9 fl">协议文件</span>
{
item.busiAttachments && item.busiAttachments.map(fileItem => {
return <span className="file-list-prof " key={fileItem.id}>
<a onClick={() => { downFile(fileItem) }}><i className="iconfont icon-fujian color-green font-14 mr3"></i>
{fileItem.fileName} </a>
<span className="ml10 color-grey-9">({fileItem.fileSizeString})</span>
</span>
})
}
</div>
{/* <div className="width100 lineh-35">
<span className="color-grey-9 fl">驳回原因</span>
<span className="infos_item">{item.content}</span>
</div> */}
</div>
</div>
</div>
)
})
}
{list.length > 0 ?
<div className="edu-txt-center mt20 mb20">
{total > pageSize && <Pagination
showQuickJumper
onChange={(page) => { changePage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>}
</div> :
<Nodata _html="暂无数据" />}
<Modal
title="驳回协议"
visible={visible}
onOk={dealAction}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
{
helper('驳回原因', 'message', [{ required: visible, message: "请输入驳回的原因" }, { max: 200, message: '不能超过200字符' }],
<TextArea
placeholder="(必填)我想说点什么呢,200字以内"
autoSize={{ minRows: 6 }}
className="applyText"
/>
)
}
</Modal>
</React.Fragment>
)
}
)

View File

@ -0,0 +1,52 @@
.list-box {
position: relative;
display: flex;
justify-content: space-between;
padding: 20px;
margin: 0 1.5rem;
background: #fff;
border-bottom: 1px solid #dedede;
a.edu-orangeline-btn {
padding: 0px 10px;
}
}
a.primary-link {
color: #1890ff;
}
.infos_item {
float: left;
max-width: 273px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #343434;
margin-right: 6px;
line-height: 35px;
margin-left: 5px;
}
.file-list-prof{
background: #fafafa;
padding:.25rem .5rem;
margin-right:.5rem;
}
.form-edit-modal {
.ant-form-item{
display: flex;
}
.ant-form-item-label{
min-width: 5rem;
}
.ant-form-item-control-wrapper{
width: 75%;
display: inline-block;
}
.ant-input-number{
width: 50%;
}
}

View File

@ -0,0 +1,269 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Pagination, Modal, Input, DatePicker, Form } from 'antd';
import { Link } from "react-router-dom";
import moment from 'moment';
import Nodata from 'forge/Nodata';
import Loading from "src/Loading";
import { getImageUrl, formatDuring } from 'educoder';
import { taskStatusAllArr } from '../../static';
import { delayTask, closeTask } from '../../api';
import './index.scss';
const format = "YYYY-MM-DD";
const statusArr = [];
for (const item of taskStatusAllArr) {
statusArr[item.dicItemCode] = item.dicItemName;
}
const classArr = ['', 'list-done', 'list-error', 'list-red', 'list-yellow', 'list-pay', '', 'list-pay', 'list-gray',];
function getSomeDayAfter(time, nDay) {
return moment(new Date(time).setDate(new Date(time).getDate() + nDay)).format('YYYY-MM-DD HH:mm');
}
export default Form.create()((props) => {
const { list, curPage, total, changePage, loading, showNotification, reloadList, form } = props;
const { getFieldDecorator, validateFields } = form;
const [checkedItem, setCheckedItem] = useState('');
const [visible, setVisible] = useState(false);
const pageSize = props.pageSize || 10;
function closeClick(item) {
Modal.confirm({
title: '是否关闭?',
content: <p class="font-14 lineh-25 mb10 edu-txt-center">关闭后该任务立即结束无法重新打开</p>,
onOk() {
closeTask(item.id).then(res => {
if (res && res.message === 'success') {
showNotification('操作成功');
reloadList();
}
})
}
});
}
function delayClick(item) {
setCheckedItem(item);
setVisible(true);
}
function delayTime() {
validateFields((err, values) => {
if (!err) {
delayTask({
taskId: checkedItem.id,
params: {
delayedTo: moment(values.delayedTo).format(format)
},
}).then(res => {
if (res && res.message === 'success') {
showNotification('操作成功');
reloadList();
setVisible(false);
}
});
}
});
}
function goUser(login) {
window.location.href = `/users/${login}`;
}
function goUserMes(login) {
window.location.href = `/users/${login}/message_detail`;
}
const helper = useCallback(
(label, name, rules, widget, initialValue) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
</Form.Item>
), []);
const surplusTime = useCallback((item) => {
let surplus;
switch (item.currentStatus) {
case 3:
surplus = item.collectingDays * 24 * 3600 - (new Date() - new Date(item.publishedAt || item.createdAt)) / 1000;
break;
case 4:
surplus = item.choosingDays * 24 * 3600 - (new Date() - new Date(item.collectingCompleteAt)) / 1000;
break;
case 5:
surplus = item.makePublicDays * 24 * 3600 - (new Date() - new Date(item.makePublicAt)) / 1000;
break;
case 6:
surplus = item.signingDays * 24 * 3600 - (new Date() - new Date(item.publicityCompleteAt)) / 1000;
break;
case 7:
surplus = item.payingDays * 24 * 3600 - (new Date() - new Date(item.signingCompleteAt)) / 1000;
break;
default:
surplus = 0;
}
let surplusTimetext = formatDuring(surplus);
return surplus > 0 ? '剩余' + surplusTimetext : <span>延期 <span className="color-red">{surplusTimetext}</span></span>;
}, []);
const stopTime = useCallback((item) => {
switch (item.currentStatus) {
case 3:
return getSomeDayAfter(item.publishedAt, item.collectingDays);
case 4:
return getSomeDayAfter(item.collectingCompleteAt, item.choosingDays);
case 5:
return getSomeDayAfter(item.makePublicAt, item.makePublicDays);
case 6:
return getSomeDayAfter(item.publicityCompleteAt, item.signingDays);
case 7:
return getSomeDayAfter(item.signingCompleteAt, item.payingDays);
case 8:
return item.payingCompleteAt;
default:
return item.expiredAt;
}
})
function disabledDate(current) {
return current && current < moment().endOf('day');
}
return (
loading ? <Loading /> :
<React.Fragment>
{
list.map(item => {
return (
<div className="list-box" key={item.id}>
<img alt="" className="radius mr15" height="50px" src={item.user && getImageUrl(item.user.logo)} width="50px" onClick={() => { goUser(item.user.login) }} />
<div className="flex1">
<div className="clearfix">
<span className="lineh-35" style={{ display: "inline-flex" }}>
<span className="color-grey-9 fl">任务编号:</span>
<span className="infos_item mr15">{item.number}</span>
<span className="fl lineh-35 ml5">
<Link className="primary-link" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
</span>
<span>{item.currentStatus > 0 && <span className={classArr[item.currentStatus] + ' status-tag'}>{statusArr[item.currentStatus]}</span>}</span>
</span>
<span className="fr">
{item.cancelStatus === 1 && <span className="spanTitle color-red fl ml20">延期</span>}
{item.cancelStatus === 2 && <span className="spanTitle color-grey-6 fl ml20">关闭</span>}
{
item.cancelStatus === 0 && <React.Fragment>
<a className="edu-default-btn edu-orangeline-btn ml20 fl" onClick={() => { goUserMes(item.user.login) }}>私信</a>
<a className="edu-default-btn edu-blueline-btn ml20 fl" onClick={() => { delayClick(item) }}>延期</a>
<a className="edu-default-btn edu-greyline-btn ml20 fl" onClick={() => { closeClick(item) }}>关闭</a>
</React.Fragment>
}
</span>
</div>
<div className="clearfix">
<span className="with40 fl lineh-35">
<span className="color-grey-9 fl">主体名称:</span>
<span className="infos_item">{item.enterpriseName}</span>
</span>
<span className="with30 fl lineh-35">
<span className="color-grey-9 fl">发布方式:</span>
<span className="infos_item mr15 fl">{item.publishMode === 1 ? '统筹任务' : '自主提交'}</span>
</span>
</div>
<div className="clearfix">
<span className="with40 fl lineh-35">
<span className="color-grey-9 fl">联系手机:</span>
<span className="infos_item">{item.user.phone}位置分析{item.belongTo}</span>
</span>
<span className="with40 fl lineh-35 color-orange">
{
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && '未上传佐证材料'
}
{item.status === 6 && item.agreementSigning === 0 && '未选择协议签订方式'}
{
item.status === 6 && item.agreementSigning === 2 && (item.contractStatus === null || item.contractStatus === 0) && '未上传委托协议'
}
{
item.status === 6 && item.agreementSigning === 2 && item.contractStatus === 2 && '已上传委托协议'
}
{
item.status === 7 && item.agreementSigning === 2 && '未上传支付报酬凭证'
}
</span>
</div>
<div className="clearfix">
<span className="with40 fl lineh-35">
<span className="color-grey-9 fl">截止时间:</span>
<span className="infos_item">{stopTime(item)}</span>
{[3, 4, 5, 6, 7].includes(item.currentStatus) && <span className="ml10">{surplusTime(item)}</span>}
</span>
{/* <span className="with40 lineh-35" style={{ display: "inline-flex" }}>
<span className="color-grey-9 fl">任务编号:</span>
<span className="infos_item mr15">{item.number}</span>
<span className="fl lineh-35 ml5">
<Link className="primary-link" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
</span>
</span> */}
</div>
</div>
</div>
)
})
}
{list.length > 0 ?
<div className="edu-txt-center mt20 mb20">
{total > pageSize && <Pagination
showQuickJumper
onChange={(page) => { changePage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>}
</div> :
<Nodata _html="暂无数据" />}
<Modal
title="请输入延期截止的具体时间"
visible={visible}
onOk={delayTime}
onCancel={() => { setVisible(false) }}
className="time-edit-modal"
>
{helper(
"",
"delayedTo",
[{ required: true, message: "请选择日期" }],
<DatePicker
format={format}
placeholder="请选择日期"
disabledDate={disabledDate}
/>,
moment(new Date(), format)
)}
</Modal>
</React.Fragment>
)
}
)

View File

@ -0,0 +1,50 @@
.list-box {
position: relative;
display: flex;
justify-content: space-between;
padding: 20px;
margin: 0 1.5rem;
background: #fff;
border-bottom: 1px solid #dedede;
a.edu-orangeline-btn {
padding: 0px 10px;
}
}
a.primary-link {
color: #1890ff;
}
.infos_item {
float: left;
max-width: 273px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #343434;
margin-right: 6px;
line-height: 35px;
margin-left: 5px;
}
.file-list-prof{
background: #fafafa;
padding:.25rem .5rem;
}
.status-tag {
display: inline-block;
padding: 0px 10px;
margin-left: .625rem;
background: #f8c753;
font-size: 12px;
color: #fff;
border-radius: 14px;
line-height: 22px;
height: 22px;
}
.time-edit-modal .ant-modal-body{
width: 200px;
margin:0 auto;
}

View File

@ -0,0 +1,356 @@
import React, { useEffect, useState, useCallback, useMemo } from 'react';
import { Form, Modal, Input, Pagination, Radio, Table } from 'antd';
import { Link } from "react-router-dom";
import Nodata from 'forge/Nodata';
import Loading from "src/Loading";
import Upload from 'military/components/Upload';
import ProofModal from '../proofModal';
import { publishModeArr, taskStatusAllArr, myPaperStatusArr } from '../../static';
import { signMethod, uploadAgreeRequire, downAgreement } from "../../api";
import { httpUrl } from '../../fetch';
import '../../index.scss';
import './index.scss';
const statusArr = [];
for (const item of taskStatusAllArr) {
statusArr[item.dicItemCode] = item.dicItemName;
}
export default Form.create()((props) => {
const { form, list, curPage, total, changePage, taskCategoryValueArr, loading, publish, showNotification, reloadList, joinTask } = props;
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [visibleProofs, setVisibleProofs] = useState(false);
const [taskId, setTaskId] = useState();
const [checkItem, setCheckItem] = useState({});
const [taskModeId, setTaskModeId] = useState('');
const pageSize = props.pageSize || 10;
const [visibleMethod, setVisibleMethod] = useState(false);
const [visibleAgree, setVisibleAgree] = useState(false);
const [fileList, setFileList] = useState(null);
const [dowloadTaskId, setDowloadTaskId] = useState('');
const [visibleDownload, setVisibleDownload] = useState(false);
const [uploadList, setUploadList] = useState([]);
useEffect(() => {
visibleDownload && downAgreement({ taskId: dowloadTaskId }).then(res => {
if (res && res.message === "success") {
setUploadList(res.data);
}
})
}, [visibleDownload])
function uploadProofs(item) {
setVisibleProofs(true);
setTaskId(item.id);
setTaskModeId(item.taskModeId);
}
function adviceModal(advice) {
Modal.info({
title: '审核意见',
content: advice
})
}
function signMethodModal(item) {
setVisibleMethod(true);
setTaskId(item.id);
}
function uploadAgree(item) {
setVisibleAgree(true);
setTaskId(item.id);
setCheckItem(item);
}
function chooseMethod() {
validateFields((err, values) => {
if (!err) {
signMethod({
taskId,
method: values.method,
}).then(res => {
if (res && res.message === 'success') {
showNotification('选择协议签订方式成功');
setVisibleMethod(false);
setFieldsValue({
method: ''
});
reloadList();
} else {
showNotification((res && res.message) || '操作失败');
}
})
}
})
}
const helper = useCallback(
(name, rules, widget) => (
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true, })(widget)}
</Form.Item>
), []);
function uploadAgreeList() {
validateFields((err, values) => {
if (!err) {
uploadAgreeRequire({
taskId,
params: {
files: values.files
}
}).then(res => {
if (res && res.message === "success") {
setFieldsValue({
files: ''
});
reloadList();
setVisibleAgree(false);
showNotification('上传协议成功');
} else {
showNotification((res && res.message) || '上传协议失败');
}
})
}
});
}
function uploadFunc(fileList, files) {
setFileList(fileList);
setFieldsValue({
files,
})
}
const columns = useMemo(() => {
return [
{
title: '成果物编号',
dataIndex: 'paperNumber',
},
{
title: '凭证文件',
dataIndex: 'fileName',
render: (text, record) => {
return <a className="line_1 color-grey3" onClick={() => { download(record.winnerContracts[0].id) }}> {record.winnerContracts && record.winnerContracts[0].fileName}</a >
}
},
{
title: '操作',
dataIndex: 'action',
render: (text, record) => {
return <a className="line_1 color-grey3" onClick={(e) => { download(record.winnerContracts[0].id) }}> 下载凭证</a >
}
}
];
}, []);
function download(id) {
window.open(httpUrl + '/busiAttachments/download/' + id);
}
return (
<React.Fragment>
<ul className="df mt10 needs_condition_content_nav">
<li key={1} className="with35 edu-txt-left">任务</li>
<li key={2} className="with15">类型</li>
{publish && <li key={3} className="with10 draft_only">应征投稿</li>}
<li key={4} className="with10">金额</li>
<li key={5} className="flex1">任务状态</li>
<li key={6} className="with15">操作</li>
</ul>
{loading ? <Loading /> : <React.Fragment>
{
list.map(item => {
return (
<div key={item.id} className="needs_condition_content">
<p className="needs_condition_content_t color-dark-grey">
任务编号{item.number}
<i className="ml20 mr5 iconfont icon-shijian color-grey9 font-16"></i>
{item.createdAt}
</p>
<ul className="df">
<li key={1} className="mytask-title with35 edu-txt-left font-16 font-bd" >
<Link className="color-grey3 font-16 font-bd" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
{
joinTask ? <React.Fragment>
{item.myPaperStatus === 0 && <span className="list_status s_orange ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
{item.myPaperStatus === 1 && <span className="list_status s_grey ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
{item.myPaperStatus === 2 && <span className="list_status s_red ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
{item.status === 6 && (item.agreementSigning === 1 || (item.agreementSigning === 2 && item.contractStatus === 1)) && <span className="list_status s_orange ml10">待签订协议</span>}
{item.status !== 8 && item.delayTime < 0 &&<span className="list_status list-yellow">延期中</span>}
{item.status !== 8 && item.cancelStatus === 1 && item.delayTime > 0 && <span className="list_status list-yellow">手动延期中</span>}
{item.status !== 8 && item.delayed && item.cancelStatus === 0 && item.delayTime > 0 && item.delayCount>0 &&<span className="list_status list-yellow">系统自动延期中</span>}
</React.Fragment> : <React.Fragment>
{item.status === 6 && (item.agreementSigning === 1 || (item.agreementSigning === 2 && item.auditing && item.auditing.pass === 1)) && <span className="list_status s_orange ml10">待签订协议</span>}
{item.status !== 8 && item.delayTime < 0 &&<span className="list_status list-yellow">延期中</span>}
{item.status !== 8 && item.cancelStatus === 1 && item.delayTime > 0 &&<span className="list_status list-yellow">手动延期中</span>}
{item.status !== 8 && item.delayed && item.cancelStatus === 0 && item.delayTime > 0 && item.delayCount>0 && <span className="list_status list-yellow">系统自动延期中</span>}
</React.Fragment>
}
</li>
<li key={2} className="with15 flex-column">
<span className="line_1">{taskCategoryValueArr[item.categoryId]}</span>
<span className="line_1">{publishModeArr[item.publishMode]}</span>
</li>
{publish && <li key={3} className="with10 draft_only">{item.papersCount || 0}</li>}
<li key={4} className="with10 color-orange">{item.bounty}</li>
<li className="flex1">
<span>
<span className="line_1">{item.exceptClosedBoolean ? '已关闭' : statusArr[item.status]}</span>
</span>
</li>
<li key={5} className="with15 flex-column">
{
joinTask ? <Link className="line_1 color-grey3" to={`/task/taskDetail/${item.id}`}>查看详情</Link>
:
<React.Fragment>
{
item.status === 0 || item.status === 9 ?
<Link className="line_1 color-grey3" to={`/task/taskEdit/${item.id}`}>编辑草稿</Link> :
<Link className="line_1 color-grey3" to={`/task/taskDetail/${item.id}`}>查看详情</Link>
}
{
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && (!item.isProofBoolean) &&
<a onClick={() => { uploadProofs(item) }} className="line_1 color-blue">上传佐证材料</a>
}
{
(!item.isProofBoolean) && (item.taskResultProof && item.taskResultProof.status === 0) &&
<a onClick={() => { adviceModal(item.advice) }} className="line_1 color-blue">佐证被拒原因</a>
}
{(item.status === 2 || item.status === 9) && <a onClick={() => { adviceModal(item.repairAdvice) }} className="line_1 color-blue">审核意见</a>}
{item.status === 6 && item.agreementSigning === 0 && <a className="line_1 color-blue" onClick={() => { signMethodModal(item) }}>选择协议签订方式</a>}
{item.status === 6 && item.agreementSigning === 2 && (item.contractStatus === null || item.contractStatus === 0) && <a className="line_1 color-blue" onClick={() => { uploadAgree(item) }}>上传委托协议</a>}
{item.status === 6 && item.agreementSigning === 2 && [1, 2].includes(item.contractStatus) && <a className="line_1 color-grey-9" >已上传委托协议</a>}
{item.status === 6 && item.agreementSigning === 1 && <span className="line_1 color-grey-9">已选择自主签订协议</span>}
{item.status === 7 && <span className="line_1 color-grey-9">{item.agreementSigning === 1 ? '待胜出者确认收款' : '待平台上传支付凭证'}</span>}
{item.status === 7 && <a className="line_1 color-blue" onClick={() => { setDowloadTaskId(item.id); setVisibleDownload(true); }}>下载协议签订凭证</a>}
</React.Fragment>
}
</li>
</ul>
</div>
)
})
}
{list.length > 0 ?
<div className="edu-txt-center mt20 mb20">
{total > pageSize && <Pagination
showQuickJumper
onChange={(page) => { changePage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>}
</div> :
<Nodata _html="暂无数据" />}
</React.Fragment>
}
{visibleProofs && <ProofModal
taskId={taskId}
taskModeId={taskModeId}
visible={visibleProofs}
changeVisible={setVisibleProofs}
showNotification={showNotification}
reloadList={reloadList}
/>}
<Modal
title="选择签订协议方式"
visible={visibleMethod}
onOk={chooseMethod}
onCancel={() => { setVisibleMethod(false) }}
className="form-edit-modal"
>
{
helper('method', [{ required: visibleMethod, message: '请选择签订协议的方式' }],
<Radio.Group className="vertical-radio">
<Radio value={2}>
<p>委托平台签订</p>
<p className="color-grey-9">以平台名义与评选胜出者签订协议需要经平台管理员审批需要发布方将奖励经费划归平台在审核通过后平台自动发送电子协议</p>
</Radio>
<Radio value={1}>
<p>自主签订</p>
<p className="color-grey-9">通过线下的方式以发布方名义与评选胜出者签订协议</p>
</Radio>
</Radio.Group>)
}
</Modal>
<Modal
title="上传委托协议"
visible={visibleAgree}
onOk={uploadAgreeList}
onCancel={() => { setVisibleAgree(false) }}
className="form-edit-modal"
>
{checkItem.auditing && <p className="color-orange mb10 task_tip">
审核意见{checkItem.auditing.message}
</p>}
<Form.Item className="upload-form" label="协议上传" required={true}>
<Upload
load={uploadFunc}
size={50}
showNotification={showNotification}
fileList={fileList}
/>
{/* 用一个隐藏的input实现上传文件的必填校验 */}
{getFieldDecorator('files', {
rules: [{ required: visibleAgree, message: "请上传文件" }],
validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
</Modal>
<Modal
title="下载协议签订凭证"
visible={visibleDownload}
onOk={() => { setVisibleDownload(false) }}
onCancel={() => { setVisibleDownload(false) }}
className="form-edit-modal"
>
<Table
loading={loading}
rowKey={(row) => row.id}
dataSource={uploadList}
columns={columns}
pagination={false}
/>
</Modal>
</React.Fragment>
)
}
)

View File

@ -0,0 +1,106 @@
.needs_condition_content_nav {
padding: 0px 20px;
background: #f7f7f7;
height: 50px;
line-height: 50px;
color: #656565;
text-align: center;
margin-bottom: 10px;
}
.needs_condition_content {
border: 1px solid #eaeaea;
border-radius: 4px;
margin-bottom: 20px;
ul {
margin: 0;
padding: 20px;
box-sizing: border-box;
li {
text-align: center;
justify-content: center;
align-items: center;
display: -webkit-flex;
}
.mytask-title {
justify-content: left;
a {
word-break: break-all;
}
span {
flex: 0 0 auto;
}
}
}
.list_status {
border-radius: 10px;
padding: 0px 10px;
height: 22px;
line-height: 22px;
display: inline-block;
color: #fff;
background: #fa6400;
margin-left: 0.625rem;
font-size: 0.8rem;
}
.s_orange {
background: #ffb121;
}
.s_red {
background: #fe0e36;
}
.s_blue {
background: #4cacff;
}
.s_grey {
background: #bababa;
}
.needs_condition_content_t {
height: 40px;
padding: 0px 20px;
background: #f7f7f7;
color: #333;
border-bottom: 1px solid #eaeaea;
line-height: 40px;
}
}
.tab-list-box {
position: relative;
display: flex;
justify-content: space-between;
padding: 20px;
background: #fff;
border-bottom: 1px solid #dedede;
}
.flex-column {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
.vertical-radio {
.ant-radio-wrapper {
display: flex;
line-height: 2rem;
align-items: flex-start;
.ant-radio {
margin-top: 0.5rem;
}
p {
white-space: normal;
word-break: break-all;
}
}
}

View File

@ -0,0 +1,297 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Pagination, Modal, Form, Input, Button } from 'antd';
import ReactWEditor from 'wangeditor-for-react';
import { timeAgo, getImageUrl } from 'educoder';
import Nodata from 'forge/Nodata';
import Loading from "src/Loading";
import { editorConfig } from 'military/components/config';
import AgreementModal from '../agreementModal';
import ComplainModal from '../complainModal';
import { reportPaper, thumbUpPaper, commentAdd, confirmReceipt } from '../../api';
import { paperCheckStatusArr } from '../../static';
import { httpUrl } from '../../fetch';
import winpng from '../../image/winner.png';
import './index.scss';
const { TextArea } = Input;
const paperCheckStatus = [];
for (const item of paperCheckStatusArr) {
paperCheckStatus[item.dicItemCode] = item.dicItemName;
}
export default Form.create()((props) => {
const { list, curPage, total, changePage, loading, applyStatusAllNameArr, reloadList, showNotification, current_user, form, detailStatus } = props;
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [page, setPage] = useState(1);
const pageSize = props.pageSize || 10;
const [checkedItem, setCheckedItem] = useState({});
const [reportVisible, setReportVisible] = useState(false);
const [commentHtml, setCommentHtml] = useState('');
const [commentId, setCommentId] = useState(undefined);
const [complainVisible, setComplainVisible] = useState(false);
const [agreeVisible, setAgreeVisible] = useState(false);
const [loadingChild, setLoadingChild] = useState(false);
useEffect(() => {
changePage(page);
}, [page]);
function downFile(item) {
let url = httpUrl + '/busiAttachments/download/' + item.id;
window.open(url);
}
function report() {
validateFields((error, values) => {
if (!error) {
setLoadingChild(true);
reportPaper({
paperId: checkedItem.id,
content: values.reportValue
}).then(res => {
if (res && res.message === 'success') {
showNotification('举报成功');
setReportVisible(false);
setFieldsValue({
reportValue: '',
complainValue: '',
});
}
setLoadingChild(false);
});
}
});
}
function thumbUp(id) {
setLoadingChild(true);
thumbUpPaper(id).then(res => {
reloadList();
setLoadingChild(false);
});
}
function commentPush(item) {
if (!commentHtml) {
showNotification("请输入评价");
return;
}
if (commentHtml.length > 10000) {
showNotification("评论过长,请减少评论内容或者简化评论格式");
return;
}
commentAdd({
content: commentHtml,
paperId: item.id,
taskId: item.taskId
}).then(res => {
if (res.message === 'success') {
closeComment();
reloadList();
}
});
}
function closeComment() {
setCommentId(undefined);
setCommentHtml('');
}
function commentEdit(id) {
setCommentId(id);
setCommentHtml('');
}
function goUser(login) {
window.location.href = `/users/${login}`;
}
function confirmReceiptModal(paperId) {
Modal.confirm({
title: '确认收款',
content: '确认已经收到任务报酬',
onOk: () => {
confirmReceipt(paperId).then(res => {
if (res && res.message === "success") {
showNotification("您已确认收款!");
reloadList();
}
})
}
})
}
const helper = useCallback(
(name, rules, widget) => (
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
return (
<React.Fragment>
{loading || loadingChild ? <Loading /> :
<React.Fragment>
{
list.map(item => {
return (
<div className="fileComments df" key={item.id}>
<img alt="头像加载失败" src={item.user && getImageUrl(item.user.logo)} width="50" height="50" className="bor-radius-all mr20" />
<div className="flex1">
<ul>
<li className="fl pr">
<span className={item.user.nickname === "******" ? "font-16 mr20 color-grey3" : "user-box font-16 mr20 color-grey3 clickable"} onClick={() => { item.user.nickname === "******" ? "" : goUser(item.user.login) }}>
{item.user.nickname || item.user.login}
</span>
<span className="color-grey9">{timeAgo(item.createdAt)}</span>
{item.status === 2 ? <img alt="胜出" className="mr5" src={winpng} /> : <span className="color-blue ml10">{item.checkStatus !== 1 ? paperCheckStatus[item.checkStatus] : applyStatusAllNameArr[item.status]}</span>}
</li>
<li className="fr">
{((item.needComplain && detailStatus === 3) || (detailStatus === 5 && item.publicTaskComplain && item.checkStatus === 1 && item.status !== 2)) && (current_user.login === item.user.login) &&
<a className="base_smallBtn blue_line_btn fl" onClick={() => { setComplainVisible(true); setCheckedItem(item) }}>申诉</a>}
{item.status === 2 && detailStatus === 6 && (current_user.login === item.user.login) && (!item.sign) && (item.canApplicantSign || item.canApplicantSignByPlatform) &&
<a className="base_smallBtn blue_line_btn fl" onClick={() => { setAgreeVisible(true); setCheckedItem(item) }}>签订协议</a>}
{item.status === 2 && detailStatus === 7 && (current_user.login === item.user.login) && (item.task && item.task.agreementSigning === 1) && (!item.isPay) &&
<a className="base_smallBtn blue_line_btn fl" onClick={() => { confirmReceiptModal(item.id) }}>确认收款</a>}
</li>
</ul>
<div className="paper-detail-content markdown-body editormd-html-preview editor-w-text" dangerouslySetInnerHTML={{ __html: item.paperDetail ? item.paperDetail.content : '' }}></div>
<div className="attachments" >
{
item.paperDetail && item.paperDetail.busiAttachments && item.paperDetail.busiAttachments.map(fileItem => {
return <div className="file-list-box" key={fileItem.id}>
<a onClick={() => { downFile(fileItem) }}><i className="iconfont icon-fujian color-green font-14 mr3"></i>
{fileItem.fileName} </a>
<span className="ml10 color-grey-9">({fileItem.fileSizeString})</span>
</div>
})
}
</div>
{item.comments && item.comments.length > 0 && <div className="padding20 fileCommentsList">
{item.comments.map(commentsItem => {
return <div className="comments-item" key={commentsItem.id}>
<div className="comments-author">
<span className="color-grey3 font-bd mr20">{commentsItem.user.nickname || commentsItem.user.login}</span>
<span className="color-grey9">{timeAgo(commentsItem.createdAt)}</span>
</div>
<div className="editor-w-text comments-content" dangerouslySetInnerHTML={{ __html: commentsItem.details && commentsItem.details.content }}>
</div>
</div>
})
}
</div>}
<li className="clearfix color-grey-6 mt10 mb20">
<span className="mr50 fl"><span className="color-grey9">成果编号</span>#{item.number}</span>
<span className="mr50 fl"><span className="color-grey9">提交时间</span>{item.createdAt}</span>
<span className="fl"><span className="color-grey9">稿件状态</span>{item.read ? '雇主已浏览' : '雇主未浏览'}</span>
{
item.user.nickname !== "******" && <span className="fr">
{[4, 5].includes(detailStatus) && <a className="mr20" onClick={() => { setReportVisible(true); setCheckedItem(item) }}><i className="iconfont icon-jinggao font-15 mr3"></i>举报</a>}
<a className="mr20" onClick={() => { commentEdit(item.id) }}><i className="iconfont icon-huifu1 font-15 mr3"></i>{item.comments ? item.comments.length : 0}</a>
<a onClick={() => { thumbUp(item.id) }}><i className="iconfont icon-dianzan11 font-16 mr3"></i>{item.thumbsUp}</a>
</span>
}
</li>
{commentId === item.id && <React.Fragment>
<ReactWEditor
config={{
...editorConfig,
placeholder: "请输入评论",
}}
onChange={(html) => { setCommentHtml(html) }}
/>
<Button className="mt20 mr20 mb20 fr" type={"primary"} onClick={() => { commentPush(item) }}>发表</Button>
<Button className="mt20 mr20 mb20 fr" onClick={closeComment}>取消</Button>
</React.Fragment>}
</div>
</div>
)
})
}
{list.length > 0 ?
<div className="edu-txt-center mt20 mb20">
{total > pageSize && <Pagination
showQuickJumper
onChange={(page) => { setPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>}
</div> :
<Nodata _html="暂无数据" />}
</React.Fragment>
}
<Modal
title="举报"
visible={reportVisible}
onOk={report}
onCancel={() => { setReportVisible(false) }}
className="form-edit-modal"
>
<div className="task-popup-content">
<p className="edu-txt-center lineh-20 mb10">你的举报信息将发送给平台管理员</p>
<p className="edu-txt-center lineh-20">请如实填写有效的举报原由我们将尽快完成审核</p>
{
helper('reportValue', [{ required: reportVisible, message: "(必填)请在此输入发起举报的原因最大限制100个字符" },
{ max: 100, message: '长度不能超过100个字符' }],
<TextArea
placeholder="(必填)请在此输入发起举报的原因最大限制100个字符"
autoSize={{ minRows: 6 }}
className="applyText"
/>
)
}
</div>
</Modal>
<ComplainModal
visible={complainVisible}
setVisible={setComplainVisible}
checkedItem={checkedItem}
detailStatus={detailStatus}
showNotification={showNotification}
reloadList={reloadList}
/>
{agreeVisible && <AgreementModal
paperId={checkedItem.id}
checkedItem={checkedItem}
visible={agreeVisible}
setVisible={setAgreeVisible}
showNotification={showNotification}
reloadList={reloadList}
/>}
</React.Fragment>
)
}
)

View File

@ -0,0 +1,46 @@
.blue_line_btn {
color: #4cacff !important;
border: 1px solid #4cacff;
background: #fff !important;
}
.base_smallBtn {
color: #ccc;
font-size: 14px;
background: #ccc;
border-radius: 4px;
height: 30px;
line-height: 30px;
display: block;
width: 100px;
box-sizing: border-box;
text-align: center;
margin-top: 1.25rem;
}
.fileCommentsList {
background: #fafafa;
padding-top: .25rem;
}
.comments-item{
margin-top:1rem;
}
.comments-content {
text-align: left;
font-size: 16px;
line-height: 1.6;
padding: 20px;
overflow: auto;
width: 100%;
background-color: #fff;
}
.small-head{
max-width: 2rem;
}
.clickable:hover{
color: #4cacff;
cursor: pointer;
}

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