Compare commits

..

95 Commits

Author SHA1 Message Date
jasder d9e3e0d96b ADD 成果库模块功 2021-05-25 14:15:20 +08:00
何童崇 563ca38d45 上传需求代码,微调成果库代码 2021-05-21 17:15:59 +08:00
何童崇 db702ed816 增加成果模块,跨域调用,修改原资源中跨域不能传cookie的设置 2021-05-17 13:22:58 +08:00
caishi 52fa8da9a1 隐藏找回密码功能入口 2021-04-17 13:59:02 +08:00
caishi 19c35eb6da 资源库不需要按引用次数排序 2021-04-14 10:28:43 +08:00
caishi 53e33414ae 资源库数量显示错误 2021-04-13 11:13:39 +08:00
caishi 3701abc2c9 资源库接口地址是另一个服务器 2021-04-13 11:10:54 +08:00
caishi d73e127f3d 组织-团队列表的头像login为undefined 2021-04-13 11:06:45 +08:00
caishi c39635af32 默认进项目详情,去掉多余提示 2021-04-13 10:59:03 +08:00
caishi f5df464d90 资源库模块+合并请求分页 2021-04-12 17:58:46 +08:00
caishi 690def741c 去掉右侧悬浮的使用手册按钮 2021-04-12 16:23:51 +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
289 changed files with 9481 additions and 11555 deletions

513
package-lock.json generated
View File

@ -1,40 +1,35 @@
{
"name": "forge",
"version": "3.0.0",
"name": "educoder",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@ant-design/colors": {
"version": "3.2.2",
"resolved": "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-3.2.2.tgz?cache=0&sync_timestamp=1612935637470&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcolors%2Fdownload%2F%40ant-design%2Fcolors-3.2.2.tgz",
"integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
"integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
"requires": {
"tinycolor2": "^1.4.1"
}
},
"@ant-design/create-react-context": {
"version": "0.2.5",
"resolved": "https://registry.npm.taobao.org/@ant-design/create-react-context/download/@ant-design/create-react-context-0.2.5.tgz",
"integrity": "sha1-9fWpFjtHcgl3EoNzl60w4i55+Fg=",
"resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz",
"integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==",
"requires": {
"gud": "^1.0.0",
"warning": "^4.0.3"
}
},
"@ant-design/css-animation": {
"version": "1.7.3",
"resolved": "https://registry.npm.taobao.org/@ant-design/css-animation/download/@ant-design/css-animation-1.7.3.tgz?cache=0&sync_timestamp=1596106749762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcss-animation%2Fdownload%2F%40ant-design%2Fcss-animation-1.7.3.tgz",
"integrity": "sha1-YKHJcAFOhrKPlAUQ1p5QPkKPETY="
},
"@ant-design/icons": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-2.1.1.tgz",
"integrity": "sha1-e5wI3/1PXUHbZn2dvl4BB9C9mko="
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
},
"@ant-design/icons-react": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/@ant-design/icons-react/download/@ant-design/icons-react-2.0.1.tgz",
"integrity": "sha1-F6JRNXGrMXrKKSfljOol3THlNvs=",
"resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz",
"integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==",
"requires": {
"@ant-design/colors": "^3.1.0",
"babel-runtime": "^6.26.0"
@ -451,8 +446,8 @@
},
"@types/react-slick": {
"version": "0.23.4",
"resolved": "https://registry.npm.taobao.org/@types/react-slick/download/@types/react-slick-0.23.4.tgz",
"integrity": "sha1-yX4qnn49GTPGhZO46CdS+rHozlM=",
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz",
"integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==",
"requires": {
"@types/react": "*"
}
@ -868,9 +863,9 @@
}
},
"antd": {
"version": "3.26.20",
"resolved": "https://registry.nlark.com/antd/download/antd-3.26.20.tgz",
"integrity": "sha1-8/Vw76qllQoUSULyHrKqqgiOlAc=",
"version": "3.26.16",
"resolved": "https://registry.npmjs.org/antd/-/antd-3.26.16.tgz",
"integrity": "sha512-EYRwlEf8FCPCVRk5yDcgjSZOC0exu+m75SwlSQU+Mh17f9wGhLeL2/DV7/Sra1r+BZlfiahFdkgrLY7UgMMBEQ==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"@ant-design/icons": "~2.1.1",
@ -930,16 +925,16 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
},
"rc-pagination": {
"version": "1.20.15",
"resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-1.20.15.tgz",
"integrity": "sha1-zLTNDpvU5H9y8p6kMsA1C/ez2Ac=",
"version": "1.20.14",
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz",
"integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.6",
@ -949,8 +944,8 @@
},
"rc-rate": {
"version": "2.5.1",
"resolved": "https://registry.npm.taobao.org/rc-rate/download/rc-rate-2.5.1.tgz?cache=0&sync_timestamp=1605573559401&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-rate%2Fdownload%2Frc-rate-2.5.1.tgz",
"integrity": "sha1-Vfxf0j6p3MciULmoiYA0efSEKWE=",
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz",
"integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==",
"requires": {
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
@ -960,8 +955,8 @@
},
"rc-select": {
"version": "9.2.3",
"resolved": "https://registry.nlark.com/rc-select/download/rc-select-9.2.3.tgz?cache=0&sync_timestamp=1618886345948&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-select%2Fdownload%2Frc-select-9.2.3.tgz",
"integrity": "sha1-ZDQOLW72TovDz8b0aP/ShiVYmsI=",
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz",
"integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "2.x",
@ -979,8 +974,8 @@
},
"rc-tree": {
"version": "2.1.4",
"resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x",
@ -990,18 +985,6 @@
"react-lifecycles-compat": "^3.0.4",
"warning": "^4.0.3"
}
},
"react-slick": {
"version": "0.25.2",
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.25.2.tgz",
"integrity": "sha1-VjMbZ9R9i8/i3OtqyrHI/VvR9rw=",
"requires": {
"classnames": "^2.2.5",
"enquire.js": "^2.1.6",
"json2mq": "^0.2.0",
"lodash.debounce": "^4.0.8",
"resize-observer-polyfill": "^1.5.0"
}
}
}
},
@ -1100,8 +1083,8 @@
},
"array-tree-filter": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
"integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
},
"array-union": {
"version": "1.0.2",
@ -2079,6 +2062,7 @@
"version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"core-js": "^2.5.0",
@ -2088,7 +2072,8 @@
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
"dev": true
}
}
},
@ -2377,12 +2362,6 @@
}
}
},
"base16": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/base16/download/base16-1.0.0.tgz",
"integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=",
"dev": true
},
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
@ -3781,8 +3760,8 @@
},
"copy-to-clipboard": {
"version": "3.3.1",
"resolved": "https://registry.npm.taobao.org/copy-to-clipboard/download/copy-to-clipboard-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-to-clipboard%2Fdownload%2Fcopy-to-clipboard-3.3.1.tgz",
"integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
"requires": {
"toggle-selection": "^1.0.6"
}
@ -3875,23 +3854,6 @@
"warning": "^4.0.3"
}
},
"cross-fetch": {
"version": "3.1.4",
"resolved": "https://registry.nlark.com/cross-fetch/download/cross-fetch-3.1.4.tgz",
"integrity": "sha1-lyPzo6JHv4uJA586OAqSROj6Lzk=",
"dev": true,
"requires": {
"node-fetch": "2.6.1"
},
"dependencies": {
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.nlark.com/node-fetch/download/node-fetch-2.6.1.tgz?cache=0&sync_timestamp=1626684741221&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnode-fetch%2Fdownload%2Fnode-fetch-2.6.1.tgz",
"integrity": "sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI=",
"dev": true
}
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -3926,6 +3888,11 @@
"randomfill": "^1.0.3"
}
},
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz",
"integrity": "sha1-KQSrJnep0EKFai6i74DekuSjbcw="
},
"crypto-random-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
@ -4885,7 +4852,7 @@
},
"dom-closest": {
"version": "0.2.0",
"resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
"requires": {
"dom-matches": ">=1.0.1"
@ -4929,7 +4896,7 @@
},
"dom-matches": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
},
"dom-scroll-into-view": {
@ -5051,8 +5018,8 @@
},
"draft-js": {
"version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/draft-js/download/draft-js-0.10.5.tgz",
"integrity": "sha1-v6m+sBj+BTPbsI1mdcNxprCPp0I=",
"resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
"integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
"requires": {
"fbjs": "^0.8.15",
"immutable": "~3.7.4",
@ -5091,18 +5058,13 @@
}
},
"echarts": {
"version": "4.9.0",
"resolved": "https://registry.nlark.com/echarts/download/echarts-4.9.0.tgz",
"integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.7.0.tgz",
"integrity": "sha512-NlOTdUcAsIyCCG+N4uh0ZEvXtrPW2jvcuqf03RyqYeCKzyPbiOQ4I3MdKXMhxG3lBdqQNdNXVT71SB4KTQjN0A==",
"requires": {
"zrender": "4.3.2"
"zrender": "4.3.0"
}
},
"echarts-wordcloud": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/echarts-wordcloud/download/echarts-wordcloud-2.0.0.tgz?cache=0&sync_timestamp=1610779172014&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts-wordcloud%2Fdownload%2Fecharts-wordcloud-2.0.0.tgz",
"integrity": "sha1-Uu+BeJWAH/6emd0brKt2hrLewEo="
},
"editor.md": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz",
@ -5187,7 +5149,7 @@
},
"enquire.js": {
"version": "2.1.6",
"resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz",
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
},
"entities": {
@ -5706,7 +5668,7 @@
},
"eventlistener": {
"version": "0.0.1",
"resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz",
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
},
"events": {
@ -6237,41 +6199,6 @@
"bser": "2.1.1"
}
},
"fbemitter": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbemitter/download/fbemitter-3.0.0.tgz",
"integrity": "sha1-ALKhr1QRJUqrQWzXX55iib7kv/M=",
"dev": true,
"requires": {
"fbjs": "^3.0.0"
},
"dependencies": {
"fbjs": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbjs/download/fbjs-3.0.0.tgz?cache=0&sync_timestamp=1602048313843&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffbjs%2Fdownload%2Ffbjs-3.0.0.tgz",
"integrity": "sha1-CQcGf7P1enj0XZXx6s/8rNYjwWU=",
"dev": true,
"requires": {
"cross-fetch": "^3.0.4",
"fbjs-css-vars": "^1.0.0",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
}
},
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz",
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"dev": true,
"requires": {
"asap": "~2.0.3"
}
}
}
},
"fbjs": {
"version": "0.8.17",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
@ -6301,12 +6228,6 @@
}
}
},
"fbjs-css-vars": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/fbjs-css-vars/download/fbjs-css-vars-1.0.2.tgz",
"integrity": "sha1-IWVRE2rgL+JVkyw+yHdfGOLAeLg=",
"dev": true
},
"fecha": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
@ -6751,42 +6672,6 @@
"readable-stream": "^2.3.6"
}
},
"flux": {
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/flux/download/flux-4.0.1.tgz",
"integrity": "sha1-eENQKwKEHUqqU0rws3MDSh917lw=",
"dev": true,
"requires": {
"fbemitter": "^3.0.0",
"fbjs": "^3.0.0"
},
"dependencies": {
"fbjs": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbjs/download/fbjs-3.0.0.tgz?cache=0&sync_timestamp=1602048313843&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffbjs%2Fdownload%2Ffbjs-3.0.0.tgz",
"integrity": "sha1-CQcGf7P1enj0XZXx6s/8rNYjwWU=",
"dev": true,
"requires": {
"cross-fetch": "^3.0.4",
"fbjs-css-vars": "^1.0.0",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
}
},
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz",
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"dev": true,
"requires": {
"asap": "~2.0.3"
}
}
}
},
"flv.js": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/flv.js/-/flv.js-1.5.0.tgz",
@ -8040,7 +7925,7 @@
},
"hammerjs": {
"version": "2.0.8",
"resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz",
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
},
"handle-thing": {
@ -8881,7 +8766,7 @@
},
"immutable": {
"version": "3.7.6",
"resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
},
"import-fresh": {
@ -9295,9 +9180,9 @@
}
},
"is-mobile": {
"version": "2.2.2",
"resolved": "https://registry.nlark.com/is-mobile/download/is-mobile-2.2.2.tgz",
"integrity": "sha1-9snF1Q7gElTOBec5vdg18e1OmVQ="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz",
"integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA=="
},
"is-npm": {
"version": "1.0.0",
@ -10003,11 +9888,6 @@
"esprima": "^4.0.0"
}
},
"js2wordcloud": {
"version": "1.1.12",
"resolved": "https://registry.npm.taobao.org/js2wordcloud/download/js2wordcloud-1.1.12.tgz",
"integrity": "sha1-8BdC2k5qyzAAsoY1dmQWjvn8o64="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@ -10430,12 +10310,6 @@
"resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz",
"integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU="
},
"lodash.curry": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/lodash.curry/download/lodash.curry-4.1.1.tgz",
"integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=",
"dev": true
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -10446,12 +10320,6 @@
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
},
"lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npm.taobao.org/lodash.flow/download/lodash.flow-3.5.0.tgz",
"integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=",
"dev": true
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@ -10486,7 +10354,7 @@
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.uniq": {
@ -11541,8 +11409,8 @@
},
"omit.js": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz",
"integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=",
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz",
"integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
"requires": {
"babel-runtime": "^6.23.0"
}
@ -14082,12 +13950,6 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"pure-color": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/pure-color/download/pure-color-1.3.0.tgz",
"integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=",
"dev": true
},
"purgecss": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.1.2.tgz",
@ -14162,9 +14024,9 @@
"integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8="
},
"qrcode.react": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/qrcode.react/download/qrcode.react-1.0.1.tgz",
"integrity": "sha1-KDS7UOXidf/lr2kG7/FTkf6eOKU=",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.0.tgz",
"integrity": "sha512-jBXleohRTwvGBe1ngV+62QvEZ/9IZqQivdwzo9pJM4LQMoCM2VnvNBnKdjvGnKyDZ/l0nCDgsPod19RzlPvm/Q==",
"requires": {
"loose-envify": "^1.4.0",
"prop-types": "^15.6.0",
@ -14351,9 +14213,9 @@
}
},
"rc-calendar": {
"version": "9.15.11",
"resolved": "https://registry.npm.taobao.org/rc-calendar/download/rc-calendar-9.15.11.tgz",
"integrity": "sha1-zh5eqOTXdDW+ZqjHfbEvHw+aNF8=",
"version": "9.15.10",
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz",
"integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==",
"requires": {
"babel-runtime": "6.x",
"classnames": "2.x",
@ -14366,8 +14228,8 @@
},
"rc-cascader": {
"version": "0.17.5",
"resolved": "https://registry.npm.taobao.org/rc-cascader/download/rc-cascader-0.17.5.tgz?cache=0&sync_timestamp=1610107054432&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-cascader%2Fdownload%2Frc-cascader-0.17.5.tgz",
"integrity": "sha1-T96R0jt2CMQgJjw47unAaH+A99w=",
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz",
"integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==",
"requires": {
"array-tree-filter": "^2.1.0",
"prop-types": "^15.5.8",
@ -14380,8 +14242,8 @@
},
"rc-checkbox": {
"version": "2.1.8",
"resolved": "https://registry.npm.taobao.org/rc-checkbox/download/rc-checkbox-2.1.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-checkbox%2Fdownload%2Frc-checkbox-2.1.8.tgz",
"integrity": "sha1-7t2e+cLzr1s7jlzeUlSqia0aiAo=",
"resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz",
"integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "2.x",
@ -14391,8 +14253,8 @@
},
"rc-collapse": {
"version": "1.11.8",
"resolved": "https://registry.npm.taobao.org/rc-collapse/download/rc-collapse-1.11.8.tgz?cache=0&sync_timestamp=1606217065785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-collapse%2Fdownload%2Frc-collapse-1.11.8.tgz",
"integrity": "sha1-ZqQAidRpUZ6UJACasckn4hQEHYA=",
"resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz",
"integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==",
"requires": {
"classnames": "2.x",
"css-animation": "1.x",
@ -14405,8 +14267,8 @@
},
"rc-dialog": {
"version": "7.6.1",
"resolved": "https://registry.npm.taobao.org/rc-dialog/download/rc-dialog-7.6.1.tgz?cache=0&sync_timestamp=1614949683544&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dialog%2Fdownload%2Frc-dialog-7.6.1.tgz",
"integrity": "sha1-EVRczAuUWTT6dgeXJuDYU+UtcF8=",
"resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz",
"integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==",
"requires": {
"babel-runtime": "6.x",
"rc-animate": "2.x",
@ -14415,8 +14277,8 @@
},
"rc-drawer": {
"version": "3.1.3",
"resolved": "https://registry.npm.taobao.org/rc-drawer/download/rc-drawer-3.1.3.tgz?cache=0&sync_timestamp=1614159639291&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-drawer%2Fdownload%2Frc-drawer-3.1.3.tgz",
"integrity": "sha1-y8sE1MB/C2by7OEdhH9KG9gOoLc=",
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz",
"integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==",
"requires": {
"classnames": "^2.2.6",
"rc-util": "^4.16.1",
@ -14425,8 +14287,8 @@
},
"rc-dropdown": {
"version": "2.4.1",
"resolved": "https://registry.npm.taobao.org/rc-dropdown/download/rc-dropdown-2.4.1.tgz?cache=0&sync_timestamp=1600332782526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dropdown%2Fdownload%2Frc-dropdown-2.4.1.tgz",
"integrity": "sha1-qu9us6UVLN2ZgolcKnjZtfBGzew=",
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz",
"integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==",
"requires": {
"babel-runtime": "^6.26.0",
"classnames": "^2.2.6",
@ -14437,8 +14299,8 @@
},
"rc-editor-core": {
"version": "0.8.10",
"resolved": "https://registry.npm.taobao.org/rc-editor-core/download/rc-editor-core-0.8.10.tgz",
"integrity": "sha1-byFbxd+cM/+p9sWzDKc6favoq3w=",
"resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz",
"integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==",
"requires": {
"babel-runtime": "^6.26.0",
"classnames": "^2.2.5",
@ -14451,8 +14313,8 @@
},
"rc-editor-mention": {
"version": "1.1.13",
"resolved": "https://registry.npm.taobao.org/rc-editor-mention/download/rc-editor-mention-1.1.13.tgz",
"integrity": "sha1-nxyrEGX4awFSOEAyF5DCqxKsXos=",
"resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz",
"integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "^2.2.5",
@ -14480,9 +14342,9 @@
}
},
"rc-hammerjs": {
"version": "0.6.10",
"resolved": "https://registry.npm.taobao.org/rc-hammerjs/download/rc-hammerjs-0.6.10.tgz",
"integrity": "sha1-GDGjvY8hmXAL/MWtayCjVjCuteA=",
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz",
"integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==",
"requires": {
"babel-runtime": "6.x",
"hammerjs": "^2.0.8",
@ -14490,9 +14352,9 @@
}
},
"rc-input-number": {
"version": "4.5.9",
"resolved": "https://registry.nlark.com/rc-input-number/download/rc-input-number-4.5.9.tgz?cache=0&sync_timestamp=1619578110950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-input-number%2Fdownload%2Frc-input-number-4.5.9.tgz",
"integrity": "sha1-HL9zXiT+I8TrmkMBAxcguV8qPj0=",
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.6.tgz",
"integrity": "sha512-AXbL4gtQ1mSQnu6v/JtMv3UbGRCzLvQznmf0a7U/SAtZ8+dCEAqD4JpJhkjv73Wog53eRYhw4l7ApdXflc9ymg==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.0",
@ -14503,8 +14365,8 @@
},
"rc-mentions": {
"version": "0.4.2",
"resolved": "https://registry.npm.taobao.org/rc-mentions/download/rc-mentions-0.4.2.tgz?cache=0&sync_timestamp=1610510822768&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-mentions%2Fdownload%2Frc-mentions-0.4.2.tgz",
"integrity": "sha1-wYq3Ae+55LdbOFGgwNLdaYZA4kY=",
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz",
"integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "^2.2.6",
@ -14532,8 +14394,8 @@
},
"rc-notification": {
"version": "3.3.1",
"resolved": "https://registry.npm.taobao.org/rc-notification/download/rc-notification-3.3.1.tgz?cache=0&sync_timestamp=1614675471156&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-notification%2Fdownload%2Frc-notification-3.3.1.tgz",
"integrity": "sha1-C6o+cPjUCrAVzo+njCYMSQ/HvrQ=",
"resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz",
"integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==",
"requires": {
"babel-runtime": "6.x",
"classnames": "2.x",
@ -14554,9 +14416,9 @@
}
},
"rc-progress": {
"version": "2.5.3",
"resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-2.5.3.tgz",
"integrity": "sha1-APAblb2+GFbTpfgiQgUZAui3qOc=",
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz",
"integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==",
"requires": {
"babel-runtime": "6.x",
"prop-types": "^15.5.8"
@ -14573,8 +14435,8 @@
},
"rc-resize-observer": {
"version": "0.1.3",
"resolved": "https://registry.npm.taobao.org/rc-resize-observer/download/rc-resize-observer-0.1.3.tgz?cache=0&sync_timestamp=1608864858155&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-resize-observer%2Fdownload%2Frc-resize-observer-0.1.3.tgz",
"integrity": "sha1-CXGR+cOrGG7ZB7VTum71Zd8Rwkk=",
"resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz",
"integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==",
"requires": {
"classnames": "^2.2.1",
"rc-util": "^4.13.0",
@ -14602,8 +14464,8 @@
},
"rc-slider": {
"version": "8.7.1",
"resolved": "https://registry.npm.taobao.org/rc-slider/download/rc-slider-8.7.1.tgz?cache=0&sync_timestamp=1616675519253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-slider%2Fdownload%2Frc-slider-8.7.1.tgz",
"integrity": "sha1-ntBzYtyTSJo45lSyG4EirXD9PEI=",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
"integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.5",
@ -14617,8 +14479,8 @@
},
"rc-steps": {
"version": "3.5.0",
"resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-3.5.0.tgz",
"integrity": "sha1-NrKn8fSZB7DZA2OISxhiPK+ftgA=",
"resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz",
"integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "^2.2.3",
@ -14627,9 +14489,9 @@
}
},
"rc-switch": {
"version": "1.9.2",
"resolved": "https://registry.npm.taobao.org/rc-switch/download/rc-switch-1.9.2.tgz?cache=0&sync_timestamp=1603791200779&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-switch%2Fdownload%2Frc-switch-1.9.2.tgz",
"integrity": "sha1-eSHHZkEf6aZCZRDDQpAi1rpN/eI=",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
"integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
"requires": {
"classnames": "^2.2.1",
"prop-types": "^15.5.6",
@ -14638,8 +14500,8 @@
},
"rc-table": {
"version": "6.10.15",
"resolved": "https://registry.nlark.com/rc-table/download/rc-table-6.10.15.tgz",
"integrity": "sha1-GB9McMT9dPZX7o8jGW5+sIoDZco=",
"resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz",
"integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==",
"requires": {
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
@ -14653,8 +14515,8 @@
},
"rc-tabs": {
"version": "9.7.0",
"resolved": "https://registry.npm.taobao.org/rc-tabs/download/rc-tabs-9.7.0.tgz?cache=0&sync_timestamp=1608866453009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tabs%2Fdownload%2Frc-tabs-9.7.0.tgz",
"integrity": "sha1-rglpW+9ZY9bmTnvBBSHHbf3YRIs=",
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz",
"integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"babel-runtime": "6.x",
@ -14671,8 +14533,8 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
@ -14681,8 +14543,8 @@
},
"rc-time-picker": {
"version": "3.7.3",
"resolved": "https://registry.npm.taobao.org/rc-time-picker/download/rc-time-picker-3.7.3.tgz?cache=0&sync_timestamp=1576572941972&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-time-picker%2Fdownload%2Frc-time-picker-3.7.3.tgz",
"integrity": "sha1-ZajekECTJQrpyCsCpJBeD5leI+I=",
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz",
"integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==",
"requires": {
"classnames": "2.x",
"moment": "2.x",
@ -14694,8 +14556,8 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
@ -14704,8 +14566,8 @@
},
"rc-tooltip": {
"version": "3.7.3",
"resolved": "https://registry.npm.taobao.org/rc-tooltip/download/rc-tooltip-3.7.3.tgz?cache=0&sync_timestamp=1614588684791&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tooltip%2Fdownload%2Frc-tooltip-3.7.3.tgz",
"integrity": "sha1-KArsavyqROjf8EgPuv+eh/wArsw=",
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
"integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
"requires": {
"babel-runtime": "6.x",
"prop-types": "^15.5.8",
@ -14753,8 +14615,8 @@
},
"rc-tree-select": {
"version": "2.9.4",
"resolved": "https://registry.nlark.com/rc-tree-select/download/rc-tree-select-2.9.4.tgz",
"integrity": "sha1-aqeU4fDmXGbEBqoKKg50/QpVewk=",
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz",
"integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==",
"requires": {
"classnames": "^2.2.1",
"dom-scroll-into-view": "^1.2.1",
@ -14771,8 +14633,8 @@
"dependencies": {
"rc-tree": {
"version": "2.1.4",
"resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x",
@ -14785,8 +14647,8 @@
},
"rc-trigger": {
"version": "3.0.0",
"resolved": "https://registry.nlark.com/rc-trigger/download/rc-trigger-3.0.0.tgz?cache=0&sync_timestamp=1619590696046&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-trigger%2Fdownload%2Frc-trigger-3.0.0.tgz",
"integrity": "sha1-9tmx2oomsrLR2RKgaHbBpIb1mA8=",
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz",
"integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.6",
@ -14798,14 +14660,18 @@
},
"dependencies": {
"rc-animate": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/rc-animate/download/rc-animate-3.1.1.tgz?cache=0&sync_timestamp=1601018005635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-animate%2Fdownload%2Frc-animate-3.1.1.tgz",
"integrity": "sha1-3v3YY/VoFsIiU05Nxo/t3s0IE4Y=",
"version": "3.0.0-rc.6",
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz",
"integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==",
"requires": {
"@ant-design/css-animation": "^1.7.2",
"classnames": "^2.2.6",
"babel-runtime": "6.x",
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"fbjs": "^0.8.16",
"prop-types": "15.x",
"raf": "^3.4.0",
"rc-util": "^4.15.3"
"rc-util": "^4.5.0",
"react-lifecycles-compat": "^3.0.4"
}
}
}
@ -14859,18 +14725,6 @@
"prop-types": "^15.6.2"
}
},
"react-base16-styling": {
"version": "0.6.0",
"resolved": "https://registry.npm.taobao.org/react-base16-styling/download/react-base16-styling-0.6.0.tgz",
"integrity": "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=",
"dev": true,
"requires": {
"base16": "^1.0.0",
"lodash.curry": "^4.0.1",
"lodash.flow": "^3.3.0",
"pure-color": "^1.2.0"
}
},
"react-beautiful-dnd": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-10.1.1.tgz",
@ -15236,18 +15090,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-json-view": {
"version": "1.21.3",
"resolved": "https://registry.npm.taobao.org/react-json-view/download/react-json-view-1.21.3.tgz",
"integrity": "sha1-8YQgnujxvzdPsMQbCBPP9UVJxHU=",
"dev": true,
"requires": {
"flux": "^4.0.1",
"react-base16-styling": "^0.6.0",
"react-lifecycles-compat": "^3.0.4",
"react-textarea-autosize": "^8.3.2"
}
},
"react-jss": {
"version": "8.6.1",
"resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz",
@ -15268,9 +15110,9 @@
}
},
"react-lazy-load": {
"version": "3.1.13",
"resolved": "https://registry.npm.taobao.org/react-lazy-load/download/react-lazy-load-3.1.13.tgz?cache=0&sync_timestamp=1593654792284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-lazy-load%2Fdownload%2Freact-lazy-load-3.1.13.tgz",
"integrity": "sha1-I2lD92twhMyEWHFtljKhyYU+pc0=",
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz",
"integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=",
"requires": {
"eventlistener": "0.0.1",
"lodash.debounce": "^4.0.0",
@ -15407,9 +15249,9 @@
}
},
"react-slick": {
"version": "0.28.1",
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.28.1.tgz",
"integrity": "sha1-EsGNmRtZQy35w3V7pUCiJ7P7hbk=",
"version": "0.25.2",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz",
"integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==",
"requires": {
"classnames": "^2.2.5",
"enquire.js": "^2.1.6",
@ -15436,34 +15278,6 @@
"prop-types": "^15.5.4"
}
},
"react-textarea-autosize": {
"version": "8.3.3",
"resolved": "https://registry.nlark.com/react-textarea-autosize/download/react-textarea-autosize-8.3.3.tgz?cache=0&sync_timestamp=1622628433420&other_urls=https%3A%2F%2Fregistry.nlark.com%2Freact-textarea-autosize%2Fdownload%2Freact-textarea-autosize-8.3.3.tgz",
"integrity": "sha1-9wkTlFNp2kU/1VTBaPa6rNH6BNg=",
"dev": true,
"requires": {
"@babel/runtime": "^7.10.2",
"use-composed-ref": "^1.0.0",
"use-latest": "^1.0.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.14.8",
"resolved": "https://registry.nlark.com/@babel/runtime/download/@babel/runtime-7.14.8.tgz",
"integrity": "sha1-cRmlb0IQGIUmlCkLn5FICXORtEY=",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.nlark.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz?cache=0&sync_timestamp=1626993001371&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.9.tgz",
"integrity": "sha1-iSV0Kpj/2QgUmI11Zq0wyjsmO1I=",
"dev": true
}
}
},
"react-transition-group": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
@ -16281,8 +16095,8 @@
},
"rmc-feedback": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/rmc-feedback/download/rmc-feedback-2.0.0.tgz",
"integrity": "sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo=",
"resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz",
"integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.5"
@ -16865,8 +16679,8 @@
},
"shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.2.1.tgz",
"integrity": "sha1-TBar+lYEOqINBQMk76aJQLDaedo="
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"shallowequal": {
"version": "1.1.0",
@ -17220,11 +17034,6 @@
"is-fullwidth-code-point": "^2.0.0"
}
},
"slick-carousel": {
"version": "1.8.1",
"resolved": "https://registry.npm.taobao.org/slick-carousel/download/slick-carousel-1.8.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fslick-carousel%2Fdownload%2Fslick-carousel-1.8.1.tgz",
"integrity": "sha1-pL+ykBSIe7Zs5Si5C9DNomLMj40="
},
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -18559,12 +18368,6 @@
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"dev": true
},
"ts-essentials": {
"version": "2.0.12",
"resolved": "https://registry.nlark.com/ts-essentials/download/ts-essentials-2.0.12.tgz",
"integrity": "sha1-yTA/PXT3X6dSjD1JuA4ImrCdh0U=",
"dev": true
},
"tslib": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
@ -19074,30 +18877,6 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"use-composed-ref": {
"version": "1.1.0",
"resolved": "https://registry.npm.taobao.org/use-composed-ref/download/use-composed-ref-1.1.0.tgz",
"integrity": "sha1-kiDk6UqXt7AtfSfq6rCzcDRDi7w=",
"dev": true,
"requires": {
"ts-essentials": "^2.0.3"
}
},
"use-isomorphic-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/use-isomorphic-layout-effect/download/use-isomorphic-layout-effect-1.1.1.tgz",
"integrity": "sha1-e7ZYkXDNKYehUgQvkIT57/t1wiU=",
"dev": true
},
"use-latest": {
"version": "1.2.0",
"resolved": "https://registry.npm.taobao.org/use-latest/download/use-latest-1.2.0.tgz",
"integrity": "sha1-pE9lcrgojgly7EEb3QhAraNm8jI=",
"dev": true,
"requires": {
"use-isomorphic-layout-effect": "^1.0.0"
}
},
"user-home": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz",
@ -20701,16 +20480,6 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true
},
"xterm": {
"version": "4.8.1",
"resolved": "https://registry.npm.taobao.org/xterm/download/xterm-4.8.1.tgz",
"integrity": "sha1-FVoXKaQ+Gom0BlJOIsVjQznjnKE="
},
"xterm-addon-fit": {
"version": "0.4.0",
"resolved": "https://registry.npm.taobao.org/xterm-addon-fit/download/xterm-addon-fit-0.4.0.tgz",
"integrity": "sha1-BuDF0KaqrPsAnvVl76HIHpPZAZM="
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
@ -20748,9 +20517,9 @@
}
},
"zrender": {
"version": "4.3.2",
"resolved": "https://registry.npm.taobao.org/zrender/download/zrender-4.3.2.tgz",
"integrity": "sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY="
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.0.tgz",
"integrity": "sha512-Dii6j2bDsPkxQayuVf2DXJeruIB/mKVxxcGRZQ9GExiBd4c3w7+oBuvo1O/JGHeFeA1nCmSDVDs/S7yKZG1nrA=="
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "forge",
"version": "3.0.0",
"version": "0.1.0",
"private": true,
"dependencies": {
"@monaco-editor/react": "^2.3.0",
@ -14,7 +14,6 @@
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-polyfill": "^6.26.0",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
"bizcharts": "^3.5.8",
@ -30,8 +29,7 @@
"dompurify": "^2.0.15",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"echarts": "^4.9.0",
"echarts-wordcloud": "^2.0.0",
"echarts": "^4.7.0",
"editor.md": "^1.5.0",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0",
@ -48,7 +46,6 @@
"install": "^0.12.2",
"jest": "20.0.4",
"js-base64": "^2.5.2",
"js2wordcloud": "^1.1.12",
"katex": "^0.11.1",
"lodash": "^4.17.15",
"loglevel": "^1.6.8",
@ -65,7 +62,7 @@
"postcss-loader": "2.0.8",
"promise": "8.0.1",
"prop-types": "^15.6.1",
"qrcode.react": "^1.0.1",
"qrcode.react": "^1.0.0",
"qs": "^6.9.3",
"quill": "^1.3.7",
"quill-delta-to-html": "^0.11.0",
@ -90,12 +87,12 @@
"react-infinite-scroller": "^1.2.4",
"react-loadable": "^5.3.1",
"react-monaco-editor": "0.37",
"react-pdf": "^4.2.0",
"react-player": "^1.15.3",
"react-redux": "5.0.7",
"react-resizable": "^1.10.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-slick": "^0.28.1",
"react-split-pane": "^0.1.91",
"react-url-query": "^1.5.0",
"react-zmage": "^0.8.5-beta.31",
@ -106,7 +103,6 @@
"scroll-into-view": "^1.14.2",
"showdown": "^1.9.1",
"showdown-katex": "^0.8.0",
"slick-carousel": "^1.8.1",
"store": "^2.0.12",
"style-loader": "0.19.0",
"styled-components": "^4.4.1",
@ -116,9 +112,7 @@
"webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.2.0",
"whatwg-fetch": "2.0.3",
"wrap-md-editor": "^0.2.20",
"xterm": "4.8.1",
"xterm-addon-fit": "0.4.0"
"wrap-md-editor": "^0.2.20"
},
"scripts": {
"start": "node --max_old_space_size=15360 scripts/start.js",
@ -193,7 +187,6 @@
"babel-core": "^6.26.0",
"babel-plugin-import": "^1.13.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
@ -204,7 +197,6 @@
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"purgecss": "^2.1.2",
"react-json-view": "^1.21.3",
"reqwest": "^2.0.5",
"resize-observer-polyfill": "^1.5.1",
"terser-webpack-plugin": "^2.3.5",

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader {
background: #24292D !important;
width: 100%;
height: 60px !important;
min-width: 1200px;
@ -38,6 +37,78 @@
box-sizing: border-box;
}
.head-nav ul#header-nav li {
float: left;
height: 60px;
line-height: 60px;
margin-right: 30px;
cursor: pointer;
position: relative;
font-size: 16px
}
.head-nav ul#header-nav li a {
display: block;
height: 100%;
width: 100%;
color: #fff
}
.head-nav ul#header-nav li a:hover {
color: #cccccc;
}
.head-nav ul#header-nav li:last-child {
margin-right: 0px
}
.head-nav ul#header-nav li.active a {
color: #459be5 !important;
}
.head-nav ul#header-nav li.active p {
color: #459be5 !important;
}
.head-nav ul#header-nav li p:hover {
color: #cccccc;
}
.head-nav ul#header-nav li p {
display: block;
height: 100%;
width: 100%;
color: #fff
}
.head-nav ul#header-nav li.active div ul li a {
color: #000 !important;
}
.head-nav ul#header-nav li.active div ul li a:hover {
color: #FFF !important;
}
.head-nav ul#header-nav li.active ul li a {
color: #000 !important;
}
.head-nav ul#header-nav li.active ul li a:hover {
color: #FFF !important;
}
.head-nav ul#header-nav li.active:after {
content: '';
position: absolute;
left: 0px;
top: auto;
bottom: 10px;
right: auto;
height: 2px;
width: 14px;
background-color: #459be5;
}
.nav-img {
position: absolute;
top: 2px;

View File

@ -1753,7 +1753,7 @@ a.decoration {
}
.mb15 {
margin-bottom: 15px!important;
margin-bottom: 15px;
}
.mb16 {
@ -2346,6 +2346,7 @@ input::-ms-clear {
/*中间部分宽度固定为1200*/
.newMain {
margin: 0 auto;
padding-bottom: 110px;
min-width: 1200px;
}
@ -2424,16 +2425,10 @@ input::-ms-clear {
.color-grey-c {
color: #ccc !important;
}
a.hoverLine:hover{
text-decoration: underline;
}
.color-grey-cd {
color: #cdcdcd !important;
}
.color-grey-d {
color: #ddd;
}
.color-grey-9 {
color: #999999 !important;
@ -3415,7 +3410,7 @@ a.user_bluebg_btn {
}
.cdefault {
cursor: default!important;
cursor: default
}
@ -3590,6 +3585,42 @@ a.user_bluebg_btn {
margin-right: 5px;
}
/*-------------------个人主页:右侧提示区域--------------------------*/
.-task-sidebar {
position: fixed;
width: 40px;
height: 180px;
right: 0;
bottom: 80px;
z-index: 10;
}
.-task-sidebar div {
height: 40px;
line-height: 40px;
box-sizing: border-box;
width: 40px;
background: #4CACFF;
color: #fff;
font-size: 20px;
text-align: center;
margin-bottom: 5px;
border-radius: 4px;
}
.-task-sidebar div i {
color: #fff;
}
.-task-sidebar div i:hover {
color: #fff !important;
}
.gotop {
background-color: rgba(208, 207, 207, 0.5) !important;
padding: 0px !important;
}
/***** loading ******/
/*****载入中******/
@ -3914,21 +3945,11 @@ html>body #ajax-indicator {
max-height: 340px;
}/*头部导航条样式---2018-03-19--by-cs*/
.privateTag{
display: block;
padding:0px 6px;
border-radius: 12px;
border:1px solid #2FC25B;
height: 18px;
line-height: 18px;
font-size: 12px;
margin-left: 10px;
color: #2FC25B;
}
.head-nav {
text-align: center;
height: 70px;
box-sizing: border-box;
min-width: 780px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@ -3950,7 +3971,7 @@ html>body #ajax-indicator {
cursor: pointer;
position: relative;
font-size: 16px;
padding-right:40px;
padding:0px 20px;
}
.head-nav ul#header-nav li a {
@ -4087,6 +4108,21 @@ em.vertical-line {
/* 右侧内容宽度变化的话需要调整posi-search right的值*/
/*底部*/
.newFooter {
max-height: 110px;
}
.newFooter {
position: absolute;
bottom: 0;
width: 100%;
background: #323232;
clear: both;
min-width: 1200px;
z-index: 8;
left: 0px;
}
.footercon {
border-bottom: 1px solid #47494d;
@ -6682,19 +6718,4 @@ ul.count_ul li:not(:last-child):after {
}
input.ant-input-lg::placeholder{
font-size: 14px !important;
}
p{
margin-bottom: 0px!important;
}
.toprightNum{
position: absolute;
right: 0px;
top:4px;
color: #999;
}
.ant-input, .ant-input .ant-input-suffix{
background-color: #fff!important;
}
.has-error .ant-input{
background-color: #FEF1F0!important;
}

File diff suppressed because one or more lines are too long

BIN
public/css/iconfont.eot Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,524 +5,6 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "23261798",
"name": "请求icon",
"font_class": "qingqiuicon",
"unicode": "e871",
"unicode_decimal": 59505
},
{
"icon_id": "23261799",
"name": "响应icon",
"font_class": "xiangyingicon",
"unicode": "e87c",
"unicode_decimal": 59516
},
{
"icon_id": "23144143",
"name": "多选选中",
"font_class": "duoxuanxuanzhong",
"unicode": "e88f",
"unicode_decimal": 59535
},
{
"icon_id": "23144144",
"name": "错误icon",
"font_class": "cuowuicon",
"unicode": "e890",
"unicode_decimal": 59536
},
{
"icon_id": "23144146",
"name": "成功icon",
"font_class": "chenggongicon",
"unicode": "e892",
"unicode_decimal": 59538
},
{
"icon_id": "23144147",
"name": "未选中响应icon",
"font_class": "weixuanzhongxiangyingicon",
"unicode": "e893",
"unicode_decimal": 59539
},
{
"icon_id": "23144149",
"name": "必填icon",
"font_class": "bitianicon",
"unicode": "e895",
"unicode_decimal": 59541
},
{
"icon_id": "23144151",
"name": "未选中项目标签icon",
"font_class": "weixuanzhongxiangmubiaoqianicon",
"unicode": "e897",
"unicode_decimal": 59543
},
{
"icon_id": "23144152",
"name": "列表icon",
"font_class": "liebiaoicon",
"unicode": "e898",
"unicode_decimal": 59544
},
{
"icon_id": "23144154",
"name": "下拉按钮_icon",
"font_class": "xialaanniu_icon",
"unicode": "e89a",
"unicode_decimal": 59546
},
{
"icon_id": "23144155",
"name": "未选中请求icon",
"font_class": "weixuanzhongqingqiuicon",
"unicode": "e89b",
"unicode_decimal": 59547
},
{
"icon_id": "23144158",
"name": "协作者管理icon",
"font_class": "xiezuozheguanliicon",
"unicode": "e8a1",
"unicode_decimal": 59553
},
{
"icon_id": "23144159",
"name": "选中响应icon",
"font_class": "xuanzhongxiangyingicon",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{
"icon_id": "23144160",
"name": "选中分支icon",
"font_class": "xuanzhongfenzhiicon",
"unicode": "e8a3",
"unicode_decimal": 59555
},
{
"icon_id": "23144162",
"name": "选中基本设置icon",
"font_class": "xuanzhongjibenshezhiicon",
"unicode": "e8a5",
"unicode_decimal": 59557
},
{
"icon_id": "23144165",
"name": "选中项目标签icon",
"font_class": "xuanzhongxiangmubiaoqianicon",
"unicode": "e8aa",
"unicode_decimal": 59562
},
{
"icon_id": "23144167",
"name": "选中webhook icon",
"font_class": "a-xuanzhongwebhookicon",
"unicode": "e8af",
"unicode_decimal": 59567
},
{
"icon_id": "23046282",
"name": "新增目录_悬停icon",
"font_class": "xinzengmulu_xuantingicon",
"unicode": "e884",
"unicode_decimal": 59524
},
{
"icon_id": "23046283",
"name": "新增页面_默认icon",
"font_class": "xinzengyemian_morenicon",
"unicode": "e885",
"unicode_decimal": 59525
},
{
"icon_id": "23046287",
"name": "展开_默认icon",
"font_class": "zhankai_morenicon",
"unicode": "e889",
"unicode_decimal": 59529
},
{
"icon_id": "23046290",
"name": "shanchu_tc_icon",
"font_class": "shanchu_tc_icon",
"unicode": "e88c",
"unicode_decimal": 59532
},
{
"icon_id": "23046293",
"name": "wiki_icon",
"font_class": "wiki_icon",
"unicode": "e88d",
"unicode_decimal": 59533
},
{
"icon_id": "23046311",
"name": "新增页面_鼠标点击icon",
"font_class": "xinzengyemian_shubiaodianjiicon",
"unicode": "e88e",
"unicode_decimal": 59534
},
{
"icon_id": "23046244",
"name": "导入模版_icon",
"font_class": "daorumoban_icon",
"unicode": "e86f",
"unicode_decimal": 59503
},
{
"icon_id": "23046247",
"name": "导出_悬浮",
"font_class": "daochu_xuanfu",
"unicode": "e870",
"unicode_decimal": 59504
},
{
"icon_id": "23046252",
"name": "错误",
"font_class": "cuowu",
"unicode": "e872",
"unicode_decimal": 59506
},
{
"icon_id": "23046254",
"name": "成功",
"font_class": "chenggong1",
"unicode": "e873",
"unicode_decimal": 59507
},
{
"icon_id": "23046255",
"name": "更多_icon",
"font_class": "gengduo_icon",
"unicode": "e874",
"unicode_decimal": 59508
},
{
"icon_id": "23046258",
"name": "复层关闭_icon",
"font_class": "fucengguanbi_icon",
"unicode": "e875",
"unicode_decimal": 59509
},
{
"icon_id": "23046262",
"name": "复制_icon",
"font_class": "fuzhi_icon",
"unicode": "e876",
"unicode_decimal": 59510
},
{
"icon_id": "23046268",
"name": "删除icon",
"font_class": "shanchuicon",
"unicode": "e877",
"unicode_decimal": 59511
},
{
"icon_id": "23046269",
"name": "垃圾桶_icon@3x",
"font_class": "a-lajitong_icon3x",
"unicode": "e878",
"unicode_decimal": 59512
},
{
"icon_id": "23046270",
"name": "收起_默认icon",
"font_class": "shouqi_morenicon",
"unicode": "e879",
"unicode_decimal": 59513
},
{
"icon_id": "23046271",
"name": "欢迎_icon",
"font_class": "huanying_icon",
"unicode": "e87a",
"unicode_decimal": 59514
},
{
"icon_id": "23046273",
"name": "搜索_删除icon",
"font_class": "sousuo_shanchuicon",
"unicode": "e87b",
"unicode_decimal": 59515
},
{
"icon_id": "23046275",
"name": "搜索_icon",
"font_class": "sousuo_icon",
"unicode": "e87d",
"unicode_decimal": 59517
},
{
"icon_id": "23046276",
"name": "文档预览_icon",
"font_class": "wendangyulan_icon",
"unicode": "e87e",
"unicode_decimal": 59518
},
{
"icon_id": "23046277",
"name": "文件夹_icon",
"font_class": "wenjianjia_icon",
"unicode": "e87f",
"unicode_decimal": 59519
},
{
"icon_id": "23046278",
"name": "下拉按钮",
"font_class": "xialaanniu",
"unicode": "e880",
"unicode_decimal": 59520
},
{
"icon_id": "23046280",
"name": "新增目录_默认icon",
"font_class": "xinzengmulu_morenicon",
"unicode": "e882",
"unicode_decimal": 59522
},
{
"icon_id": "23046281",
"name": "新增目录_鼠标点击icon",
"font_class": "xinzengmulu_shubiaodianjiicon",
"unicode": "e883",
"unicode_decimal": 59523
},
{
"icon_id": "22906287",
"name": "二次确认_icon",
"font_class": "erciqueren_icon",
"unicode": "e867",
"unicode_decimal": 59495
},
{
"icon_id": "22906288",
"name": "选中ssh_icon",
"font_class": "xuanzhongssh_icon",
"unicode": "e868",
"unicode_decimal": 59496
},
{
"icon_id": "22906289",
"name": "未选中安全设置_icon",
"font_class": "weixuanzhonganquanshezhi_icon",
"unicode": "e869",
"unicode_decimal": 59497
},
{
"icon_id": "22906290",
"name": "未选中ssh_icon",
"font_class": "weixuanzhongssh_icon",
"unicode": "e86a",
"unicode_decimal": 59498
},
{
"icon_id": "22906291",
"name": "选中安全设置_icon",
"font_class": "xuanzhonganquanshezhi_icon",
"unicode": "e86b",
"unicode_decimal": 59499
},
{
"icon_id": "22906292",
"name": "删除_icon",
"font_class": "shanchu_icon",
"unicode": "e86c",
"unicode_decimal": 59500
},
{
"icon_id": "22906293",
"name": "列表ssh_icon",
"font_class": "liebiaossh_icon",
"unicode": "e86e",
"unicode_decimal": 59502
},
{
"icon_id": "17575494",
"name": "file-submodule",
"font_class": "file-submodule",
"unicode": "e866",
"unicode_decimal": 59494
},
{
"icon_id": "7539612",
"name": "nv",
"font_class": "nv1",
"unicode": "e864",
"unicode_decimal": 59492
},
{
"icon_id": "7539613",
"name": "nan",
"font_class": "nan1",
"unicode": "e865",
"unicode_decimal": 59493
},
{
"icon_id": "21936935",
"name": "邮箱",
"font_class": "youxiang",
"unicode": "e8b2",
"unicode_decimal": 59570
},
{
"icon_id": "21936924",
"name": "单位",
"font_class": "danwei",
"unicode": "e8a7",
"unicode_decimal": 59559
},
{
"icon_id": "21936925",
"name": "待办事项",
"font_class": "daibanshixiang",
"unicode": "e8a8",
"unicode_decimal": 59560
},
{
"icon_id": "21936928",
"name": "概览",
"font_class": "gailan",
"unicode": "e8ab",
"unicode_decimal": 59563
},
{
"icon_id": "21936929",
"name": "男",
"font_class": "nan",
"unicode": "e8ac",
"unicode_decimal": 59564
},
{
"icon_id": "21936930",
"name": "女",
"font_class": "nv",
"unicode": "e8ad",
"unicode_decimal": 59565
},
{
"icon_id": "21936931",
"name": "工作流",
"font_class": "gongzuoliu1",
"unicode": "e8ae",
"unicode_decimal": 59566
},
{
"icon_id": "21936934",
"name": "数据统计",
"font_class": "shujutongji",
"unicode": "e8b1",
"unicode_decimal": 59569
},
{
"icon_id": "21936936",
"name": "项目",
"font_class": "xiangmu",
"unicode": "e8b3",
"unicode_decimal": 59571
},
{
"icon_id": "21936937",
"name": "组织",
"font_class": "zuzhi",
"unicode": "e8b4",
"unicode_decimal": 59572
},
{
"icon_id": "14835599",
"name": "右箭头",
"font_class": "arrowRight",
"unicode": "e863",
"unicode_decimal": 59491
},
{
"icon_id": "21151489",
"name": "箭头镂空-左",
"font_class": "jiantouloukong-zuo",
"unicode": "e861",
"unicode_decimal": 59489
},
{
"icon_id": "21151557",
"name": "箭头镂空-右",
"font_class": "jiantouloukong-you",
"unicode": "e862",
"unicode_decimal": 59490
},
{
"icon_id": "21568989",
"name": "分享",
"font_class": "fenxiang1",
"unicode": "e89c",
"unicode_decimal": 59548
},
{
"icon_id": "21568990",
"name": "回到顶部",
"font_class": "huidaodingbu1",
"unicode": "e89d",
"unicode_decimal": 59549
},
{
"icon_id": "21568993",
"name": "帮助",
"font_class": "bangzhu",
"unicode": "e8a0",
"unicode_decimal": 59552
},
{
"icon_id": "991344",
"name": "提交",
"font_class": "tijiao",
"unicode": "e860",
"unicode_decimal": 59488
},
{
"icon_id": "1852052",
"name": "数据库",
"font_class": "dataBase",
"unicode": "e85a",
"unicode_decimal": 59482
},
{
"icon_id": "4165948",
"name": "文件",
"font_class": "wenjian4",
"unicode": "e85b",
"unicode_decimal": 59483
},
{
"icon_id": "17165148",
"name": "链接",
"font_class": "lianjie2",
"unicode": "e85c",
"unicode_decimal": 59484
},
{
"icon_id": "17463741",
"name": "分支",
"font_class": "fenzhi2",
"unicode": "e85d",
"unicode_decimal": 59485
},
{
"icon_id": "17972521",
"name": "分支-3",
"font_class": "fenzhi-3",
"unicode": "e85e",
"unicode_decimal": 59486
},
{
"icon_id": "18682391",
"name": "天平",
"font_class": "tianping",
"unicode": "e85f",
"unicode_decimal": 59487
},
{
"icon_id": "1770896",
"name": "撤销",
@ -4705,7 +4187,7 @@
{
"icon_id": "1004630",
"name": "点赞2",
"font_class": "dianzaned",
"font_class": "dianzan1",
"unicode": "e639",
"unicode_decimal": 58937
},

1853
public/css/iconfont.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 724 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/favicon.ico Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="zh-CN" class="notranslate translated-ltr" translate="no">
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>

View File

@ -60,13 +60,12 @@ body {
.ant-progress-textno {
color: #f5222d;
}
.CodeMirror pre.CodeMirror-line{
font-size: 16px!important;
}
/* md多空格 */
.markdown-body p {
margin:10px 0px!important;
font-size: 16px !important;
line-height: 2 !important;
white-space: pre-wrap;
}
@ -88,10 +87,6 @@ body {
border-left: 1px solid rgb(221, 221, 221);
/* 某些情况下被cm盖住了 */
z-index: 99;
padding:8px 8px 50px;
}
.editormd-preview .markdown-body{
padding:0px !important;
}
/* 图片点击放大的场景,隐藏图片链接 */

View File

@ -17,7 +17,8 @@ import marked from './common/marked';
import moment from 'moment'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import SiderBar from './forge/Component/SiderBar'
import history from './history';
import { SnackbarHOC } from 'educoder'
import { initAxiosInterceptors } from './AppConfig'
@ -39,11 +40,6 @@ const Projects = Loadable({
loader: () => import('./forge/Index'),
loading: Loading,
})
//forge安全设置
const Security = Loadable({
loader: () => import('./forge/SecuritySetting/Index'),
loading: Loading,
})
//forge项目-devOps详情
const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'),
@ -78,15 +74,18 @@ const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'),
loading: Loading,
})
const Search = Loadable({
loader: () => import('./modules/search/'),
// 成果库
const Achieve = Loadable({
loader: () => import('./achieveRequirement/achieve'),
loading: Loading,
})
// 需求管理
const Requirement = Loadable({
loader: () => import('./achieveRequirement/requirement'),
loading: Loading,
})
const ProjectIndex = Loadable({
loader: () => import("./forge/Index"),
loading: Loading,
});
class App extends Component {
constructor(props) {
super(props);
@ -112,9 +111,36 @@ class App extends Component {
Addcoursestypes: false
})
};
ModalCancelsy = () => {
this.setState({
mydisplay: false,
})
window.location.href = "/";
};
ModalshowCancelsy = () => {
this.setState({
mydisplay: true,
})
};
disableVideoContextMenu = () => {
window.$("body").on("mousedown", "video", function (event) {
if (event.which === 3) {
window.$('video').bind('contextmenu', function () { return false; });
} else {
window.$('video').unbind('contextmenu');
}
});
}
componentDidMount() {
document.title = "loading...";
this.disableVideoContextMenu();
history.listen(() => {
this.forceUpdate()
const $ = window.$
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props);
this.getAppdata();
@ -192,14 +218,11 @@ class App extends Component {
};
render() {
const { mygetHelmetapi } = this.state;
let personal = mygetHelmetapi && mygetHelmetapi.personal;
return (
<Provider store={store}>
<ConfigProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
<SiderBar/>
<Router>
<Switch>
{/*项目*/}
@ -211,14 +234,6 @@ class App extends Component {
}
}>
</Route>
<Route
path={"/settings"}
render={
(props) => {
return (<Security {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/}
<Route
path={"/projects"}
@ -249,28 +264,47 @@ class App extends Component {
</Route>
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 查询 */}
<Route path="/search" component={Search} />
{/* 个人主页 */}
<Route path="/users/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
}></Route>
}></Route>
{/*成果库*/}
<Route
path={"/achieve"}
render={
(props) => {
return (<Achieve {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*需求管理/创客行动*/}
<Route
path={"/requirement"}
render={
(props) => {
return (<Requirement {...this.props} {...props} {...this.state} />)
}
}>
</Route>
<Route exact path="/"
render={
(props) => (
personal && personal.length > 0 ?
<InfosIndex {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
<Projects {...this.props} {...props} {...this.state}></Projects>
)
}
/>
<Route component={Shixunnopage} />
</Switch>
</Router>
</MuiThemeProvider>

View File

@ -2,17 +2,17 @@ import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy";
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") {
window.location.href = list
window.location.href = list
}
}
// TODO 开发期多个身份切换
@ -24,22 +24,55 @@ if (isDev) {
parsed = queryString.parse(_search);
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 's'
}
function clearAllCookie() {
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
setpostcookie()
}
// clearAllCookie();
function setpostcookie() {
const str = window.location.pathname;
if (str.indexOf("/wxcode") !== -1) {
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
let _educoder_sessions = _search.split('&')[0].split('=');
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
let autologin_trusties = _search.split('&')[1].split('=');
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
}
}
}
setpostcookie();
window._debugType = debugType;
export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
initOnlineOfflineListener()
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
var
proxy = "http://localhost:3000";
proxy = "http://117.50.100.12:49999";
var proxy = "https://testforgeplus.trustie.net";
const requestMap = {};
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
}
//响应前的设置
axios.interceptors.request.use(
config => {
if(config.url.indexOf("http") !== -1) {
setpostcookie()
clearAllCookie()
if (config.url.indexOf(proxy) !== -1 || config.url.indexOf("http") !== -1) {
return config
}
requestProxy(config);
requestProxy(config)
let url = `/api${config.url}`;
if (`${config[0]}` !== `true`) {
@ -53,12 +86,17 @@ export function initAxiosInterceptors(props) {
} else {
config.url = url;
}
setpostcookie();
}
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
}
return config;
},
err => {
return Promise.reject(err);
});
});
axios.interceptors.response.use(function (response) {
if (response === undefined) {
@ -107,6 +145,8 @@ export function initAxiosInterceptors(props) {
message501 = false
}, 2000);
}
requestMap[response.config.url] = false;
setpostcookie();
return response;
}, function (error) {
return Promise.reject(error);

View File

@ -9,7 +9,20 @@ class Loading extends Component {
}
render() {
return ""
return (
<div className="App" style={{ minHeight: '800px', width: "100%" }}>
<style>
{
`
.margintop{
margin-top:20%;
}
`
}
</style>
<Spin size="large" className={"margintop"} />
</div>
);
}
}

View File

@ -0,0 +1,97 @@
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 AchieveIndex = Loadable({
loader: () => import("./achieve/achieveList"),
loading: Loading,
});
const AchieveDetail = Loadable({
loader: () => import("./achieve/achieveDetail"),
loading: Loading,
});
const AchieveMine = Loadable({
loader: () => import("./achieve/achieveMine"),
loading: Loading,
});
const AchieveAdd = Loadable({
loader: () => import("./achieve/achieveEdit"),
loading: Loading,
});
const AchieveEdit = Loadable({
loader: () => import("./achieve/achieveEdit"),
loading: Loading,
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
<Route
path="/achieve/achieveDetail/:achieveId"
render={(props) => (
<AchieveDetail {...this.props} {...props} />
)}
></Route>
<Route
path="/achieve/achieveMine"
render={(props) => (
<AchieveMine {...this.props} {...props} />
)}
></Route>
<Route
path="/achieve/achieveAdd"
render={(props) => (
<AchieveAdd {...this.props} {...props} />
)}
></Route>
<Route
path="/achieve/achieveEdit/:achieveId"
render={(props) => (
<AchieveEdit {...this.props} {...props} />
)}
></Route>
<Route
path="/achieve"
render={(props) => (
<AchieveIndex {...this.props} {...props} />
)}
></Route>
<Route
path="/"
render={(props) => (
<AchieveIndex {...this.props} {...props} />
)}
></Route>
{/* <Route
exact
path="/"
render={(props) => (
this.props.current_user && this.props.current_user.login ?
<Infos {...this.props} {...props} />
:
<AchieveIndex {...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,142 @@
import React, { useEffect, useState } from 'react';
import { Descriptions, Modal } from 'antd';
import { Document, Page, pdfjs } from 'react-pdf';
import DelModal from '../../components/DelModal';
import { httpUrl } from '../../../fetch';
import { deleteAchieve, getAchieveDetail } from '../api';
import './index.scss';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
export default (props) => {
const { match, history, current_user } = props;
const id = match.params.achieveId;
const [achiveForm, setAchiveForm] = useState({});
const [createUserId, setCreateUserId] = useState("");
const [visible, setVisible] = useState(false);
const [fileType, setFileType] = useState(4);
const [fileUrl, setFileUrl] = useState(4);
const [numPages, setNumPages] = useState(null);
useEffect(() => {
getAchieveDetail(id).then(data => {
setAchiveForm(data);
setCreateUserId(data.user.id);
})
}, [id]);
function editItem() {
props.history.push(`/achieve/achieveEdit/${id}`);
}
function deletItem() {
DelModal(() => {
deleteAchieve(id).then(res => {
if (res.code === '1') {
props.showNotification("删除成功");
history.go(-1);
} else {
props.showNotification("删除失败");
}
})
});
}
function downFile(item) {
let url = httpUrl + '/busiAttachments/download/' + item.id;
window.open(url);
}
function pdfShow(e) {
setFileType(e.fileType);
if (e.fileType === 1 || e.fileType === 2 || e.fileType === 3) {
// pdf||video||img
setVisible(true);
setFileUrl(httpUrl + '/busiAttachments/view/' + e.id);
}
}
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
}
return (
<div className="centerbox">
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">{achiveForm.achievementName}</div>
{
createUserId === current_user.user_id &&
<div className="center-right-but" ><span onClick={editItem}>编辑</span> <span onClick={deletItem}>删除</span></div>
}
</div>
<Descriptions className="item-content" column={1}>
<Descriptions.Item label="成果类别">{achiveForm.achievementType && achiveForm.achievementType.dicItemName}</Descriptions.Item>
<Descriptions.Item label="标签">
{
achiveForm.achievementLabel && achiveForm.achievementLabel.map(itemx => {
return <span className="list-tag" key={itemx + 'ax'}>{itemx}</span>
})
}
</Descriptions.Item>
<Descriptions.Item label="单位名称">{achiveForm.achievementBelong}</Descriptions.Item>
<Descriptions.Item label="发布时间">{achiveForm.updatedAt}</Descriptions.Item>
<Descriptions.Item label="成果描述">{achiveForm.achievementRemark}</Descriptions.Item>
<Descriptions.Item label="成果文件" className="file-list-item">
{
achiveForm.achievementAttachments && achiveForm.achievementAttachments.map(item => {
return <div className="file-list-box" key={item.id + 'down'}>
<p onClick={() => { pdfShow(item) }}>{item.fileName}</p>
<span className="downP" onClick={() => { downFile(item) }}>下载</span>
</div>
})
}
</Descriptions.Item>
</Descriptions>
</div>
<Modal
visible={visible}
maskClosable={true}
closable={true}
footer={null}
onCancel={() => { setVisible(false) }}
className="file-modal"
>
{
fileType === 3 && <div >
<img className="show-img" src={fileUrl} alt="" />
</div>
}
{
fileType === 2 && <div>
<video src={fileUrl} style={{ width: '100%' }} controls="controls">您的浏览器不支持 video 标签</video>
</div>
}
{
fileType === 1 && <div className="pdf-box">
{
<Document
file={fileUrl}
onLoadSuccess={onDocumentLoadSuccess}
>
{new Array(numPages).fill("").map((item, index) => {
return (
<Page
loading=""
noData=""
key={index}
pageNumber={index + 1}
renderTextLayer={true}
/>
);
})}
</Document>
}
</div>
}
</Modal>
</div>
)
}

View File

@ -0,0 +1,33 @@
// 内容详情
.item-content {
padding: 10px 10px 0 30px;
}
.ant-descriptions-item-label {
width: 5em;
margin-right: 5px;
color: rgba(0, 0, 0, 0.65);
text-align: right;
}
.ant-descriptions-item-content {
color: rgba(0, 0, 0, 1);
}
.file-list-item > span {
vertical-align: top;
}
.file-list-box {
width: 600px;
height: 60px;
display: flex;
justify-content: space-between;
p:hover {
cursor: pointer;
color: #0089ff;
}
.downP {
color: #0089ff;
cursor: pointer;
text-decoration: none;
}
}

View File

@ -0,0 +1,236 @@
import React, { forwardRef, useCallback, useEffect, useState } from 'react';
import { Form, Input, Select, Button, } from 'antd';
import Upload from '../../components/Upload';
import { httpUrl } from '../../../fetch';
import { getDictionary, getAchieveDetail, addAchieve, editAchieve } from '../api';
import './index.scss';
const Option = Select.Option;
const { TextArea } = Input;
export default Form.create()(
forwardRef(({ form, showNotification, match, history }, ref) => {
const [shareType, setShareType] = useState([]);
const [tagType, setTagType] = useState([]);
const [fileList, setFileList] = useState(null);
const [achievementFileTypes, setAchievementFileTypes] = useState('');
const id = match.params.achieveId;
const { getFieldDecorator, validateFields, setFieldsValue } = form;
useEffect(() => {
id && getAchieveDetail(id).then(data => {
const formValue = {
achievementName: data.achievementName,
achievementTypeId: data.achievementTypeId,
achievementBelong: data.achievementBelong,
achievementLabel: data.achievementLabel,
achievementRemark: data.achievementRemark,
achievementFiles: data.achievementFiles
};
setFieldsValue(formValue);
if (data.achievementAttachments.length) {
for (const item of data.achievementAttachments) {
item.name = item.fileName;
item.size = item.fileSize;
item.uid = "rc-upload" + item.id
}
setFileList(data.achievementAttachments);
}
})
}, [id]);
//
useEffect(() => {
getDictionary('share_type').then((res) => {
setShareType(res.data);
});
getDictionary("tag_type").then((res) => {
setTagType(res.data);
});
}, []);
//
function UploadFunc(fileList) {
setFileList(fileList);
let files = [];
let fileTypes = [];
for (const item of fileList) {
files.push(item.id || item.response.data.id);
fileTypes.push(item.fileType || item.response.data.fileType);
}
setFieldsValue({
achievementFiles: files.join()
});
setAchievementFileTypes(fileTypes.join());
}
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
const formItemLayout = {
labelCol: {
xs: { span: 12 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 12 },
sm: { span: 16 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 20,
offset: 4,
},
sm: {
span: 20,
offset: 4,
},
},
};
//
function saveItem() {
validateFields((error, values) => {
if (!error) {
let params = {
...values,
achievementFileTypes,
};
params.achievementLabel = params.achievementLabel.join();
if (id) {
//
params.id = id;
editAchieve(params).then(res => {
if (res.code === '1') {
showNotification("成果更新成功!");
history.go(-1);
} else {
showNotification(res.message);
}
});
} else {
//
params.uploadUserId = 1;
addAchieve(params).then(res => {
if (res.code === '1') {
showNotification("成果新增成功!");
history.go(-1);
} else {
showNotification(res.message);
}
});
}
}
})
}
return (
<div className="centerbox">
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">{id ? '修改' : '新增'}成果</div>
</div>
<Form className="achieve-form" {...formItemLayout}>
{helper(
"成果名称:",
"achievementName",
[{ required: true, message: "请输入成果名称" }],
<Input
className="edit-input"
placeholder="请输入成果名称"
/>
)}
{helper(
"成果类别:",
"achievementTypeId",
[{ required: true, message: "请选择成果类别" }],
<Select placeholder="请选择成果类别"
className="edit-input"
>
{
shareType.map(item => {
return <Option key={item.dicItemName + item.id} value={item.id}>{item.dicItemName}</Option>
})
}
</Select>
)}
{helper(
"单位名称:",
"achievementBelong",
[{ required: true, message: "请输入单位名称" }],
<Input
className="edit-input"
placeholder="请输入单位名称"
/>
)}
<Form.Item label={"成果文件:"} required={true}>
<Upload
className="commentStyle"
load={UploadFunc}
size={100}
showNotification={showNotification}
actionUrl={httpUrl}
fileList={fileList}
/>
{/* 用一个隐藏的input实现上传文件的必填校验 */}
{getFieldDecorator('achievementFiles', {
rules: [{ required: true, message: "请上传成果文件" }], validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
{helper(
"标签:",
"achievementLabel",
[{ required: true, message: "请选择成果标签" }],
<Select
className="edit-input"
placeholder="请选择成果标签"
mode="tags"
tokenSeparators={[',']}
>
{
tagType.map(item => {
return <Option key={item.dicItemName}>{item.dicItemName}</Option>
})
}
</Select>
)}
{helper(
"成果描述:",
"achievementRemark",
[{ required: true, message: "请输入成果描述" }],
<TextArea
placeholder="请输入成果描述"
autoSize={{ minRows: 3, maxRows: 5 }}
/>
)}
<Form.Item {...tailFormItemLayout}>
<Button className="mr20" type={"primary"} onClick={saveItem}>保存</Button>
<Button onClick={() => { history.go(-1) }}>取消</Button>
</Form.Item>
</Form>
</div>
</div>
)
})
)

View File

@ -0,0 +1,4 @@
.achieve-form{
padding:24px 40px 0px 40px;
}

View File

@ -0,0 +1,148 @@
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import { Pagination, Button, Icon } from 'antd';
import ChooseNav from '../../components/chooseNav';
import ItemList from '../../components/itemList';
import { getDictionary, getAchieveList } from '../api';
export default (props) => {
const { current_user } = props;
// console.log(current_user);
const [achievementTypeId, setAchievementTypeId] = useState(''); //
const [achievementFileTypes, setAchievementFileTypes] = useState(''); //
const [orderBy, setOrderBy] = useState('-1');
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [industryOption, setIndustryOption] = useState([]);
const [achiveList, setAchiveList] = useState([]);
useEffect(() => {
getDictionary('share_type').then(res => {
if (res && res.data) setIndustryOption(res.data);
});
}, []);
useEffect(() => {
const params = {
achievementTypeId,
achievementFileTypes,
achievementLabel: '',
isOwned: '',
orderBy,
curPage,
pageSize: 10
};
getAchieveList(params).then(data => {
setAchiveList(data.rows);
setTotal(data.total);
})
}, [achievementTypeId, achievementFileTypes, orderBy, curPage]);
function changeOptionId(option, type) {
if (type === 'share_type') {
setAchievementTypeId(option.id);
setCurPage(1);
} else if (type === 'file_type') {
setAchievementFileTypes(option.id);
setCurPage(1);
}
}
function changeSort(sortType) {
setOrderBy(sortType);
setCurPage(1);
}
function goAchieveMine() {
props.history.push('/achieve/achieveMine');
}
function goAdd() {
props.history.push("/achieve/achieveAdd");
}
function achiveClick(id) {
props.history.push(`/achieve/achieveDetail/${id}`);
}
const filetypeOption = [
{
dicItemName: '文件',
id: 1
},
{
dicItemName: '视频',
id: 2
},
{
dicItemName: '图片',
id: 3
},
{
dicItemName: '软件',
id: 4
},
{
dicItemName: '其它',
id: 5
},
];
return (
<div className="centerbox">
<div className="nav-content">
<ChooseNav
key={'share_type'}
type={'share_type'}
title={'成果类别'}
options={industryOption}
changeOptionId={changeOptionId}
/>
<ChooseNav
key={'file_type'}
type={'file_type'}
title={'文件类型'}
options={filetypeOption}
changeOptionId={changeOptionId}
/>
</div>
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">
<div className={classNames({ 'center-left-butD': true, 'center-left-butDACT': orderBy === '-1' })} onClick={() => { changeSort('-1') }}>默认</div>
<div className={classNames({ 'center-left-butD': true, 'center-left-butDACT': orderBy === 'created_at' })} onClick={() => { changeSort('created_at') }}><Icon type="arrow-down" />最新</div>
<div className={classNames({ 'center-left-butD': true, 'center-left-butDACT': orderBy === 'view_count' })} onClick={() => { changeSort('view_count') }}><Icon type="arrow-down" />最热</div>
</div>
{
// current_user.login &&
<div className="center-right-but">
<Button className="mr15 font-12" size="small" type="primary" onClick={goAchieveMine}>我的成果</Button>
<Button className="mr20 font-12" size="small" type="primary" onClick={goAdd}><i className="iconfont icon-zaibianji font-12 mr3"></i>发布成果</Button>
</div>
}
</div>
<ItemList
list={achiveList}
itemClick={achiveClick}
/>
</div>
<div className="edu-txt-center ">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>
</div>
</div>
)
}

View File

@ -0,0 +1,82 @@
import React, { useEffect, useState } from 'react';
import { Pagination } from 'antd';
import ItemList from '../../components/itemList';
import DelModal from '../../components/DelModal';
import { deleteAchieve, getAchieveList } from '../api';
export default (props) => {
const [achiveList, setAchiveList] = useState([]);
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
useEffect(() => {
getAcheiveListOwn();
}, [curPage]);
function getAcheiveListOwn() {
const params = {
achievementTypeId: '',
achievementFileTypes: '',
achievementLabel: '',
// isOwned: '', //便
isOwned: true,
orderBy: -1,
curPage,
pageSize: 10
};
getAchieveList(params).then(data => {
setAchiveList(data.rows);
setTotal(data.total);
})
}
function achiveClick(id) {
props.history.push(`/achieve/achieveDetail/${id}`);
}
function editItem(id) {
props.history.push(`/achieve/achieveEdit/${id}`);
}
function deletItem(id) {
DelModal(() => {
deleteAchieve(id).then(res => {
if (res.code === '1') {
props.showNotification("删除成功");
getAcheiveListOwn();
} else {
props.showNotification("删除失败");
}
})
});
}
return (
<div className="centerbox">
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">
我的成果
</div>
</div>
<ItemList
list={achiveList}
itemClick={achiveClick}
deletItem={deletItem}
editItem={editItem}
/>
</div>
<div className="edu-txt-center ">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>
</div>
</div>
)
}

View File

@ -0,0 +1,62 @@
import fetch from '../../fetch';
// 获取字典分类列表
export function getDictionary(id) {
return fetch({
url: '/dicItem/getData?dicTypeCode=' + id,
method: 'get'
});
}
// 成果列表查询
export async function getAchieveList(params) {
let res = await fetch({
url: '/api/achievement/',
method: 'get',
params,
})
if (res && res.data) {
for (const i of res.data.rows) {
// 处理分解标签
i.tag = i.achievementLabel.split(',');
}
}
return res.data;
}
//新增成果
export function addAchieve(data) {
return fetch({
url: '/api/achievement/',
method: 'post',
data: data
});
}
//删除成果
export function deleteAchieve(id) {
return fetch({
url: '/api/achievement/' + id,
method: 'DELETE',
});
}
//更新成果
export function editAchieve(data) {
return fetch({
url: '/api/achievement/',
method: 'put',
data: data
});
}
// 成果详情查询
export async function getAchieveDetail(id) {
let res = await fetch({
url: '/api/achievement/' + id,
method: 'get',
});
res.data.achievementLabel = res.data.achievementLabel.split(',');
return res.data;
}

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,97 @@
import React, { useEffect, useState } from "react";
import { Upload, Button } from 'antd';
import axios from 'axios';
import { appendFileSizeToUploadFileAll } from 'educoder';
axios.defaults.withCredentials = true;
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);
// fileIdList(nf);
load && load(nf);
//
// const url = actionUrl + `/busiAttachments/${id}`;
// axios.delete(url).then((response) => {
// if (response.data) {
// if (response.data.code === "1") {
// let nf = files.filter(item => (item.response.data.id !== id) && (item.id !== id));
// setFiles(nf);
// fileIdList(nf);
// } else {
// showNotification(response.data.message);
// }
// }
// }).catch(function (error) {
// console.log(error);
// });
}
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.status === 'done' || info.file.status === 'removed') load && load(fileList);
}
}
// function fileIdList(fileList) {
// let id = [];
// let fileType = [];
// for (const item of fileList) {
// id.push(item.id || item.response.data.id);
// fileType.push(item.fileType || item.response.data.fileType);
// }
// load && load(id.join(), fileType.join());
// }
function beforeUpload(file) {
const isLt100M = file.size / 1024 / 1024 < size;
if (!isLt100M) {
showNotification(`文件大小必须小于${size}MB!`);
}
return isLt100M;
}
const upload = {
name: 'file',
fileList: files,
action: 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,29 @@
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import './index.scss';
export default (props) => {
const { title, options, changeOptionId, type } = props;
const [option, setOption] = useState({ id: "", dicItemName: "" ,dicItemCode:""});
useEffect(() => {
changeOptionId(option, type);
}, [option])
return (
<div className="shop-box">
<div className="choose-title">{title}</div>
<div className="choose-list">
<div className={classNames({ "choose-item-checked": option.id === "", "choose-item": true })} key={"all"} onClick={() => { setOption({ id: "", dicItemName: "" }) }}>全部</div>
{
options.map((item) => {
return <div className={classNames({ "choose-item-checked": option.id === item.id, "choose-item": true })} key={item.dicItemName} onClick={() => { setOption(item) }} >{item.dicItemName}</div>
})
}
</div>
</div>
)
}

View File

@ -0,0 +1,41 @@
.nav-content {
margin-top:20px;
background: #fff;
border-bottom: 1px solid #eaeaea;
box-shadow: #ddd 0px 0px 5px;
}
.shop-box {
width: 1280px;
border-top: 1px solid #eaeaea;
display: flex;
justify-content: start;
}
.choose-title {
width: 110px;
background: #f3f3f3;
text-align: center;
padding: 16px 0;
font-size: 14px;
color: #666;
font-weight: 600;
}
.choose-list {
width: 1170px;
padding: 16px 0;
display: flex;
justify-content: start;
}
.choose-item {
font-size: 14px;
text-align: center;
padding: 0 15px ;
cursor: pointer;
&:hover{
color: #0072ff;
}
}
.choose-item-checked {
color: #0072ff;
}

View File

@ -0,0 +1,42 @@
import React from 'react';
import './index.scss';
const statusArr = ['待审核', '进行中', '成果验收中', '完成', '审核未通过', '延期', '其他', '验收未通过'];
const classArr = ['', 'list-done', 'list-done', 'list-done', 'list-error', '', '', 'list-error'];
export default (props) => {
const { list, itemClick, editItem, deletItem, activeByStatus } = 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.status && <span className={classArr[item.status]}>{statusArr[item.status]}</span>}
</div>
<div >
{
item.tag.map(i => {
return <span className="list-tag" key={i + "av"}>{i}</span>;
})
}
</div>
<div className="list-other">
{item.user && <p>发布者{item.user.nickname ? item.user.nickname : item.user.login}</p>}
{item.createUser && <p>发布者{item.createUser.nickname ? item.createUser.nickname : item.createUser.login}</p>}
<p>发布时间{item.achievementPublishTime || item.createTime}</p>
</div>
{
editItem && <div className="list-box-action">
{
!activeByStatus || (activeByStatus && item.status == '0' || item.status == '4' || item.status == '5') &&
<button onClick={() => { editItem(item.id) }}><i className="iconfont icon-zaibianji font-25"></i></button>
}
<button onClick={() => { deletItem(item.id) }}><i className="iconfont icon-shanchu font-30 "></i></button>
</div>
}
</div>
)
})
)
}

View File

@ -0,0 +1,70 @@
.list-box {
position: relative;
padding: 20px;
background: #fff;
border-bottom: 1px solid #dedede;
}
.list-title {
font-size: 17px;
color: #000;
cursor: pointer;
}
.list-title:hover {
color: #409eff;
}
.list-title span {
padding: 3px 5px;
margin-left:.5em;
background: #f8c753;
font-size: 13px;
color: #fff;
border-radius: 3px;
}
span.list-done {
background: #35d77e;
}
span.list-error {
background: #f56c6c;
}
.list-tag {
display: inline-block;
margin: 5px 10px 5px 0;
background: #cfe9ff;
color: #0089ff;
font-size: 14px;
border-radius: 3px;
padding: 2px 5px;
}
.list-other > p {
display: inline-block;
margin: 0 10px 0 0;
font-size: 12px;
color: #666;
}
.list-box-action {
position: absolute;
display: flex;
align-items: center;
top: 0;
bottom: 0;
right: 100px;
visibility: hidden;
}
.list-box:hover .list-box-action {
visibility: visible;
}
.list-box-action button {
display: inline-block;
margin: 0 25px;
width: 50px;
height: 50px;
color: #0089ff;
line-height: 50px;
text-align: center;
border: 0;
border-radius: 25px;
box-shadow: 2px 2px 5px 2px #eee;
cursor: pointer;
}

View File

@ -0,0 +1,100 @@
// 本模块公共样式
.centerbox {
width: 80vw;
max-width: 1280px;
margin: 40px auto;
}
.center-content {
margin: 20px 0;
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-right-but {
display: flex;
align-items: center;
}
.center-right-but > span {
margin: 0 10px;
font-size: 16px;
color: #0089ff;
cursor: pointer;
}
// 通用标签样式
.list-tag {
display: inline-block;
margin-right: 10px;
background: #cfe9ff;
color: #0089ff;
font-size: 14px;
border-radius: 3px;
padding: 2px 5px;
line-height: 25px;
}
// 文件预览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;
}

View File

@ -0,0 +1,95 @@
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 RequireList = Loadable({
loader: () => import("./requirement/requireList"),
loading: Loading,
});
const RequireDetail = Loadable({
loader: () => import("./requirement/requireDetail"),
loading: Loading,
});
const RequireMine = Loadable({
loader: () => import("./requirement/requireMine"),
loading: Loading,
});
const RequireAdd = Loadable({
loader: () => import("./requirement/requireEdit"),
loading: Loading,
});
const RequireEdit = Loadable({
loader: () => import("./requirement/requireEdit"),
loading: Loading,
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
<Route
path="/requirement/requireDetail/:requireId"
render={(props) => (
<RequireDetail {...this.props} {...props} />
)}
></Route>
<Route
path="/requirement/requireMine"
render={(props) => (
<RequireMine {...this.props} {...props} />
)}
></Route>
<Route
path="/requirement/requireAdd"
render={(props) => (
<RequireAdd {...this.props} {...props} />
)}
></Route>
<Route
path="/requirement/requireEdit/:requireId"
render={(props) => (
<RequireEdit {...this.props} {...props} />
)}
></Route>
<Route
path="/requirement"
render={(props) => (
<RequireList {...this.props} {...props} />
)}
></Route>
{/* <Route
exact
path="/"
render={(props) => (
this.props.current_user && this.props.current_user.login ?
<Infos {...this.props} {...props} />
:
<RequireIndex {...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,71 @@
import fetch from '../../fetch';
// 获取字典分类列表
export function getDictionary(id) {
return fetch({
url: '/dicItem/getData?dicTypeCode=' + id,
method: 'get'
});
}
// 需求列表查询
export async function getRequirementList(data) {
let res = await fetch({
url: '/requirement/page',
method: 'post',
data,
});
if (res && res.data && res.data.rows) {
for (const i of res.data.rows) {
// 处理分解标签
i.tag = i.tag.split(',');
}
}
return res.data;
}
//新增需求
export function addRequirement(data) {
return fetch({
url: '/requirement/add',
method: 'post',
data: data
});
}
//删除需求
export function deleteRequirement(id) {
return fetch({
url: '/requirement/delete?id=' + id,
method: 'DELETE',
});
}
//更新需求
export function updateRequirement(data) {
return fetch({
url: '/requirement/update',
method: 'put',
data: data
});
}
// 需求详情查询
export async function getRequirementDetail(id) {
let res = await fetch({
url: '/requirement/getInfo?id=' + id,
method: 'get',
});
if (res && res.data) {
res.data.tag = res.data.tag.split(',');
return res.data;
}
}
//获取用户列表
export function getAllUsers() {
return fetch({
url: '/user/getUsers',
method: 'get'
});
}

View File

@ -0,0 +1,217 @@
import React, { useEffect, useState } from 'react';
import { Descriptions, Modal, Button } from 'antd';
import { Document, Page, pdfjs } from 'react-pdf';
import DelModal from '../../components/DelModal';
import Upload from '../../components/Upload';
import { httpUrl } from '../../../fetch';
import { deleteRequirement, getRequirementDetail, updateRequirement } from '../api';
import './index.scss';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
export default ({ match, history, current_user, showNotification }) => {
const id = match.params.requireId;
const [requireForm, setRequireForm] = useState({});
const [visible, setVisible] = useState(false);
const [visibleAchieve, setVisibleAchieve] = useState(false);
const [fileType, setFileType] = useState(4);
const [fileUrl, setFileUrl] = useState(4);
const [numPages, setNumPages] = useState(null);
const [fileList, setFileList] = useState(null);
const [edit, setEdit] = useState(false);
useEffect(() => {
getRequirementDetail(id).then(data => {
if (data) {
setRequireForm(data);
if (data.achievementList) {
for (const item of data.achievementList) {
item.name = item.fileName;
item.size = item.fileSize;
item.uid = "rc-upload" + item.id
}
setFileList(data.achievementList);
}
}
});
}, [id, edit]);
function editItem() {
history.push(`/requirement/requireEdit/${id}`);
}
function deletItem() {
DelModal(() => {
deleteRequirement(id).then(res => {
if (res.code === '1') {
showNotification("删除成功");
history.go(-1);
} else {
showNotification("删除失败");
}
})
});
}
function downFile(item) {
let url = httpUrl + '/busiAttachments/download/' + item.id;
window.open(url);
}
function pdfShow(e) {
setFileType(e.fileType);
if (e.fileType === 1 || e.fileType === 2 || e.fileType === 3) {
// pdf||video||img
setVisible(true);
setFileUrl(httpUrl + '/busiAttachments/view/' + e.id);
}
}
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
}
//
function UploadFunc(fileList) {
setFileList(fileList);
}
function uploadAchievement() {
let files = [];
let filestype = [];
for (const item of fileList) {
files.push(item.id || item.response.data.id);
filestype.push(item.fileType || item.response.data.fileType);
}
let data = {
id,
achievements: files.toString(),
// createUserAccount: sessionStorage.getItem('SET_Account'),//
// createUserName: sessionStorage.getItem('SET_NAME'),
status: "2"
}
updateRequirement(data).then(res => {
if (res.code === '1') {
showNotification('更新成果文件成功!');
setEdit(!edit);
setVisibleAchieve(false);
}
})
}
return (
<div className="centerbox">
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">{requireForm.title}</div>
{
<div className="center-right-but">
{
// (role||operator||needsForm.assignedUserLogin==userid||needsForm.createUserAccount==userid)&&(needsForm.status==1||needsForm.status==2||needsForm.status==7||needsForm.status==5)
((current_user.admin || current_user.operator || requireForm.assignedUserLogin == current_user.login || requireForm.createUserAccount == current_user.login)
&& (requireForm.status == 1 || requireForm.status == 2 || requireForm.status == 7 || requireForm.status == 5)) &&
<Button className="mr15 font-12" size="small" type="primary" onClick={() => { setVisibleAchieve(true) }}>上传成果</Button>
}
{
requireForm.createUserAccount === current_user.login &&
<React.Fragment>
<span onClick={editItem}>编辑</span>
<span onClick={deletItem}>删除</span>
</React.Fragment>
}
</div>
}
</div>
<Descriptions className="item-content" column={1}>
<Descriptions.Item label="需求类别">{requireForm.typeName}</Descriptions.Item>
<Descriptions.Item label="标签">
{
requireForm.tag && requireForm.tag.map(itemx => {
return <span className="list-tag" key={itemx + 'ax'}>{itemx}</span>
})
}
</Descriptions.Item>
<Descriptions.Item label="指派人员">{requireForm.assignedUserName}</Descriptions.Item>
<Descriptions.Item label="结束时间">{requireForm.endTime}</Descriptions.Item>
<Descriptions.Item label="需求描述">{requireForm.remark}</Descriptions.Item>
<Descriptions.Item label="需求文件" className="file-list-item">
{
requireForm.attachmentList && requireForm.attachmentList.map(item => {
return <div className="file-list-box" key={item.id + 'down'}>
<p onClick={() => { pdfShow(item) }}>{item.fileName}</p>
<span className="downP" onClick={() => { downFile(item) }}>下载</span>
</div>
})
}
</Descriptions.Item>
</Descriptions>
</div>
<Modal
visible={visible}
maskClosable={true}
closable={true}
footer={null}
onCancel={() => { setVisible(false) }}
className="file-modal"
>
{
fileType === 3 && <div >
<img className="show-img" src={fileUrl} alt="" />
</div>
}
{
fileType === 2 && <div>
<video src={fileUrl} style={{ width: '100%' }} controls="controls">您的浏览器不支持 video 标签</video>
</div>
}
{
fileType === 1 && <div className="pdf-box">
{
<Document
file={fileUrl}
onLoadSuccess={onDocumentLoadSuccess}
>
{new Array(numPages).fill("").map((item, index) => {
return (
<Page
loading=""
noData=""
key={index}
pageNumber={index + 1}
renderTextLayer={true}
width={750}
/>
);
})}
</Document>
}
</div>
}
</Modal>
<Modal
visible={visibleAchieve}
maskClosable={true}
closable={true}
onCancel={() => { setVisibleAchieve(false) }}
onOk={uploadAchievement}
className="upload-modal"
>
<Upload
className="commentStyle"
load={UploadFunc}
size={100}
showNotification={showNotification}
actionUrl={httpUrl}
fileList={fileList}
/>
</Modal>
</div>
)
}

View File

@ -0,0 +1,40 @@
// 内容详情
.item-content {
padding: 10px 10px 0 30px;
}
.ant-descriptions-item-label {
width: 5em;
margin-right: 5px;
color: rgba(0, 0, 0, 0.65);
text-align: right;
}
.ant-descriptions-item-content {
color: rgba(0, 0, 0, 1);
}
.file-list-item > span {
vertical-align: top;
}
.file-list-box {
width: 600px;
height: 60px;
display: flex;
justify-content: space-between;
p:hover {
cursor: pointer;
color: #0089ff;
}
.downP {
color: #0089ff;
cursor: pointer;
text-decoration: none;
}
}
.upload-modal{
width: 800px !important;
.commentStyle{
display: inline-block;
width: 100%;
}
}

View File

@ -0,0 +1,247 @@
import React, { forwardRef, useCallback, useEffect, useState } from 'react';
import { Form, Input, Select, Button, DatePicker } from 'antd';
import moment from 'moment';
import Upload from '../../components/Upload';
import { httpUrl } from '../../../fetch';
import { getDictionary, getRequirementDetail, addRequirement, updateRequirement } from '../api';
import './index.scss';
const Option = Select.Option;
const { TextArea } = Input;
const format = "YYYY-MM-DD HH:mm:ss";
export default Form.create()(forwardRef(({current_user, form, showNotification, match, history }, ref) => {
const [requireType, setRequireType] = useState([]);
const [tagType, setTagType] = useState([]);
const [fileList, setFileList] = useState(null);
const [typeCode, setTypeCode] = useState('');
const [typeName, setTypeName] = useState('');
const id = match.params.requireId;
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
useEffect(() => {
id && getRequirementDetail(id).then(data => {
const formValue = {
title: data.title,
attachments: data.attachments,
// typeCode: data.typeCode, //使select labelInValue
endTime: moment(data.endTime),
tag: data.tag,
remark: data.remark
};
setFieldsValue(formValue);
setTypeName(data.typeName);
setTypeCode(data.typeCode)
if (data.attachmentList.length) {
for (const item of data.attachmentList) {
item.name = item.fileName;
item.size = item.fileSize;
item.uid = "rc-upload" + item.id
}
setFileList(data.attachmentList);
}
})
}, [id]);
//
useEffect(() => {
getDictionary('requirement_type').then((res) => {
setRequireType(res.data);
});
getDictionary("tag_type").then((res) => {
setTagType(res.data);
});
}, []);
//
function UploadFunc(fileList) {
setFileList(fileList);
let files = [];
for (const item of fileList) {
files.push(item.id || item.response.data.id);
}
setFieldsValue({
attachments: files.join()
});
}
const helper = useCallback(
(label, name, rules, widget, initialValue) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
</Form.Item>
), []);
const formItemLayout = {
labelCol: {
xs: { span: 12 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 12 },
sm: { span: 16 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 20,
offset: 4,
},
sm: {
span: 20,
offset: 4,
},
},
};
//
function saveItem() {
validateFields((error, values) => {
if (!error) {
let params = {
...values,
createUserAccount:current_user.login|| sessionStorage.getItem("SET_Account"), //
createUserName:current_user.username|| sessionStorage.getItem("SET_NAME"), //使
typeName,
typeCode,
status: 0, //
};
params.tag = params.tag.join();
params.endTime = params.endTime.format(format);
if (id) {
//
params.id = id;
updateRequirement(params).then(res => {
if (res.code === '1') {
showNotification("需求更新成功!");
history.go(-1);
} else {
showNotification(res.message);
}
});
} else {
//
addRequirement(params).then(res => {
if (res.code === '1') {
showNotification("需求新增成功!");
history.go(-1);
} else {
showNotification(res.message);
}
});
}
}
})
}
function changeTypeName(value) {
setTypeCode(value.key);
setTypeName(value.label);
}
return (
<div className="centerbox">
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">{id ? '修改' : '新增'}需求</div>
</div>
<Form className="achieve-form" {...formItemLayout}>
{helper(
"需求名称:",
"title",
[{ required: true, message: "请输入需求名称" }],
<Input
className="edit-input"
placeholder="请输入需求名称"
/>
)}
{helper(
"需求类型:",
"typeCode",
[{ required: true, message: "请选择需求类别" }],
<Select placeholder="请选择需求类别"
className="edit-input"
labelInValue
onChange={changeTypeName}
>
{
requireType.map(item => {
return <Option key={item.id + ''} value={item.id + ''}>{item.dicItemName}</Option>
})
}
</Select>
, { key: typeCode, label: typeName })}
{helper(
"结束时间:",
"endTime",
[{ required: true, message: "请输入结束时间" }],
<DatePicker
showTime
format={format}
placeholder="请输入结束时间"
/>
)}
<Form.Item label={"需求文件:"} required={true}>
<Upload
className="commentStyle"
load={UploadFunc}
size={100}
showNotification={showNotification}
actionUrl={httpUrl}
fileList={fileList}
/>
{/* 用一个隐藏的input实现上传文件的必填校验 */}
{getFieldDecorator('attachments', {
rules: [{ required: true, message: "请上传需求文件" }], validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
{helper(
"标签:",
"tag",
[{ required: true, message: "请选择需求标签" }],
<Select
placeholder="请选择需求标签"
className="edit-input"
mode="tags"
tokenSeparators={[',']}
>
{
tagType.map(item => {
return <Option key={item.dicItemName}>{item.dicItemName}</Option>
})
}
</Select>
)}
{helper(
"需求描述:",
"remark",
[{ required: true, message: "请输入需求描述" }],
<TextArea
placeholder="请输入需求描述"
autoSize={{ minRows: 3, maxRows: 5 }}
/>
)}
<Form.Item {...tailFormItemLayout}>
<Button className="mr20" type={"primary"} onClick={saveItem}>保存</Button>
<Button onClick={() => { history.go(-1) }}>取消</Button>
</Form.Item>
</Form>
</div>
</div>
)
})
)

View File

@ -0,0 +1,4 @@
.achieve-form{
padding:24px 40px 0px 40px;
}

View File

@ -0,0 +1,117 @@
import React, { useEffect, useState } from 'react';
import { Pagination, Button } from 'antd';
import ChooseNav from '../../components/chooseNav';
import ItemList from '../../components/itemList';
import { getDictionary, getRequirementList } from '../api';
export default (props) => {
const { current_user } = props;
// console.log(current_user);
const [requirementType, setrequirementType] = useState([]); //
const [requirementStatusArr, setrequirementStatusArr] = useState([]); //
const [requirementTypeName, setRequirementTypeName] = useState(''); //
const [requirementStatus, setRequirementStatus] = useState(''); //
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [requirementList, setRequirementList] = useState([]);
useEffect(() => {
getDictionary('requirement_type').then(res => {
if (res && res.data) setrequirementType(res.data);
});
getDictionary('requirement_status').then(res => {
if (res && res.data) setrequirementStatusArr(res.data);
});
}, []);
useEffect(() => {
const params = {
tag: null,
status: requirementStatus || null,
typeName: requirementTypeName || null,
queryType: 'all',
curPage,
pageSize: 10
};
getRequirementList(params).then(data => {
if (data && data.rows) {
setRequirementList(data.rows);
setTotal(data.total);
}
})
}, [requirementTypeName, requirementStatus, curPage]);
function changeOptionId(option, type) {
if (type === 'requirement_type') {
setRequirementTypeName(option.dicItemName);
setCurPage(1);
} else if (type === 'requirement_status') {
setRequirementStatus(option.dicItemCode);
setCurPage(1);
}
}
function goRequirementMine() {
props.history.push('/requirement/requireMine');
}
function goAdd() {
props.history.push("/requirement/requireAdd");
}
function achiveClick(id) {
props.history.push(`/requirement/requireDetail/${id}`);
}
return (
<div className="centerbox">
<div className="nav-content">
<ChooseNav
key={'requirement_type'}
type={'requirement_type'}
title={'需求类别'}
options={requirementType}
changeOptionId={changeOptionId}
/>
<ChooseNav
key={'requirement_status'}
type={'requirement_status'}
title={'需求状态'}
options={requirementStatusArr}
changeOptionId={changeOptionId}
/>
</div>
<div className="center-content">
<div className="centerScreen">
<div className="center-left-but">需求大厅</div>
{
current_user.login &&
<div className="center-right-but">
<Button className="mr15 font-12" size="small" type="primary" onClick={goRequirementMine}>我的需求</Button>
<Button className="mr20 font-12" size="small" type="primary" onClick={goAdd}><i className="iconfont icon-zaibianji font-12 mr3"></i>发布需求</Button>
</div>
}
</div>
<ItemList
list={requirementList}
itemClick={achiveClick}
/>
</div>
<div className="edu-txt-center ">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
showTotal={total => `${total}`}
/>
</div>
</div>
)
}

View File

@ -0,0 +1,333 @@
import React, { useEffect, forwardRef, useCallback, useState } from 'react';
import classnames from 'classnames';
import { Form, Radio, Input, Select, Pagination, Table, Button, Modal } from 'antd';
import DelModal from '../../components/DelModal';
import { deleteRequirement, getRequirementList, getAllUsers, updateRequirement } from '../api';
const Option = Select.Option;
const { TextArea } = Input;
const statusArr = ['待审核', '进行中', '成果验收中', '完成', '审核未通过', '延期', '其他', '验收未通过'];
const chooseStatusArr = ['待审核', '进行中', '成果验收中', '完成', '审核未通过', '延期', '全部'];
const statusColor = ['#f8c753', '#67c23a', '#67c23a', '#67c23a', '#F56C6C', '#f8c753', '#f8c753', '#F56C6C'];
export default Form.create()(forwardRef(({ form, showNotification, match, history }, ref) => {
const [requirementList, setRequirementList] = useState([]);
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [status, setStatus] = useState(6);
const [checkVisible, setCheckVisible] = useState(false);
const [checkStatus, setCheckStatus] = useState(1);
const [acceptVisible, setAcceptVisible] = useState(false);
const [currentId, setCurrentId] = useState('');
const [allUsers, setAllUsers] = useState([]);
const { getFieldDecorator, validateFields, } = form;
useEffect(() => {
getRequireList();
}, [curPage, status]);
useEffect(() => {
if (checkVisible) {
getAllUsers().then(res => {
if (res.code === '1') {
setAllUsers(res.data);
} else {
showNotification(res.message);
}
})
}
}, [checkVisible]);
function getRequireList() {
let searchStaus = "";
if (status !== 6) {
searchStaus = status;
}
const params = {
curPage,
pageSize: 10,
status: searchStaus,
tag: "",
title: "",
typeName: "",
currentUser: "",
queryType: "all" //all: my: tome:
};
getRequirementList(params).then(data => {
if (data) {
for (const item of data.rows) {
item.createUserName = item.createUser.nickname ? item.createUser.nickname : item.createUser.login;
}
setRequirementList(data.rows);
setTotal(data.total);
}
})
}
function detailItem(id) {
history.push(`/requirement/requireDetail/${id}`);
}
function editItem(id) {
history.push(`/requirement/requireEdit/${id}`);
}
function deletItem(id) {
DelModal(() => {
deleteRequirement(id).then(res => {
if (res.code === '1') {
showNotification("删除成功");
getRequireList();
} else {
showNotification("删除失败");
}
})
}, '此操作将删除该记录, 是否继续?');
}
//
function checkItem() {
validateFields((error, values) => {
if (!error) {
let params = {
id: currentId,
status: checkStatus, //
assignedUserLogin: values.vertifyUserAccount ? values.vertifyUserAccount.key : '',
assignedUserName: values.vertifyUserAccount ? values.vertifyUserAccount.label : '',
vertifyUserAccount: values.vertifyUserAccount ? values.vertifyUserAccount.key : '',
vertifyUserName: values.vertifyUserAccount ? values.vertifyUserAccount.label : '',
vertifyComments: values.vertifyComments,
};
console.log(params);
updateRequirement(params).then(res => {
if (res.code === '1') {
showNotification("操作成功!");
setCheckVisible(false);
getRequireList();
} else {
showNotification(res.message);
}
});
}
})
}
//
function acceptItem() {
validateFields((error, values) => {
if (!error) {
let params = {
status: values.status,
id: currentId,
checkComments: values.checkComments,
};
console.log(params);
updateRequirement(params).then(res => {
if (res.code === '1') {
showNotification("操作成功!");
setAcceptVisible(false);
getRequireList();
} else {
showNotification(res.message);
}
});
}
})
}
const columns = [
{
title: '需求标题',
dataIndex: 'title',
key: 'title',
width: '20%',
},
{
title: '类型',
dataIndex: 'typeName',
key: 'typeName',
},
{
title: '创建人',
dataIndex: 'createUserName',
key: 'createUserName',
},
{
title: '指派人',
key: 'assignedUserName',
dataIndex: 'assignedUserName',
},
{
title: '创建时间',
key: 'createTime',
dataIndex: 'createTime',
},
{
title: '结束时间',
key: 'endTime',
dataIndex: 'endTime',
},
{
title: '状态',
key: 'status',
dataIndex: 'status',
render: (text, record) => {
return <span style={{ color: statusColor[text] }}>{statusArr[text]}</span>
}
},
{
title: '操作',
key: 'action',
render: (text, record) => (
<span>
<Button className="mr5 font-12" type="primary" size="small" onClick={() => { editItem(record.id) }}><i className="iconfont icon-zaibianji font-15 mr3"></i></Button>
<Button className="mr5 font-12" type="danger" size="small" onClick={() => { deletItem(record.id) }}><i className="iconfont icon-shanchu font-15 "></i></Button>
<Button className="mr5 font-12" type="info" size="small" onClick={() => { detailItem(record.id) }}>详情</Button>
{record.status === '0' && <Button className="mr5 font-12" type="primary" size="small" onClick={() => { setCurrentId(record.id); setCheckVisible(true); }}>审核</Button>}
{record.status === '2' && <Button className="mr5 font-12" type="success" size="small" onClick={() => { setCurrentId(record.id); setAcceptVisible(true) }}>验收成果</Button>}
</span>
),
},
];
const helper = useCallback(
(label, name, rules, widget, initialValue) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
</Form.Item>
), []);
const formItemLayout = {
labelCol: {
xs: { span: 12 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 12 },
sm: { span: 18 },
},
};
return (
<React.Fragment>
<div className="choose-status">
{
chooseStatusArr.map((item, i) => {
return <Button className={classnames({ mr10: true, active: status === i })} type="dashed" key={i} onClick={() => { setStatus(i) }}> {item}</Button>
})
}
</div>
<Table
rowKey={(row) => row.id}
dataSource={requirementList}
columns={columns}
pagination={false}
/>
<div className="edu-txt-center mt10">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
/>
</div>
<Modal
title="需求审核"
visible={checkVisible}
onOk={checkItem}
onCancel={() => { setCheckVisible(false) }}
className="form-edit-modal"
>
{checkVisible && <Form {...formItemLayout}>
<Form.Item label="审批结果:">
<Radio.Group value={checkStatus} onChange={(e) => { setCheckStatus(e.target.value) }}>
<Radio className="columsRadio" value={1}>
同意
</Radio>
<Radio className="columsRadio" value={4}>
拒绝
</Radio>
</Radio.Group>
</Form.Item>
{helper(
"指派用户:",
"vertifyUserAccount",
[{ required: checkStatus === 1, message: "请指派用户" }],
<Select placeholder="请指派用户"
className="edit-input"
showSearch
labelInValue
disabled={checkStatus === 4}
filterOption={(input, option) =>
option.props && option.props.children && (option.props.children.indexOf(input) > -1 || option.props.children.toLowerCase().indexOf(input.toLowerCase()) > -1)
}
>
{
allUsers.map((item, i) => {
return <Option key={item.id} value={item.login}>{item.nickName}</Option>
})
}
</Select>
)}
{helper(
"审核意见:",
"vertifyComments",
[{ required: true, message: "请输入审核意见" }],
<TextArea
className="edit-input"
placeholder="请输入审核意见"
/>
)}
</Form>}
</Modal>
<Modal
title="验收成果"
visible={acceptVisible}
onOk={acceptItem}
onCancel={() => { setAcceptVisible(false) }}
className="form-edit-modal"
>
{acceptVisible && <Form {...formItemLayout}>
{helper(
"验收结果:",
"status",
[{ required: true, message: "请选择验收结果" }],
<Radio.Group>
<Radio className="columsRadio" value={3}>
同意
</Radio>
<Radio className="columsRadio" value={7}>
拒绝
</Radio>
</Radio.Group>
)}
{helper(
"验收意见:",
"checkComments",
[],
<TextArea
className="edit-input"
placeholder="请输入验收意见"
/>
)}
</Form>}
</Modal>
</React.Fragment>
)
})
)

View File

@ -0,0 +1,25 @@
import React from 'react';
import { Tabs } from 'antd';
import AllRequire from './allRequire';
import MyRequire from './myRequire';
import './index.scss';
const { TabPane } = Tabs;
export default (props) => {
return (
<div className="centerbox">
<Tabs className="tabs-style" type="card">
<TabPane tab="全部需求" key="1">
<AllRequire {...props}/>
</TabPane>
<TabPane tab="我的需求" key="2">
<MyRequire {...props}/>
</TabPane>
</Tabs>
</div>
)
}

View File

@ -0,0 +1,54 @@
// Tabs
.tabs-style{
background: #fff;
border: 1px solid #dcdfe6;
-webkit-box-shadow: 0 2px 4px 0 rgba(0,0,0,.12), 0 0 6px 0 rgba(0,0,0,.04);
box-shadow: 0 2px 4px 0 rgba(0,0,0,.12), 0 0 6px 0 rgba(0,0,0,.04);
padding-bottom: 1vw;
.ant-tabs-tab{
margin: 0 !important;
}
.ant-tabs-tab{
border-top:0 !important;
border-left:0 !important;
border-radius:0 !important;
}
.ant-tabs-nav .ant-tabs-tab{
padding:19px 0px;
margin-right: 40px;
}
.ant-tabs-ink-bar{
width:25px!important;
bottom: 10px;
}
}
.choose-status{
padding: 1em;
background: #fff;
}
.ant-btn-info{
color: #fff;
background-color: #909399;
border-color: #909399;
}
.ant-btn-success{
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.mt10{
margin-top:10px;
}
.form-edit-modal{
.ant-col{
display: inline-block;
}
.edit-input{
width: 300px;
}
}

View File

@ -0,0 +1,80 @@
import React, { useEffect, useState } from 'react';
import classnames from 'classnames';
import { Pagination, Button } from 'antd';
import ItemList from '../../components/itemList';
import DelModal from '../../components/DelModal';
import { deleteRequirement, getRequirementList } from '../api';
export default (props) => {
const [requirementList, setRequirementList] = useState([]);
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
// const [queryType, setQueryType] = useState("my");
const [queryType, setQueryType] = useState("all");
useEffect(() => {
getRequireList();
}, [curPage, queryType]);
function getRequireList() {
const params = {
curPage,
pageSize: 10,
status: "",
tag: "",
title: "",
typeName: "",
currentUser: "",
queryType, //all: my: tome:
};
getRequirementList(params).then(data => {
setRequirementList(data.rows);
setTotal(data.total);
})
}
function detailItem(id) {
props.history.push(`/requirement/requireDetail/${id}`);
}
function editItem(id) {
props.history.push(`/requirement/requireEdit/${id}`);
}
function deletItem(id) {
DelModal(() => {
deleteRequirement(id).then(res => {
if (res.code === '1') {
props.showNotification("删除成功");
getRequireList();
} else {
props.showNotification("删除失败");
}
})
}, '此操作将删除该记录, 是否继续?');
}
return (
<React.Fragment>
<div className="choose-status">
<Button className={classnames({ mr10: true, active: queryType === "my" })} type="dashed" key="my" onClick={() => { setQueryType("my") }}>我创建的</Button>
<Button className={classnames({ mr10: true, active: queryType === "tome" })} type="dashed" key="tome" onClick={() => { setQueryType("tome") }}> 指派给我的 </Button>
</div>
<ItemList
list={requirementList}
itemClick={detailItem}
deletItem={queryType === "my" && deletItem}
editItem={queryType === "my" && editItem}
activeByStatus={queryType === "my"}
/>
<div className="edu-txt-center mt10">
<Pagination
showQuickJumper
onChange={(page) => { setCurPage(page) }}
current={curPage}
total={total}
/>
</div>
</React.Fragment>
)
}

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,23 +6,23 @@ 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}`
}
return `${path}`;
return `/${path}`;
}
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 +93,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,28 +162,28 @@ export function getmyUrl(geturl) {
}
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
return `${getUrl()}/api/attachments.json`;
}
export function getUploadLogoActionUrl() {
return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`;
}
export function getUploadActionUrltwo(id) {
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}`
}
export function getUploadActionUrlthree() {
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}`
}
export function getupload_git_file(id) {
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json?debug=${window._debugType || 'admin'}`
}
export function getUploadActionUrlOfAuth(id) {
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}`
}
export function getRandomNumber(type) {

View File

@ -64,7 +64,7 @@ function CommentItem({
const commentAvatar = (author) => (
<img
className="item-flex flex-image"
src={author.image_url ? getImageUrl(`/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
src={author.image_url ? getImageUrl(`images/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
alt=""
/>
);

View File

@ -46,18 +46,18 @@ export default ({
let id = decodeURIComponent(u.split("#")[1]);
let ele = document.getElementById(id);
if(ele){
window.scrollTo(0, ele.offsetTop + 120);
window.scrollTo(0, ele.offsetTop + 220);
}
}
}
},[url,html])
},[url])
const el = useRef();
function onAncherHandler(e) {
let target = e.target;
let target = e.target
if (target.tagName.toUpperCase() === 'A') {
let ancher = target.getAttribute('href');
if (ancher && ancher.startsWith('#')) {
let ancher = target.getAttribute('href')
if (ancher.startsWith('#')) {
e.preventDefault()
let viewEl = document.getElementById(ancher.replace('#', ''))
if (viewEl) {

85
src/fetch.js Normal file
View File

@ -0,0 +1,85 @@
import axios from 'axios';
import cookie from 'react-cookies';
export const httpUrl='http://117.50.100.12:8001';
const TokenKey = 'autologin_forge_military';
axios.defaults.withCredentials = true;
// 创建axios实例
const service = axios.create({
// baseURL: process.env.BASE_API, // api的base_url
baseURL:httpUrl,
timeout: 5000 // 请求超时时间
// headers:{'X-Custom-Header': 'foobar'} // 请求头
});
// request拦截器
service.interceptors.request.use(config => {
if (cookie.load(TokenKey)) {
config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
// config.headers['Authorization'] = 'autologin_forge_military=' + cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config;
}, error => {
// Do something with request error
console.log(error); // for debug
Promise.reject(error);
});
// respone拦截器
service.interceptors.response.use(
response => {
/**
* 下面的注释为通过response自定义code来标示请求状态当code返回如下情况为权限有问题登出并返回到登录页
* 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
*/
const res = response;
if (res.status === 400) {
// Message({
// message: '请求错误',
// type: 'error',
// duration: 5 * 1000
// });
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('error');
}
if (res.status === 401) {
// Message({
// message: '未授权,请登录!',
// type: 'error',
// duration: 5 * 1000
// });
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('error');
}
if (res.status === 40001) {
// Message({
// message: '账户或密码错误!',
// type: 'warning'
// });
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('error');
}
if (response.status !== 200 && res.status !== 200) {
// Message({
// message: res.message,
// type: 'error',
// duration: 7 * 1000
// });
} else {
return response.data;
}
},
error => {
if (error.response&& error.response.status === 401 && !error.config.url.includes('/auth-server/oauth/token')) {
return cookie.remove(TokenKey);
// that.$router.push('/Login');
} else {
// that.$router.push('/Login');
}
return Promise.reject(error);
}
);
export default service;

View File

@ -67,14 +67,15 @@ function Index(props){
}
return(
<div className="aboutPanels">
<div className="aboutContent">
<AlignCenterBetween style={{padding:"14px 20px"}}>
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目概览</span>
<AlignCenterBetween style={{padding:"14px 0px"}}>
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目简介</span>
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
</AlignCenterBetween>
{
edit ?
<div className="padding20">
<div>
<MDEditor
placeholder={"请输入描述信息"}
height={500}
@ -113,11 +114,11 @@ function Index(props){
</div>
</div>
:
<div className="padding20">
<div style={{padding:"20px 0px"}}>
{content ?
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
:
<div>暂无概览~</div>
<div>暂无简介~</div>
}
{attachments && attachments.length > 0 &&
<Attachments

View File

@ -4,6 +4,7 @@
.aboutContent{
border-radius: 2px;
border: 1px solid #EEEEEE;
padding:0px 30px;
width:100%;
background-color: #fff;
margin-top:20px;

View File

@ -1,7 +1,7 @@
import React , { Component } from 'react';
import { Dropdown , Menu , Icon , Pagination , Spin } from 'antd';
import '../css/index.scss';
import '../Branch/branch.scss';
import '../Branch/branch.css';
import './activity.css';
import NoneData from '../Nodata';

View File

@ -33,7 +33,7 @@ class ActivityItem extends Component {
}
<p className="itemLine mt10">
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}

View File

@ -1,35 +1,39 @@
import React, { useState } from 'react';
import { Dropdown, Menu, Tooltip } from 'antd';
import "./branch.scss";
import React, { Component } from 'react';
import { Dropdown, Icon, Tooltip } from 'antd';
import "./branch.css";
function CloneAddress({http_url , ssh_url , zip_url , tar_url}) {
const [ key , setKey ] = useState("HTTP");
class CloneAddress extends Component {
// 点击按钮复制功能
function jsCopy(){
jsCopy = () => {
var e = document.getElementById("copy_rep_content");
e.select();
document.execCommand("Copy");
}
return (
<div className="downMenu">
<div style={{padding:"10px 20px 20px 20px",borderBottom:"1px solid #eee"}}>
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
<Menu.Item key="HTTP" onClick={(e)=>{setKey(e.key)}}>HTTP</Menu.Item>
<Menu.Item key="SSH" onClick={(e)=>{setKey(e.key)}}>SSH</Menu.Item>
</Menu>
<div className="gitAddressClone">
<input type="text" id="copy_rep_content" value={key==="HTTP" ? http_url:ssh_url} />
<Tooltip title="复制链接">
<span className="color-blue" onClick={jsCopy}><i className="iconfont icon-fuzhi"></i></span>
</Tooltip>
</div>
render() {
const { http_url, downloadUrl } = this.props;
return (
<div className="gitAddressClone">
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
{
http_url && <span>HTTP</span>
}
<input type="text" id="copy_rep_content" value={http_url} />
<Tooltip title="复制链接">
<span className="color-blue" onClick={() => this.jsCopy()}><i className="iconfont icon-fuzhi"></i></span>
</Tooltip>
{
downloadUrl &&
<span>
<Dropdown overlay={downloadUrl} trigger={['click']} placement="bottomRight">
<a className="ant-dropdown-link">
<Icon type="cloud-download" className="font-18 fl color-blue" />
</a>
</Dropdown>
</span>
}
</div>
<Menu className="edu-txt-center">
<Menu.Item><a href={zip_url}>下载 ZIP</a></Menu.Item>
<Menu.Item><a href={tar_url}>下载 TAR.GZ</a></Menu.Item>
</Menu>
</div>
)
)
}
}
export default CloneAddress;

View File

@ -1,6 +1,6 @@
import React , { useState , useEffect } from 'react';
import { Popover , Input , Spin } from 'antd';
import './branch.scss';
import './branch.css';
import { getBranch , getTag } from '../GetData/getData';
@ -102,10 +102,9 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
</div>
);
return(
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<div className="branch-tagBox">
{/* {nav === 0 ?"分支":"标签"} */}
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
<a className="ant-dropdown-link">
{showValue}
</a>

View File

@ -51,7 +51,7 @@
display: flex;
align-items: center;
cursor: pointer;
min-width: 140px;
min-width: 240px;
}
.branch-tagBox-list .ant-popover-arrow{
display: none;
@ -81,25 +81,4 @@
.listTips{
padding:20px 0px;
text-align: center;
}
.urlMenu{
line-height: 30px;
margin-bottom: 10px;
border-bottom: none;
li.ant-menu-item{
height: 30px;
line-height: 30px;
padding:0px 5px;
margin-right: 20px!important;
&.ant-menu-item-selected,&.ant-menu-item-active{
color: #333;
}
&.ant-menu-item-selected{
border-color:#1890ff!important;
}
&.ant-menu-item-active{
border-color:transparent ;
}
}
}

View File

@ -4,7 +4,7 @@ import axios from 'axios';
import { getImageUrl } from 'educoder';
const { Option } = AutoComplete;
function AddMember({getID,login,showNotification}){
function AddMember({getID,login}){
const [ id , setID ] = useState(undefined);
const [ source , setSource ] = useState(undefined);
const [ searchKey , setSearchKey ] = useState(undefined);
@ -42,10 +42,10 @@ function AddMember({getID,login,showNotification}){
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`/${item && item.image_url}`)}
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ verticalAlign: "middle" }}>
<span className="ml10" style={{ "vertical-align": "middle" }}>
{item.username}
<span className="color-grey ml10">({item.login})</span>
</span>
@ -66,12 +66,7 @@ function AddMember({getID,login,showNotification}){
};
function addCollaborator(){
if(source && source.length>0){
getID && getID(id);
setSearchKey(undefined);
}else{
showNotification("请选择存在的用户!");
}
getID && getID(id);
}
return(

View File

@ -3,10 +3,10 @@ import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
import './Component.scss';
function Cards({img , title, desc , rightBtn , src , bottomInfos}){
function Cards({img , title, desc , rightBtn , src}){
return(
<div className="cards">
{img &&<div className="img"><img src={getImageUrl(`/${img}`)} alt=""/></div>}
{img &&<div className="img"><img src={getImageUrl(`images/${img}`)} alt=""/></div>}
<div className="content">
<p className="titles">
<Link to={src}>{title}</Link>
@ -15,7 +15,6 @@ function Cards({img , title, desc , rightBtn , src , bottomInfos}){
<div className="desc">
{desc}
</div>
{bottomInfos}
</div>
</div>
)

View File

@ -20,7 +20,6 @@ li.ant-menu-item{
background-color: #fff;
margin-bottom:18px;
min-height: 130px;
border:1px solid #eee;
.img{
margin-right: 20px;
width: 190px;
@ -62,7 +61,6 @@ li.ant-menu-item{
}
// Tabs
.tabsStyle{
border:1px solid #eee;
.ant-tabs-bar.ant-tabs-top-bar{
padding-left: 35px;
margin-bottom: 0px;
@ -112,9 +110,6 @@ li.ant-menu-item{
right:240px;
z-index: 10000;
}
.laterest{
color: #05690d;
}
@media screen and (max-width: 1800px){
.handleBox{
@ -140,224 +135,4 @@ li.ant-menu-item{
.handleBox{
right:0px;
}
}
.ant-drawer{
z-index: 10000!important;
}
.ant-drawer-body{
padding:0px!important;
.drawerHead{
background-color: #333;
color: #fff;
padding:15px 20px;
}
.ant-tree{
margin:0px 20px!important;
}
}
.menuPanels{
width: 240px;
height: 180px;
.ant-popover-content,.ant-popover-inner{
height: 100%;
width: 100%;
}
}
.halfs{
margin-top: 24px;
padding:24px 0px 0px 0px;
border-top: 1px solid #e8e8e8;
.attrPerson{
padding-bottom: 24px;
}
}
.menuinfos{
padding:15px 0px;
&>a{
display: flex;
flex-direction: column;
align-items: center;
border-right: 1px solid #eee;
flex: 1;
& >span:first-child{
font-size: 18px;
font-weight: 400;
color: #333;
}
& >span:last-child{
color: #666;
}
&:last-child{
border-right: none;
}
}
}
/*-------------------个人主页:右侧提示区域--------------------------*/
.-task-sidebar {
position: fixed;
width: 40px;
right: 0;
bottom: 80px;
z-index: 10;
}
@media screen and (max-width: 1920px){
.-task-sidebar{
right:220px;
}
}
@media screen and (max-width: 1750px){
.-task-sidebar{
right:160px;
}
}
@media screen and (max-width: 1650px){
.-task-sidebar{
right:115px;
}
}
@media screen and (max-width: 1550px){
.-task-sidebar{
right:90px;
}
}
@media screen and (max-width: 1450px){
.-task-sidebar{
right:45px;
}
}
@media screen and (max-width: 1200px){
.-task-sidebar{
right:0px;
display: none;
}
}
.-task-sidebar>div {
height: 40px;
line-height: 40px;
box-sizing: border-box;
width: 40px;
color: #999;
font-size: 20px;
text-align: center;
margin-bottom: 20px;
border-radius: 50%;
background: #FFFFFF;
box-shadow: 0px 0px 10px 1px #F1F1F1;
}
.-task-sidebar>div i {
color: #999;
}
.-task-sidebar>div:hover i {
color: #fff !important;
}
.-task-sidebar>div:hover{
background: #1890FF;
box-shadow: 0px 0px 10px 2px #B6D0FC;
}
.helpBox{
width: 260px;
z-index: 103;
&.shareContent{
width: 200px;
}
.ant-popover-inner-content{
padding:0px;
}
p.titlecontent{
font-size: 18px;
color: #333;
line-height: 20px;
padding:15px 20px;
}
.faqUl{
padding:0px 20px 10px;
max-height: 230px;
overflow-y: auto;
li{
background: #F5F5F5;
border-radius: 20px;
padding:0px 20px;
color: #333;
height: 34px;
line-height: 34px;
margin-bottom: 10px;
a{
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&:hover{
background-color: #D1E9FF;
a{
color: #333!important;
}
}
}
}
.shareUl{
padding:10px 0px;
display: flex;
align-items: center;
.titlecontent{
margin-right: 20px;
}
li > i{
font-size: 32px!important;
}
}
}
.-task-desc {
background: #494949;
width: 90px;
line-height: 36px;
text-align: center;
position: absolute;
color: #fff;
font-size: 13px;
z-index: 999999;
opacity: 0;
}
.-task-desc div {
position: absolute;
top: 10px;
right: -7px;
height: 13px;
}
.-task-desc div img {
float: left
}
.-task-sidebar .scan_ewm {
position: absolute !important;
right: 45px !important;
bottom: 0px !important;
background-color: #494949 !important;
-webkit-box-sizing: border-box !important;
box-sizing: border-box !important;
font-size: 14px !important;
line-height: 16px !important;
display: none;
height: 213px !important;
}
.trangle_right {
position: absolute;
right: -5px;
bottom: 15px;
width: 0;
height: 0px;
border-top: 6px solid transparent;
border-left: 5px solid #494949;
border-bottom: 6px solid transparent
}
}

View File

@ -1,160 +0,0 @@
import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom';
import { Popover , Spin } from 'antd';
import { getImageUrl } from 'educoder';
import './Component.scss';
import { getUser } from '../GetData/getData';
import axios from 'axios';
function Contributors({contributors,owner,projectsId}){
const [ menuList ,setMenuList ]= useState([]);
const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0);
const [ menu , setMenu ] = useState("");
const [ login , setLogin ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(false);
useEffect(()=>{
if(contributors && contributors.total_count>0){
setTotal(contributors.total_count);
setList(contributors.list);
}
},[contributors])
useEffect(()=>{
if(login){
getUsers(login);
}else{
setMenu(undefined);
}
},[login])
async function getUsers(login){
setIsSpin(true);
let a = menuList && menuList.filter(i=>i.login === login);
if(a.length === 0){
let result = await getUser(login);
let arr = menuList;
arr.push({...result});
setMenuList(arr);
setMenusFunc(result);
setIsSpin(false);
}else{
setMenusFunc(a[0]);
setIsSpin(false);
}
}
function setMenusFunc(data){
if(data){
let ele = (
<Spin spinning={isSpin}>
<FlexAJ>
<AlignCenter>
<Link to={`/users/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
<Link to={`/users/${data.login}`} className="ml10">{data.name}</Link>
</AlignCenter>
{
data.is_watch ? <a className="color-grey-9" onClick={()=>FocusFunc(false,data.login)}>取消关注</a>:<a className="color-blue" onClick={()=>FocusFunc(true,data.login)}>关注</a>
}
</FlexAJ>
<AlignCenter className="menuinfos">
<a href={data.projects_url}>
<span>{data.projects_count}</span>
<span>项目数</span>
</a>
<a href={data.followers_url}>
<span>{data.followers_count}</span>
<span>粉丝数</span>
</a>
<a href={data.following_url}>
<span>{data.following_count}</span>
<span>关注数</span>
</a>
</AlignCenter>
{
data.organizations && data.organizations.length > 0 ?
<AlignCenter className="font-12 pt4 pb4">
<span>所属组织</span>
<div className="task-hide flex1">
{renderArray(data.organizations)}
</div>
</AlignCenter>
:""
}
{
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
}
</Spin>
)
setMenu(ele);
}
}
function FocusFunc(flag,login){
axios({
method: flag ? 'post' : 'delete',
url: `/watchers/${flag ? 'follow' : 'unfollow'}.json`,
params: {target_type: "user",id:login}
}).then(result => {
if (result && (result.data.status === 0 || result.data.status === 2)) {
let a = menuList && menuList.filter(i=>i.login === login);
if(a){
a[0].is_watch = flag;
}
setMenusFunc(a[0]);
}
})
.catch(error => {
console.log(error);
});
}
function renderArray(array){
let str = "";
for(var i = 0;i<array.length;i++){
str += array[i].name +"、";
}
let substr = str.substr(0,str.length-1);
return (<span title={substr}>{substr}</span>)
}
function setVisibleFunc(flag,l,index){
if(l !== login){
setLogin(l);
}
var lx = list.concat();
lx.map(i=>i.visible =false);
if(flag){
lx[index].visible = flag;
}
lx.splice();
setList(lx);
}
return(
<div className="halfs">
<FlexAJ>
<AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter>
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/contribute`}>全部</Link>
</FlexAJ>
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
{
total > 0 ?
list.map((item,key)=>{
return(
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
<Link key={key} to={`/users/${item.login}`}>
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
</Link>
</Popover>
)
})
:""
}
</div>
</div>
)
}
export default Contributors;

View File

@ -1,35 +0,0 @@
import React from 'react';
import { AlignCenter } from '../layout';
import { Modal , Button } from 'antd';
import './Index.scss';
function DeleteBox({
visible ,
onCancel ,
onSuccess ,
title ,
subTitle,
content
}) {
return(
<Modal
visible={visible}
onCancel={onCancel}
title={title}
width="600px"
className="deleteBox"
footer={
<div>
<Button size={'large'} onClick={onCancel}>取消</Button>
<Button type={"danger"} size={"large"} onClick={onSuccess}>确认删除</Button>
</div>
}
>
<div className="desc">
<AlignCenter className="descMain"><i className="iconfont icon-shanchu_tc_icon mr10"></i>{content}</AlignCenter>
<p>{subTitle}</p>
</div>
</Modal>
)
}
export default DeleteBox;

View File

@ -1,45 +0,0 @@
.deleteBox{
.ant-modal-header{
background-color: #f8f8f8;
border-bottom: none;
.ant-modal-title{
text-align: left;
font-size: 20px;
}
}
.ant-modal-body{
padding:30px 50px;
p{
font-size: 16px;
line-height: 26px;
color:#666;
word-break: break-all;
}
.desc{
.descMain{
align-items: center;
justify-content: center;
font-size: 20px;
margin-bottom: 10px;
i{
font-size: 38px!important;
color:#DF0002
}
}
}
}
.ant-modal-footer{
border-top: none;
text-align: center;
padding-bottom: 40px;
button{
width: 120px;
margin:0px 20px;
&.ant-btn-danger{
background-color: #fff;
color: #DF0002;
border-color: #D0D0D0;
}
}
}
}

View File

@ -1,106 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Drawer , Tree , Spin } from 'antd';
import './Component.scss';
import axios from 'axios';
const { TreeNode , DirectoryTree } = Tree;
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , list}){
const [ treeData , setTreeData ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true);
const [first , setFirst ] = useState(true);
useEffect(()=>{
if(visible && first){
if(list){
setTreeData(list);
setIsSpin(false);
}else{
getMenulist();
}
setFirst(false);
}
},[visible])
function getMenulist(){
const url = `/${owner}/${projectsId}/entries.json`;
axios.get(url,{ params: { ref: branch } }).then(result=>{
if(result){
setTreeData(result.data.entries);
}
setIsSpin(false);
}).catch(error=>{})
}
function renderTreeNodes(data) {
return data && data.length > 0 && data.map((item) => {
return (
<TreeNode title={item.name} key={item.key} dataRef={item} isLeaf={item.type === "file"}>
{renderTreeNodes(item.children)}
</TreeNode>
);
});
}
function onLoadData(tr){
return new Promise((resolve) => {
if (tr.props.children) {
resolve();
return;
}
let en = [];
const url = `/${owner}/${projectsId}/sub_entries.json`;
axios.get(url, {
params:{
filepath:tr.props.dataRef.path,
ref:branch,
type:"dir"
}
}).then((result) => {
if(result){
en = result.data.entries;
}
}).catch(error=>{})
setTimeout(() => {
tr.props.dataRef.children = en;
setTreeData([...treeData]);
resolve();
}, 2000);
});
}
function selectTree(keys,event){
let dataref = event.node.props.dataRef;
if(dataref.type==="file"){
onClose();
let value = turnbar(branch);
history.push(`/projects/${owner}/${projectsId}/tree/${value}/${dataref.path}`);
}
}
return(
<Drawer
placement="left"
visible={visible}
closable={false}
onClose={onClose}
width={"320px"}
maskStyle={{backgroundColor:'rgba(0,0,0,0.09)'}}
>
<Spin spinning={isSpin}>
<div className="drawerHead">
<p className="font-20">{name}</p>
<p><i class="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>{branch}</p>
</div>
<DirectoryTree loadData={onLoadData} onSelect={selectTree}>
{treeData && renderTreeNodes(treeData)}
</DirectoryTree>
</Spin>
</Drawer>
)
}
export default DrawerPanel;

View File

@ -1,6 +0,0 @@
.ant-modal-mask{
z-index: 1001;
}
.ant-modal-wrap{
z-index: 1002;
}

View File

@ -1,60 +0,0 @@
import React , {forwardRef, useEffect} from 'react';
import { Modal , Form , Input , Button } from 'antd';
import './EAccount.scss';
function EducoderAccount({form , visible , onOk , email}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{
if(email){
setFieldsValue({email})
}
},[email])
function onSure(){
validateFields((error,values)=>{
if(!error){
onOk(values);
}
})
}
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
return(
<Modal
visible={visible}
title="提示"
width="500px"
closable={false}
footer={
<Button type="primary" onClick={onSure}>确定</Button>
}
centered
>
<div>
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
为确保您能正常使用平台功能请确认以下信息:
</p>
<Form {...layout}>
<Form.Item label="邮箱">
{getFieldDecorator("email",{
rules:[{required:true,message:"请输入邮箱账号"}]
})(
<Input placeholder="请输入您的邮箱账号" width="220px"/>
)}
</Form.Item>
<Form.Item label="密码">
{getFieldDecorator("password",{
rules:[{required:true,message:"请输入邮箱密码"}]
})(
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
)}
</Form.Item>
</Form>
</div>
</Modal>
)
}
export default Form.create()(forwardRef(EducoderAccount));

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=>{

View File

@ -5,7 +5,7 @@ import './Component.scss';
export default (()=>{
return(
<div className="handleBox">
<a href="https://forum.trustie.net/forums/3075/detail" target="_blank" >
<a href="https://forum.trustie.net/forums/3075/detail" ta rget="_blank" >
<img src={Handbook} alt=""/>
</a>
</div>

View File

@ -1,41 +0,0 @@
import React, { useState } from "react";
import { Input ,notification} from "antd";
const { Search } = Input;
export default ({history}) => {
const [openSearch, setOpenSearch] = useState(false);
function onGlobalSearch(value) {
history.push('/search?value=' + value);
// window.location.href = `search?value=` + value;
// history.push({
// pathname:'/search',
// state:value
// })
}
return (
<React.Fragment>
{
openSearch ?
<div
onBlur={() => {
setTimeout(() => {
setOpenSearch(false)
}, 500)
}}
>
<Search placeholder="请输入搜索关键字"
className={`search-input mr20`}
onSearch={onGlobalSearch}
autoFocus={true}
style={{width:'260px'}}
/>
</div>
:
<i className="iconfont icon-sousuo font-18 color-grey-6 ml30" onClick={() => {
setOpenSearch(true)
}} />
}
</React.Fragment>
)
};

View File

@ -1,54 +0,0 @@
import React, { useEffect, useState } from 'react';
import { FlexAJ } from '../Component/layout';
function LanguagePower({languages}){
const [ array , setArray ] = useState(undefined);
useEffect(()=>{
if(languages){
let arr = [];
Object.keys(languages).map((item,key)=>{
arr.push({name:item,percent:languages[item],color:getColor()});
})
setArray(arr);
}
},[languages])
 function getColor(){
let str = "#";
let arr = ["1","2","3","4","4","5","6","7","8","9","a","b","c","d","e","f"];
for(var i=0;i<6;i++){
let num = parseInt(Math.random() * 16);
str+=arr[num];
}
return str;
}
return(
<div>
<p className="font-16 color-grey-6">开发语言</p>
<div className="progress">
{
array && array.map((item,key)=>{
return(
<span style={{width:item.percent,backgroundColor:item.color}}></span>
)
})
}
</div>
{
array && array.length > 0 &&
<FlexAJ className="progresstip">
{
array.map((item,key)=>{
return(
<span><i className="zero" style={{backgroundColor:`${item.color}`}}></i><span>{item.name}</span><span>{item.percent}</span></span>
)
})
}
</FlexAJ>
}
</div>
)
}
export default LanguagePower;

View File

@ -45,7 +45,7 @@ const Div = styled.div`{
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
return (
<Div>
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`images/${img}`)} /></Link>
<div className="m-infos">
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>

View File

@ -1,62 +0,0 @@
import React, {useEffect, useRef, useState} from 'react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
import './Component.scss';
function Monaco(props) {
const {
style = { // dom
height: '400px',
},
value = '', //
onChange = () => { //
},
fontSize = 14, //
monacoOptions = {
scrollBeyondLastLine: false,
lineNumbers: "off",
wordWrap: true,
overviewRulerBorder: true,
lineHeight: 24,
readOnly:true
}, // monaco
language = 'html', // js ts sql css json html
} = props;
const editOrRef = useRef();
const ThisEditor = useRef();
useEffect(() => {
ThisEditor.current = monaco.editor.create(editOrRef.current, {
value: value || '',
language,
theme: "vs-grey",
fontSize: fontSize + 'px',
minimap: { //
enabled: false,
},
...monacoOptions,
});
ThisEditor.current.onDidChangeModelContent((e) => {
let newValue = ThisEditor.current.getValue();
onChange(newValue);
});
return () => {
ThisEditor.current.dispose();
ThisEditor.current = undefined; //
}
}, []);
useEffect(() => {
if (ThisEditor.current) {
ThisEditor.current.updateOptions({
fontSize: fontSize + 'px',
})
}
}, [fontSize]);
return (
<div style={style} ref={editOrRef}>
</div>
);
}
export default Monaco;

View File

@ -1,41 +0,0 @@
import React from 'react';
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom';
function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
return(
<div>
<FlexAJ>
<AlignCenter><span className="font-16 color-grey-6">发行版</span>
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
</AlignCenter>
{ (releaseVersions && releaseVersions.total_count > 0) || projectType ===2 ?
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/releases`}>全部</Link>
:
baseOperate && <Link className="font-12 color-blue" to={`/projects/${owner}/${projectsId}/releases/new`}>新建</Link>
}
</FlexAJ>
{
releaseVersions && releaseVersions.total_count>0 ?
releaseVersions.list.map((item,key)=>{
return(
key === 0 &&<AlignTop className="mt10">
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
<div>
<p className="font-16 color-grey-6">
<Link to={`/projects/${owner}/${projectsId}/releases`}>{item.name}</Link>
<span className="font-12 laterest ml5">最新</span>
</p>
<p className="color-grey-9 font-13">{item.created_at}</p>
</div>
</AlignTop>
)
})
:""
}
</div>
)
}
export default Releases;

View File

@ -1,54 +1,50 @@
import React , { useState , useEffect } from 'react';
import React , { useState } from 'react';
import { AutoComplete } from 'antd';
import { getImageUrl } from "educoder";
import axios from 'axios';
const Option = AutoComplete.Option;
export default ({ getUser , placeholder, width ,value })=>{
const [ source , setSource ] = useState(undefined);
export default ({ getUser })=>{
const [ searchKey , setSearchKey ] = useState(undefined);
useEffect(()=>{
if(!value){
setSearchKey(undefined);
}
},[value])
useEffect(()=>{
getUserList();
},[searchKey])
const [ userDataSource , setUserDataSource ] = useState(undefined);
function getUserList(e){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: searchKey,
search: e,
},
}).then((result) => {
})
.then((result) => {
if (result) {
sourceOptions(result.data.users);
setUserDataSource(result.data.users);
}
})
.catch((error) => {
console.log(error);
});
};
function changeInputUser(value){
setSearchKey(value);
getUserList(value);
}
function sourceOptions(userDataSource){
const s = userDataSource && userDataSource.map((item, key) => {
function selectInputUser(id, option){
setSearchKey(option.props.value);
getUserList(option.props.value);
getUser && getUser(id);
}
const source =
userDataSource && userDataSource.map((item, key) => {
return (
<Option
key={key}
value={`${item.user_id}`}
login={`${item.login}`}
name={item.username}
>
<Option key={key} value={`${item.login}`}>
<img
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`/${item && item.image_url}`)}
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>
@ -58,31 +54,14 @@ export default ({ getUser , placeholder, width ,value })=>{
</Option>
);
});
setSource(s);
}
function changeInputUser(e){
setSearchKey(e);
};
//
function selectInputUser(e, option){
setSearchKey(option.props.name);
getUser(option.props.login);
};
return(
<div className="addPanel">
<AutoComplete
getPopupContainer={trigger => trigger.parentNode}
dataSource={source}
value={searchKey}
style={{ width: width || 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder={placeholder || "搜索需要添加的用户..."}
allowClear
/>
</div>
<AutoComplete
dataSource={source}
value={searchKey}
style={{ width: 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder="搜索需要添加的用户..."
/>
)
}

View File

@ -1,91 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Popover , Tooltip } from 'antd';
import './Component.scss';
import axios from 'axios';
import ShareModal from './SiderBarShareModal';
const $ = window.$;
$(window).scroll(function () {
if ($(".gotop").length > 0) {
if ($(document).scrollTop() > 0) {
$(".-task-sidebar .gotop").show();
$(".gotop").click(function () {
$("html,body").scrollTop(0);
});
}
if ($(document).scrollTop() === 0) {
$(".-task-sidebar .gotop").hide();
}
}
});
function SiderBar() {
const [ data , setData ] = useState([]);
const [ visible , setVisible ] = useState(false);
useEffect(()=>{
getFAQ();
},[])
function getFAQ(){
const url = `/faqs.json`;
axios.get(url).then(result=>{
if(result && result.data){
setData(result.data);
}
}).catch(error=>{})
}
function content(list){
return <div>
<p className="titlecontent">帮助</p>
<ul className="faqUl">
{
list && list.map((i,k)=>{
return(
<li key={i.question+k}><a href={`${i.url}`} title={i.question} target="_blank">{i.question}</a></li>
)
})
}
</ul>
</div>
}
function shareContent(){
return <div>
<ul className="shareUl">
<p className="titlecontent">分享到</p>
<li onClick={()=>setVisible(true)}><i className="iconfont icon-weixin2" style={{color:"#62b900"}}></i></li>
</ul>
</div>
}
return (
<div className={"-task-sidebar"} >
<ShareModal visible={visible} urlValue={window.location.href} onCancel={()=>setVisible(false)}/>
{
data && data.length > 0 && (data[0] && data[0].question) ?
<Popover content={content(data)} overlayClassName="helpBox" placement={"left"}>
<div className="feedback">
<i className="iconfont icon-bangzhu font-22"></i>
</div>
</Popover>
:""
}
{/* <div className="scan pr" title="">
<span className="inline erweima"><i className="iconfont icon-erweima color-white font-22 fl"></i></span>
</div>*/}
<Popover content={shareContent()} overlayClassName="helpBox shareContent" placement={"left"}>
<div className="consult">
<i className="iconfont icon-fenxiang1"></i>
</div>
</Popover>
<div className="gotop">
<Tooltip title="返回顶部" placement={"right"}>
<a><i className="iconfont icon-huidaodingbu1"></i></a>
</Tooltip>
</div>
</div>
)
}
export default SiderBar;

View File

@ -1,27 +0,0 @@
import React from 'react';
import { Modal } from 'antd';
import QRCode from 'qrcode.react';
function SiderBarShareModal({visible,urlValue,onCancel}) {
return(
<Modal
title={"分享到微信"}
visible={visible}
width="500px"
closable={true}
footer={false}
onCancel={onCancel}
>
<div style={{textAlign:"center"}}>
{urlValue &&<QRCode
value={urlValue}
size={200}
fgColor="#000000"
style={{margin:"20px"}}
/>}
<p>打开微信扫一扫,点击右上角菜单即可将网页分享至朋友圈</p>
</div>
</Modal>
)
}
export default SiderBarShareModal;

View File

@ -1,8 +1,8 @@
import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
export default ({ url , name , column , id , login })=>{
export default ({ url , name , column })=>{
const Img = styled.span`
display:flex;
${column && "flex-direction: column;text-align:center;"}
@ -19,16 +19,8 @@ export default ({ url , name , column , id , login })=>{
}
`;
return(
id?
<Link to={`/users/${login}`}>
<Img>
{ url && <img src={url} alt=""/> }
<span>{name}</span>
</Img>
</Link>
:
<Img>
{ url && <img src={url} alt=""/> }
<img src={url} alt=""/>
<span>{name}</span>
</Img>
)

View File

@ -24,38 +24,18 @@ export const AlignCenter = styled.div`{
display:flex;
align-items: center;
}`
export const AlignTop = styled.div`{
display:flex;
align-items: flex-start;
}`
export const AlignAJBottom = styled.div`{
display:flex;
justify-content: space-between;
align-items: flex-end;
}`
//
export const Box = styled.div`{
display:flex;
align-items:flex-start;
}`
export const LongWidth = styled.div`{
flex:1;
width:0;
border-radius:5px;
margin-bottom:30px;
align-item:flex-start;
}`
export const Long = styled.div`{
width:78%;
border-radius:5px;
margin-bottom:30px;
}`
export const ShortWidth = styled.div`{
width:300px;
width:72%;
border-radius:5px;
margin-bottom:30px;
}`
export const Short = styled.div`{
flex:1;
width:28%;
border-radius:5px;
margin-bottom:30px;
}`

View File

@ -36,7 +36,8 @@ function About(props, ref) {
const [ disabled, setDisabled ] = useState(false);
const [ typeFlag, setTypeFlag] = useState(false);
const AuthorLogin = props.projectDetail && props.projectDetail.author && props.projectDetail.author.login;
const AuthorLogin = props.author && props.author.login;
const CurrentLogin = props.current_user && props.current_user.login;
useEffect(()=>{
if(CurrentLogin === AuthorLogin){
@ -55,6 +56,11 @@ function About(props, ref) {
setIsSpining(false);
if(result && result.data ){
setStep(result.data.step);
// setStep(0);
// setFieldsValue({...result.data.cloud_account});
// if(result.data.cloud_account){
// setDisabled(true);
// }
}
}).catch(error=>{
setIsSpining(false);

View File

@ -45,9 +45,9 @@ function Dispose(props){
}).then(result=>{
if(result && result.data){
setList(result.data.pipelines);
setSpining(false);
}
setSpining(false);
}).catch(error=>{setSpining(false);})
}).catch(error=>{})
}
useEffect(()=>{
@ -137,17 +137,13 @@ function Dispose(props){
props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
}
//
function toparameter(){
props.history.push(`/projects/${owner}/${projectsId}/devops/params`);
}
const operate = current_user && (permission && permission !== "Reporter");
return(
<Spin spinning={spining}>
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
<div className="disposePanel">
<Head manager={ operate ? toModalManage : undefined} parameter={operate ? toparameter :undefined}/>
<Head manager={ operate ? toModalManage : undefined} />
<Div>
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
<div className="mt20 disposeList">

View File

@ -2,56 +2,16 @@ import React from 'react';
import { Table , Popconfirm } from 'antd';
import { Link } from 'react-router-dom';
// const STATUS = {
// running:"",
// failure:"",
// error:"",
// success:"",
// killed:"",
// pending:""
// }
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function renderTableStatus(status) {
switch (status) {
case "running":
return (
<span className="statusTag running">
<i className="iconfont icon-yunhangzhong"></i>运行中
</span>
);
case "failure": case 'error':
return (
<span className="statusTag failed">
<i className="iconfont icon-weitongguo"></i>未通过
</span>
);
case "success":
return (
<span className="statusTag pass">
<i className="iconfont icon-yitongguo"></i>已通过
</span>
);
case 'killed':
return (
<span className="statusTag killed">
<i className="iconfont icon-weitongguo"></i>已撤销
</span>
);
default :
return (
<span className="statusTag Preparing">
<i className="iconfont icon-zhunbeizhong"></i>准备中
</span>
);
}
const STATUS = {
running:"运行中",
failure:"未通过",
error:"未通过",
success:"已通过",
killed:"已撤销",
pending:"准备中"
}
function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
const columns = [
{
title:"流水线名称",
@ -71,9 +31,8 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
width:"15%",
ellipsis:true,
render:(value,item)=>{
let v = turnbar(item.branch);
return(
<Link to={`/projects/${owner}/${projectsId}/tree/${v}/${value}`} className="color-blue">{value}</Link>
<Link to={`/projects/${owner}/${projectsId}/branch/${item.branch}/tree/${value}`} className="color-blue">{value}</Link>
)
}
},
@ -102,10 +61,10 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
title:"最近构建状态",
dataIndex:"pipeline_status",
key:1,
width:"12%",
width:"10%",
ellipsis:true,
render:(txt)=>{
return renderTableStatus(txt)
return(STATUS[txt])
}
},
{

View File

@ -42,7 +42,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
</div>
<div className="choosenList mt20">
<span>触发条件:</span>
<Select value={branchValue} style={{width:"150px"}} dropdownClassName="chooseCon" onChange={(e)=>setBranchValue(e)}>
<Select value={branchValue} style={{width:"150px"}} onChange={(e)=>setBranchValue(e)}>
{
branchList && branchList.length>0 && branchList.map((item,key)=>{
return(
@ -51,7 +51,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
})
}
</Select>
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
<Select mode="multiple" allowClear value={eventValue} style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
{
EVENT.map((item,key)=>{
return(

View File

@ -2,18 +2,15 @@ import React from 'react';
import { AlignCenterBetween , Blueline , FlexAJ } from '../../Component/layout';
function head({manager , parameter}){
function head({manager}){
return(
<AlignCenterBetween>
<span className="font-20">工作流配置</span>
<FlexAJ>
{
parameter && <Blueline onClick={parameter}>参数管理</Blueline>
}
<a href={`https://forum.trustie.net/forums/3111/detail`} target="_blank" className="color-grey-6"><i className="iconfont icon-tishi1 font-14 mr3"></i>模板使用说明</a>
{
manager && <Blueline style={{marginLeft:"20px"}} onClick={manager}>模板管理</Blueline>
}
<a href={`https://forum.trustie.net/forums/3111/detail`} target="_blank" className="color-grey-6 ml20"><i className="iconfont icon-tishi1 font-14 mr3"></i>模板使用说明</a>
</FlexAJ>
</AlignCenterBetween>
)

View File

@ -26,11 +26,6 @@ const Mould = Loadable({
loader: () => import('./Mould'),
loading: Loading,
})
const Params = Loadable({
loader: () => import('./Manage/Params'),
loading: Loading,
})
export default ((props)=>{
return(
@ -41,11 +36,6 @@ export default ((props)=>{
(p) => (<New {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/params"
render={
(p) => (<Params {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/mould"
render={
(p) => (<Mould {...props} {...p}/>)

View File

@ -1,8 +1,9 @@
import React , { useEffect , useState } from 'react';
import React , { useEffect , useState , useRef } from 'react';
import { Banner } from '../Component/layout';
import { Link } from 'react-router-dom';
import Dispost from './Dispose';
import Structure from './Structure';
import styled from 'styled-components';
@ -10,11 +11,22 @@ const Div = styled.div`{
padding:24px 30px;
}`;
export default ((props)=>{
const [ menu , setMenu ] = useState(false);
const [ permission , setPermission ] = useState("");
const childRef = useRef();
const path = props.location.pathname;
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const projectDetail = props.projectDetail;
useEffect(()=>{
if(path === `/projects/${owner}/${projectsId}/devops/list`){
setMenu(true);
}else{
setMenu(false);
}
},[path])
useEffect(()=>{
if(projectDetail){
@ -22,13 +34,22 @@ export default ((props)=>{
}
},[projectDetail])
const updateChildState = () => {
// changeVal
if (childRef.current) {
childRef.current.changeVal();
}
}
return(
<div className="disposePanel">
<Banner>
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
{/* <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/list`}className={menu===true && "color-blue"}>构建列表</Link> */}
{/* { menu===true && <a onClick={updateChildState} style={{float:"right",fontSize:"14px",color:"#FF6E21",marginTop:"5px"}}>刷新</a>} */}
</Banner>
<Div>
{/* { menu === true && <Structure {...props} wrappedComponentRef={(form) => childRef.current = form} ref={childRef}/> } */}
<Dispost {...props}/>
</Div>
</div>

View File

@ -1,119 +0,0 @@
import React , { useEffect , useState , useRef } from 'react';
import { Banner , Blueback , FlexAJ , AlignCenter } from '../../Component/layout';
import { Input , Table , Popconfirm , Pagination } from 'antd';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import New from './ParamsNew';
import "./manage.scss";
import axios from 'axios';
import { result } from 'lodash';
const Div = styled.div`{
padding:24px 30px;
min-height:420px;
}`;
function Params(props){
const [ list ,setList ] = useState(undefined);
const [ editList ,setEditList ] = useState(undefined);
const [ visible ,setVisible ] = useState(false);
let projectsId = props.match.params.projectsId;
let owner = props.match.params.owner;
useEffect(()=>{
Init()
},[])
function Init(){
const url = `/ci/secrets.json`;
axios.get(url,{
params:{
owner,repo:projectsId
}
}).then(result=>{
if(result){
setList(result.data);
}
}).catch(error=>{})
}
const columns=[
{
title:"参数名",
dataIndex:"name",
key:1,
ellipsis:true
},
{
title:"操作",
dataIndex:"operation",
key:4,
render:(txt,item)=>{
return(
<React.Fragment>
<a className="mr10 color-grey-6" onClick={()=>editMouldFunc(item)}><i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</a>
<Popconfirm title={"确定要删除此模板?"} onConfirm={()=>deleteMouldFunc(item.id,item.name)} okText="确定" cancelText={"取消"}>
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
</Popconfirm>
</React.Fragment>
)
}
}
]
//
function editMouldFunc(item){
setEditList(item);
setVisible(true);
}
//
function deleteMouldFunc(id,name){
if(id && name){
const url = `/ci/secrets/${id}.json`;
axios.delete(url,{
params:{owner,repo:projectsId,name}
}).then(result=>{
if(result){
Init();
props.showNotification(`参数删除成功!`);
}
}).catch(error=>{})
}
}
function successFunc(values,id){
const url = `/ci/secrets.json?owner=${owner}&repo=${projectsId}`;
axios.post(url,{
...values,id
}).then(result=>{
if(result){
props.showNotification(`${id ? '参数编辑':"新增参数"}成功!`);
Init();
}
}).catch(error=>{})
}
function CancelFunc(){
setVisible(false)
}
return(
<div>
<New visble={visible} successFunc={successFunc} CancelFunc={CancelFunc} editList={editList}/>
<Banner>
<FlexAJ>
<span className="font-18">工作流 - 参数管理</span>
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9 ml20">返回</Link>
</FlexAJ>
</Banner>
<Div className="disposeList">
<div style={{textAlign:"right"}}>
<Blueback onClick={()=>setVisible(true)}>新建</Blueback>
</div>
<Table className="mt20" size="small" columns={columns} dataSource={list} rowKey={(row)=>row.id} pagination={false}></Table>
</Div>
</div>
)
}
export default Params;

View File

@ -1,73 +0,0 @@
import React , { useEffect , useState , useRef , forwardRef } from 'react';
import { Modal , Input , Form } from 'antd';
const { TextArea } = Input;
function ParamsNew({ form , visble,successFunc,CancelFunc ,editList }){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
useEffect(()=>{
if(editList && editList.id){
setFieldsValue({
name:editList.name,
data:editList.data
})
}else{
setFieldsValue({
name:undefined,
data:undefined
})
}
},[editList])
//
function onConfirmFunc(){
validateFields((error,values)=>{
if(!error){
successFunc(values,editList && editList.id);
onCancelFunc();
}
})
}
function onCancelFunc(){
setFieldsValue({
name:undefined,
data:undefined
})
CancelFunc();
}
return(
<Modal
visible={visble}
okText={"确定"}
cancelText={"取消"}
onCancel={onCancelFunc}
onOk={onConfirmFunc}
title={"新建"}
closable={false}
width="500px"
>
<Form {...layout}>
<Form.Item label="参数名称">
{getFieldDecorator("name",{
rules:[{required:true,message:"请输入参数名称"}]
})(
<Input placeholder="请输入参数名称" width="220px"/>
)}
</Form.Item>
<Form.Item label="参数值">
{getFieldDecorator("data",{
rules:[{required:true,message:"请输入参数值"}]
})(
<TextArea placeholder="请输入参数值" width="220px" autoSize={{ minRows: 4, maxRows: 4 }}/>
)}
</Form.Item>
</Form>
</Modal>
)
}
export default Form.create()(forwardRef(ParamsNew));

View File

@ -1,4 +0,0 @@
.ant-form-explain{
position: absolute;
bottom: -15px;
}

View File

@ -1,8 +1,7 @@
import React, { useState, useEffect } from "react";
import { Spin , Menu } from "antd";
import { Spin } from "antd";
import { FlexAJ, AlignCenter } from "../Component/layout";
import axios from "axios";
import CodeSSH from './ssh/Index';
export default ({
data,
@ -18,8 +17,6 @@ export default ({
const [spining, setSpining] = useState(true);
const [stage, setStage] = useState(undefined);
const [step, setStep] = useState(undefined);
const [nav, setNav] = useState("0");
useEffect(() => {
setSpining(rightSpin);
}, [rightSpin]);
@ -38,7 +35,6 @@ export default ({
: p[0];
setStep(sub);
setNav("0");
if (sub && sub.status !== "skipped") {
getStep(pre.number, sub.number);
}
@ -69,55 +65,43 @@ export default ({
}
}
return (
<React.Fragment>
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
</Menu> */}
{
nav === "0" &&
<Spin spinning={spining}>
<div className="rightMainContent">
{data && data.status !== "error" ? (
<div>
<FlexAJ className="items">
<span>{step && step.name}</span>
<AlignCenter>
{step && step.duration_time}
<i className="iconfont icon-sanjiaoxing-down"></i>
</AlignCenter>
</FlexAJ>
<div>
{coders && coders.length > 0 ? (
coders.map((item, key) => {
return (
<div className="opsDetailOut">
<span>{key + 1}</span>
<p>{item.out}</p>
</div>
);
})
) : empty ? (
<Spin spinning={spining}>
<div className="rightMainContent">
{data && data.status !== "error" ? (
<div>
<FlexAJ className="items">
<span>{step && step.name}</span>
<AlignCenter>
{step && step.duration_time}
<i className="iconfont icon-sanjiaoxing-down"></i>
</AlignCenter>
</FlexAJ>
<div>
{coders && coders.length > 0 ? (
coders.map((item, key) => {
return (
<div className="opsDetailOut">
<span>1</span>
<p>
{stage && stage.name} {step && step.name}: Skipped
</p>
<span>{key + 1}</span>
<p>{item.out}</p>
</div>
) : (
""
)}
);
})
) : empty ? (
<div className="opsDetailOut">
<span>1</span>
<p>
{stage && stage.name} {step && step.name}: Skipped
</p>
</div>
</div>
) : (
<div style={{ color: "red" }}>error:{data && data.error}</div>
)}
) : (
""
)}
</div>
</div>
</Spin>
}
{
nav === "1" && <CodeSSH />
}
</React.Fragment>
) : (
<div style={{ color: "red" }}>error:{data && data.error}</div>
)}
</div>
</Spin>
);
};

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "re
import { FlexAJ, AlignCenter , Banner } from "../Component/layout";
import { Table, Pagination, Popconfirm } from "antd";
import { truncateCommitId } from "../common/util";
import { getImageUrl } from 'educoder';
import {getUrl} from 'educoder';
import axios from "axios";
import { Link } from 'react-router-dom';
@ -58,7 +58,6 @@ function Structure(props,ref){
return {
...item,
author:item.author && item.author.name,
image_url:item.author && item.author.image_url,
message: {
branch: item.branch_target,
message: item.message,
@ -188,7 +187,7 @@ function Structure(props,ref){
<i className="iconfont icon-weitongguo"></i>已撤销
</span>
);
default:
case 'pending':
return (
<span className="statusTag Preparing">
<i className="iconfont icon-zhunbeizhong"></i>准备中
@ -245,7 +244,7 @@ function Structure(props,ref){
{meg.sha && <span className="color-orange">{meg.sha}</span>}
</div>
<AlignCenter>
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} alt="" src={`${item.image_url && getImageUrl(`/${item.image_url}`)}`} />
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} src={`${current_user && getUrl(`/images/${current_user.image_url}`)}`} />
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
{meg.message}
</div>

View File

@ -10,7 +10,6 @@
padding:60px 0px;
}
.disposePanel{
border:1px solid #eee;
.language{
display: flex;
margin-bottom: 20px;
@ -82,7 +81,48 @@
.ant-modal-close{
top:7px;
}
// 列表
.listPart{
.statusTag{
display: flex;
padding:0px 16px;
height: 32px;
line-height: 32px;
border-radius:20px;
float: left;
i{
font-size: 20px!important;
margin-right: 7px;
}
&.running{
background:#F1F8FF;
border:1px solid #5091FF;
color: #5091FF;
}
&.Preparing{
background:rgba(255,248,244,1);
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1) ;
}
&.pass{
background:#EEFDF5;
border:1px solid #28BD6C;
color:#28BD6C ;
}
&.failed{
background:#FCEEEE;
border:1px solid #F73030;
color:#F73030 ;
}
&.killed{
background:#eee;
border:1px solid #999;
color:#999 ;
}
}
}
}
// ops详情
.opsDetailPanel{
@ -194,18 +234,6 @@
&.rightSection{
width:100%;
background-color: #081930;
.devopsNav{
background-color: #111c24;
border-bottom: none;
.ant-menu-item{
color: #ccc;
padding:0px;
margin:0px 20px!important;
}
.ant-menu-item.ant-menu-item-selected{
color: #1890ff;
}
}
.rightMainContent{
padding:24px 30px;
height:100vh;
@ -391,9 +419,6 @@
}
}
}
.chooseCon.ant-select-dropdown{
z-index: 100001;
}
.choosenList{
display: flex;
@ -484,41 +509,4 @@
}
.hide{
display: none!important;
}
.statusTag{
display: flex;
padding:0px 16px;
height: 32px;
line-height: 32px;
border-radius:20px;
float: left;
i{
font-size: 20px!important;
margin-right: 7px;
}
&.running{
background:#F1F8FF;
border:1px solid #5091FF;
color: #5091FF;
}
&.Preparing{
background:rgba(255,248,244,1);
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1) ;
}
&.pass{
background:#EEFDF5;
border:1px solid #28BD6C;
color:#28BD6C ;
}
&.failed{
background:#FCEEEE;
border:1px solid #F73030;
color:#F73030 ;
}
&.killed{
background:#eee;
border:1px solid #999;
color:#999 ;
}
}

View File

@ -1,42 +0,0 @@
import React, { useState, useEffect } from "react";
import XmlPanel from "./XmlPanel";
import mediator from "./mediator";
import axios from "axios";
// const defaulturl = `http://47.111.130.18:48088`;
const defaultValue = {
host: "106.75.231.63",
port: "2021",
ws_url: "wss://pre-webssh.educoder.net/ws",
username: "root",
secret: "Dron_123123",
};
function Index() {
const [sshConfigData, setSshConfigData] = useState(undefined);
useEffect(() => {
if (!sshConfigData) {
init();
}
setTimeout(() => {
mediator.publish("create-socket", 1);
}, 300);
}, [sshConfigData]);
//
function init() {
const url = `/api/ci/pipelines/ssh_server.json`;
axios.get(url).then(result=>{
if(result && result.data){
setSshConfigData({...result.data})
}
}).catch(error=>{})
}
return (
<XmlPanel
sshConfigData={sshConfigData||{}}
sid={1}
/>
);
}
export default Index;

View File

@ -1,219 +0,0 @@
import React, { useRef, useEffect, useState } from 'react';
import { Base64 } from 'js-base64';
import { Terminal } from 'xterm';
import 'xterm/css/xterm.css';
import mediator from './mediator';
import ResizeObserver from 'resize-observer-polyfill';
function getColsAndRows(width, height, term) {
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
let h = term._core._renderService.dimensions.actualCellHeight || 18;
const rows = Math.floor(height / h);
const cols = Math.floor(width / w);
return [cols, rows];
}
function onLayout(term, el) {
const ro = new ResizeObserver(entries => {
console.log(entries);
for (let entry of entries) {
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
const [cols, rows] = getColsAndRows(
entry.target.offsetWidth,
entry.target.offsetHeight,
term,
);
console.log('cols, rows', cols, rows);
term.resize(cols, rows);
mediator.publish('ssh-xterm-resize', {
columns: cols,
rows: rows,
width: entry.target.offsetWidth,
height: entry.target.offsetHeight,
});
}
}
});
ro.observe(el);
return ro;
}
const TimeTicket = 30000;
// websockt
//
//socket term socket
//mediator id
export default ({ sshConfigData, sid }) => {
const [term, setTerm] = useState(null);
const { ws_url, password, port, secret } = sshConfigData;
const el = useRef();
const socket = useRef();
const isFirstConnected = useRef(false);
//term init
useEffect(() => {
if (el.current && ws_url) {
const term = new Terminal({ fontSize: 16, rendererType: 'dom' });
term.open(el.current);
term.onData(data => {
if (socket.current) {
if (socket.current.readyState === 1) {
socket.current.send(JSON.stringify({ tp: 'client', data: data }));
mediator.publish('on-operating-ssh'); //
} else {
//
// socket.current = null
// mediator.publish('create-socket', sid)
}
}
});
term.write('Connecting...');
setTerm(term);
const ro = onLayout(term, el.current);
return () => {
term.dispose();
ro.unobserve(el.current);
};
}
}, [ws_url, el.current]);
useEffect(() => {
if (term && ws_url) {
function createSocket() {
const socketInstance = new WebSocket(ws_url);
socket.current = socketInstance;
socketInstance.onopen = () => {
let container = term.element.parentElement;
if (container) {
let width = container.offsetWidth;
let height = container.offsetHeight;
console.log('init', {
tp: 'init',
data: {
...sshConfigData,
secret: secret,
width,
height,
rows: term.rows,
columns: term.cols,
},
});
socketInstance.send(
JSON.stringify({
tp: 'init',
data: {
...sshConfigData,
secret: secret,
width,
height,
rows: term.rows,
columns: term.cols,
},
}),
);
}
term.focus();
};
socketInstance.onerror = error => {
console.log(
'------in socket error----',
error,
socketInstance,
ws_url,
);
//
// mediator.publish('on-recreate-socket')
};
socketInstance.onmessage = event => {
if (!isFirstConnected.current) {
term.write('\r');
// term.focus()
setTimeout(() => {
// term.clear();
}, 1000);
}
isFirstConnected.current = true;
console.log('event:', event);
const data = Base64.decode(event.data.toString());
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
console.log('data:', data, w, term);
term.write(data);
};
socketInstance.onclose = evt => {
if (tid) {
clearInterval(tid);
}
term.write('\r\nconnection closed');
};
}
const tid = setInterval(() => {
if (socket.current) {
socket.current.send(JSON.stringify({ tp: 'h' }));
}
}, TimeTicket);
const unSubCreate = mediator.subscribe('create-socket', id => {
if (sid === id) {
if (socket.current && socket.current.readyState === 1) {
term.focus();
} else {
createSocket();
}
term.focus();
}
});
const unSubClose = mediator.subscribe('close-socket', id => {
if (sid === id) {
if (socket.current) {
socket.current.close();
isFirstConnected.current = false;
term.clear();
}
socket.current = null;
}
});
const unSubResize = mediator.subscribe('ssh-xterm-resize', option => {
if (socket.current && socket.current.readyState === 1) {
socket.current.send(
JSON.stringify({ tp: 'resize', data: { ...option } }),
);
}
});
const unSubAddTime = mediator.subscribe('ssh-add-connect-time', () => {
if (socket.current && socket.current.readyState === 1) {
socket.current.send(JSON.stringify({ tp: 'overtime' }));
}
});
return () => {
unSubClose();
unSubCreate();
unSubResize();
unSubAddTime();
if (socket.current) {
socket.current.close();
isFirstConnected.current = false;
}
};
}
}, [term, ws_url, port]);
return (
<div ref={el} className="xterm-panel" style={{height:"100%"}}>
{!ws_url ? <p style={{ color: '#fff' }}>正在连接命令行服务...</p> : null}
</div>
);
};

View File

@ -1,46 +0,0 @@
function Mediator(obj) {
const channels = {};
const mediator = {
subscribe: function(channel, cb) {
if (!channels[channel]) {
channels[channel] = [];
}
channels[channel].push(cb);
return this.unsubscribe.bind(null, channel, cb);
},
unsubscribe: function(channel, cb) {
let rs = channels[channel];
let index = -1;
if (rs) {
for (let i = 0; i < rs.length; i++) {
if (rs[i].name === cb.name) {
index = i;
break;
}
}
if (index >= 0) {
channels[channel].splice(index, 1);
return true;
}
}
return false;
},
publish: function(channel) {
if (!channels[channel]) {
return false;
}
const args = Array.prototype.slice.call(arguments, 1);
channels[channel].forEach(subscription => {
subscription.apply(null, args);
});
return this;
},
};
return obj ? Object.assign(obj, mediator) : mediator;
}
const mediator = new Mediator();
export default mediator;

View File

@ -1,175 +0,0 @@
import React ,{ forwardRef, useEffect, useState } from 'react';
import { Modal , Form , Input , Radio , Select } from 'antd';
import SearchUser from '../Component/SearchUser';
import './Index.scss';
import Axios from 'axios';
const { Option } = Select;
function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const [ cate , setCate ] = useState(0);
const [ value , setValue ] = useState(undefined);
const [ organizations , setOrganizations ] = useState(undefined);
useEffect(()=>{
setFieldsValue({goal:cate})
},[])
useEffect(()=>{
if(owner && repo && visible===true){
getTeam();
}
if(!visible){
setFieldsValue({
owner_name:undefined,
identifier:undefined
})
setValue(undefined)
}
},[repo,owner,visible])
function getTeam(){
const url = `/${owner}/${repo}/applied_transfer_projects/organizations.json`;
Axios.get(url).then(result=>{
if(result){
setOrganizations(result.data.organizations);
}
}).catch(error=>{})
}
//
function onOk(){
validateFields((error,values)=>{
console.log(...values);
if(!error){
const url = `/${owner}/${repo}/applied_transfer_projects.json`;
Axios.post(url,{
...values
}).then(result=>{
if(result){
onSuccess(result.data && result.data.owner);
}
}).catch(error=>{})
}
})
}
function changeType(e){
setCate(e.target.value);
setFieldsValue({
owner_name:undefined
})
}
function checkIdentifier(rule, value, callback){
if(!value){
callback();
}
if (repo && value !== repo) {
callback("请输入当前项目的标识!");
}
callback();
}
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
function getUser(id){
setValue(id);
setFieldsValue({
owner_name:id
})
}
return(
<Modal
width="620px"
visible={visible}
title="转移仓库"
onCancel={onCancel}
onOk={onOk}
okText="确认转移"
cancelText={"取消"}
centered
>
<div className="diverModal">
{
cate === 0 ?
<ul className="descUl">
<li>转移需对方确认接受转移成功后你将被移出仓库其他已有成员权限不变</li>
<li>转移成功后仓库的地址将变更至目标用户的命名空间下</li>
<li>已有成员如需继续操作仓库需更新本地仓库的remote使之指向新的地址</li>
</ul>
:
<ul className="descUl">
<li>仓库仅可以转移到您已经加入的组织中不可以转移到未加入的组织中</li>
<li>涉及到仓库改名操作请提前做好仓库备份并且在转移后对本地仓库的remote进行修改</li>
<li>转移仓库到组织后你和组织创建者/管理员同时拥有对该仓库的管理操作</li>
</ul>
}
<Form {...layout} colon={false} layout={"horizontal"}>
<Form.Item label="转移给:" style={{marginBottom:"0px"}}>
{getFieldDecorator("goal",{
rules:[]
})(
<Radio.Group onChange={changeType}>
<Radio value={0}>个人</Radio>
<Radio value={1}>组织</Radio>
</Radio.Group>
)}
</Form.Item>
{
cate === 0 &&
<Form.Item label=" ">
{getFieldDecorator("owner_name",{
rules:[{required:true,message:"请输入目标用户名"}]
})(
// <Input placeholder="" autoComplete={"off"}/>
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户" value={value}/>
)}
</Form.Item>
}
{
cate === 1 &&
<Form.Item label=" ">
{getFieldDecorator("owner_name",
{rules:[{required:true,message:"请选择目标组织"}]}
)(
<Select placeholder="请选择目标组织" getPopupContainer={trigger => trigger.parentNode}>
{
organizations && organizations.length > 0 ?
organizations.map((i,k)=>{
return(
<Option value={i.name}>{i.nickname}</Option>
)
})
:""
}
</Select>
)}
</Form.Item>
}
<Form.Item label="仓库标识:" style={{marginBottom:"0px"}}>
{getFieldDecorator("identifier",
{
rules:[
{required:true,message:"请输入仓库标识!"},
{
validator:checkIdentifier
}
]
}
)(
<Input placeholder="请输入仓库标识" autoComplete={"off"}/>
)}
</Form.Item>
<span className="color-grey-9" style={{marginLeft:"120px"}}>请输入当前项目的标识<span className="ml5 mr5 color-grey-3">{repo}</span>进行确认</span>
</Form>
</div>
</Modal>
)
}
export default Form.create()(forwardRef(DivertModal));

View File

@ -1,12 +0,0 @@
.diverModal{
.descUl{
background-color: #fffae6;
border-radius: 4px;
padding:10px 15px;
color: #efc16b;
border:1px solid #efc16b;
}
.ant-form-item-required::before{
content: "";
}
}

View File

@ -10,12 +10,4 @@ export const getTag = async (id,owner)=>{
// hooks-web
export const getHooks = async (id,params)=>{
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
}
//
export const getSubEntries = async (owner,projectsId,params)=>{
return (await axios.get(`/${owner}/${projectsId}/sub_entries.json`,{params})).data;
}
//
export const getUser = async (login)=>{
return (await axios.get(`/users/${login}/hovercard.json`)).data;
}

View File

@ -1,84 +0,0 @@
import React, { useState , forwardRef, useEffect } from 'react';
import { Form , Modal , Input , Radio } from 'antd';
import Axios from 'axios';
export default Form.create()(
forwardRef((props)=>{
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
const [ visible , setVisible ] = useState(false);
useEffect(()=>{
if(!visible){
setFieldsValue({
code:undefined,
role:"developer"
})
}
},[visible])
function onOk() {
validateFields((error,values)=>{
if(!error){
const url = `/applied_projects.json`;
Axios.post(url,{
applied_project:{
...values
}
}).then(result=>{
if(result && result.data){
setVisible(false);
props.showNotification("申请加入项目成功,等待审核!");
}
}).catch(error=>{})
}
})
}
function checkValue(rule, value, callback){
if(!value){
callback();
}
if(value.length < 6 || value.length > 6){
callback("请输入6位数的邀请码");
}
callback();
}
return(
<React.Fragment>
<Modal
title="加入项目"
width="480px"
visible={visible}
centered={true}
onOk={onOk}
onCancel={()=>setVisible(false)}
>
<Form layout={'inline'} className="inviteForm">
<Form.Item label="项目邀请码">
{getFieldDecorator("code",{
rules:[
{required:true,message:"请输入6位项目邀请码"},
{validator:checkValue}
]
})(
<Input placeholder="请输入6位项目邀请码" autoComplete={"off"} maxLength="6" style={{width:"300px"}}/>
)}
</Form.Item>
<Form.Item label="选择角色">
{getFieldDecorator("role",{
rules:[{required:true,message:"请选择角色"}]
})(
<Radio.Group defaultValue={"developer"}>
<Radio value="manager">管理员</Radio>
<Radio value="developer">开发者</Radio>
<Radio value="reporter">报告者</Radio>
</Radio.Group>
)}
</Form.Item>
</Form>
</Modal>
<a onClick={()=>setVisible(true)}>加入项目</a>
</React.Fragment>
)
})
)

View File

@ -1,66 +0,0 @@
import React, { useEffect , useState } from 'react';
import './header.scss';
function Footer(){
const [ value , setValue ] = useState(undefined);
useEffect(()=>{
try {
var chromesettingArray = JSON.parse(localStorage.getItem('chromesetting'));
setValue(chromesettingArray.footer);
} catch (e) {
}
},[])
function showhtml(htmlString){
var html = {__html:htmlString};
return <div dangerouslySetInnerHTML={html}></div> ;
}
return(
<div>
<div style={{height:"497px"}}></div>
<div className="newFooter edu-txt-center">
{value && showhtml(value)}
{/* <div className="footerInfos">
<ul>
<li>社区</li>
<li><a href={`/`} target="_blank">网站首页</a></li>
<li><a href={`https://www.trustie.net/agreement`} target="_blank">服务协议</a></li>
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
<li><a href={`https://forum.trustie.net/`} target="_blank">问吧交流</a></li>
<li><a href={`https://www.trustie.net/cooperation`} target="_blank">合作伙伴</a></li>
</ul>
<ul>
<li>支持与服务</li>
<li><a href={`https://forgeplus.trustie.net/docs/api`} target="_blank">API文档</a></li>
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
<li><a href={`https://git-scm.com`} target="_blank">Git常用命令</a></li>
<li><a href={`https://forum.trustie.net/forums/3080/detail`} target="_blank">DevOps使用文档</a></li>
<li><a href={`https://forgeplus.trustie.net/projects/jasder/forgeplus/tree/master/CHANGELOG.md`} target="_blank">日志更新</a></li>
</ul>
<ul>
<li>合作伙伴</li>
<li><a href={`http://www.sei.pku.edu.cn`} target="_blank">北京大学</a></li>
<li><a href={`http://scse.buaa.edu.cn`} target="_blank">北京航空航天大学</a></li>
<li><a href={`https://www.nju.edu.cn`} target="_blank">南京大学</a></li>
<li><a href={`https://www.xtu.edu.cn`} target="_blank">湘潭大学</a></li>
<li><a href={`http://www.iscas.ac.cn`} target="_blank">ISCAS</a></li>
<li><a href={`https://www.ucloud.cn`} target="_blank">UCloud优刻得</a></li>
<li><a href={`http://www.inforbus.com`} target="_blank">中创软件</a></li>
<li><a href={`https://www.inspur.com`} target="_blank">浪潮集团</a></li>
<li><a href={`http://www.copu.org.cn`} target="_blank">中国开源软件推进联盟</a></li>
<li><a href={`https://www.sjtu.edu.cn`} target="_blank">上海交通大学</a></li>
</ul>
<ul>
<li>合作伙伴</li>
<li><span>热线</span></li>
<li><span>QQ群1071514693</span></li>
</ul>
</div>
<p className="footerCopy">© Copyright 2007~2021 国防科技大学Trustie团队 & IntelliDE <a href="https://beian.miit.gov.cn">湘ICP备 17009477</a></p> */}
</div>
</div>
)
}
export default Footer;

View File

@ -1,456 +0,0 @@
import React, { Component } from 'react';
import AccountProfile from "../../modules/user/AccountProfile";
import { getImageUrl } from 'educoder'
import axios from 'axios';
import { Input , notification , Dropdown , Menu } from 'antd';
import { Link } from 'react-router-dom';
import LoginDialog from '../../modules/login/LoginDialog';
import HeadSearch from '../Component/HeadSearch';
import AddProjectModal from './AddProjectModal';
import '../../modules/tpm/TPMIndex.css';
import './header.scss';
const $ = window.$
// TODO 这部分脚本从公共脚本中直接调用
const { Search } = Input;
let old_url;
window._header_componentHandler = null;
// 非trustie链接则新开页跳转
const str = ['www.trustie.net','forgeplus.trustie.net','forum.trustie.net','testforgeplus.trustie.net']
class NewHeader extends Component {
constructor(props) {
super(props)
this.state = {
Addcoursestypes: false,
tojoinitemtype: false,
tojoinclasstitle: undefined,
rolearr: ["", ""],
Checkboxteacherchecked: false,
Checkboxstudentchecked: false,
Checkboxteachingchecked: false,
Checkboxteachertype: false,
Checkboxteachingtype: false,
code_notice: false,
RadioGroupvalue: undefined,
submitapplications: false,
isRender: false,
showTrial: false,
setevaluatinghides: false,
occupation: 0,
mydisplay: false,
headtypesonClickbool: false,
headtypess: "/",
settings: null,
visiblemyss: false,
openSearch:false,
}
}
componentDidMount() {
this.geturlsdata();
window._header_componentHandler = this;
//下拉框的显示隐藏
var hoverTimeout;
var hoveredPanel;
$(".edu-menu-panel").hover(function () {
if (hoverTimeout) { // 一次只显示一个panel
if (hoveredPanel && hoveredPanel !== this) {
$(hoveredPanel).find(".edu-menu-list").hide()
}
clearTimeout(hoverTimeout);
hoverTimeout = null;
}
hoveredPanel = this;
$(this).find(".edu-menu-list").show();
}, function () {
var that = this;
// 延迟hide
hoverTimeout = setTimeout(function () {
$(that).find(".edu-menu-list").hide();
}, 800)
});
//获取游览器地址
try {
window.sessionStorage.setItem("yslgeturls", JSON.stringify(window.location.href))
} catch (e) {}
}
openNotification = (messge) => {
notification.open({
message: "提示",
description:
messge,
});
};
componentWillReceiveProps(newProps, oldProps) {
this.setState({
user: newProps.user
})
if (newProps.Headertop !== undefined) {
old_url = newProps.Headertop.old_url
}
}
educoderlogin = () => {
//登录账号
this.setState({
isRender: true
})
}
educoderloginysl = () => {
//退出账号
var url = `/accounts/logout.json`;
axios.get((url)).then((result) => {
if (result !== undefined) {
window.location.href = "/";
}
}).catch((error) => {
console.log(error);
})
}
hideAddcoursestypes = () => {
this.setState({
Addcoursestypes: false
})
};
HideAddcoursestypess = (i) => {
console.log("调用了");
this.setState({
Addcoursestypes: false,
mydisplay: true,
occupation: i,
})
};
ModalCancelsy = () => {
this.setState({
mydisplay: false,
})
};
// 关闭
cancelModulationModels = () => {
this.setState({ isRenders: false })
}
setevaluatinghides = () => {
this.setState({
setevaluatinghides: true
})
}
//修改登录方法
Modifyloginvalue = () => {
this.setState({
isRender: false,
})
}
hideAccountProfile = () => {
this.setState({
AccountProfiletype: false
})
};
headtypesonClick = (url, bool) => {
this.setState({
headtypess: url,
headtypesonClickbool: bool,
})
}
//获取数据为空的时候
gettablogourlnull = () => {
this.setState({
settings: undefined
});
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
};
//获取数据的时候
gettablogourldata = (response) => {
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/' + response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
handleVisibleChanges = (boll) => {
this.setState({
visiblemyss: boll,
})
}
geturlsdata = () => {
let url = "/setting.json";
axios.get(url).then((response) => {
if (response && response.data) {
this.setState({ settings: response.data.setting });
localStorage.setItem('chromesetting', JSON.stringify(response.data.setting));
localStorage.setItem('chromesettingresponse', JSON.stringify(response));
} else {
this.gettablogourlnull();
}
}).catch((error) => {
this.gettablogourlnull();
});
}
matchpaths = (url) => {
const { match } = this.props;
if(url){
if (match.path.indexOf(url) > -1) {
return true
}else {
return false
}
}
}
addMenu=(list)=>{
return(
list && list.length >0 &&
<div className="dropdownFlex">
<Menu>
{
list.map((item,key)=>{
return(
(item.name !=="加入课堂" && item.name !=="加入开发项目") && <Menu.Item key={item.name+key}><a href={item.url}>{item.name}</a></Menu.Item>
)
})
}
<Menu.Item><AddProjectModal showNotification={this.props.showNotification}/></Menu.Item>
</Menu>
</div>
)
}
renderMenu=(personal)=>{
const { current_user } = this.props;
return(
<Menu className="currentMenu">
<Menu.Item>
<span title={current_user && current_user.username}>{current_user && current_user.username}</span>
</Menu.Item>
{
personal && personal.length > 0 && personal.map((item,key)=>{
return(
<li key={key}><a href={item.url} target="_blank">{item.name}</a></li>
)
})
}
<li><Link to={`/settings/SSH`}>设置</Link></li>
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
</Menu>
)
}
render() {
const { match} = this.props;
let current_user = this.props.user;
let {
AccountProfiletype,
user,
isRender,
headtypesonClickbool,
headtypess,
settings,
} = this.state;
/*用户名称 用户头像url*/
let activeIndex = false;
let activeForums = false;
let activeShixuns = false;
let activePaths = false;
let coursestype = false;
let activePackages = false;
let activeMoopCases = false;
let activeCompetitions = false;
if (match.path === '/forums') {
activeForums = true;
} else if (match.path.startsWith('/shixuns')) {
activeShixuns = true;
} else if (match.path.startsWith('/paths')) {
activePaths = true;
} else if (match.path.startsWith('/courses')) {
coursestype = true;
} else if (match.path.startsWith('/crowdsourcing')) {
activePackages = true;
} else if (match.path.startsWith('/moop_cases')) {
activeMoopCases = true;
} else if (match.path.startsWith('/competitions')) {
activeCompetitions = true;
} else {
activeIndex = true;
}
let headtypes = '/';
if (settings) {
if (settings.navbar) {
if (settings.navbar.length > 0) {
if (match.path === '/') {
if (headtypesonClickbool === false) {
headtypes = undefined;
} else {
headtypes = headtypess;
}
} else {
for (var i = 0; i < settings.navbar.length; i++) {
if (match.path === settings.navbar[i].link) {
headtypes = settings.navbar[i].link;
break;
}
}
}
}
}
}
let shixuntype = false;
let pathstype = false;
let coursestypes = false;
if (this.props && this.props.mygetHelmetapi != null) {
let shixun = "/shixuns";
let paths = "/paths";
let courses = "/courses";
this.props.mygetHelmetapi && this.props.mygetHelmetapi.navbar && this.props.mygetHelmetapi.navbar.map((item, key) => {
var reg = RegExp(item.link);
if (shixun.match(reg)) {
if (item.hidden === true) {
shixuntype = true
}
}
if (paths.match(reg)) {
if (item.hidden === true) {
pathstype = true
}
}
if (courses.match(reg)) {
if (item.hidden === true) {
coursestypes = true
}
}
})
}
// let search_url = settings && settings.common && settings.common.search;
let notice_url = settings && settings.common && settings.common.notice;
return (
<div className="newHeaders" id="nHeader">
<div className="headerContent">
{isRender === true ?
<LoginDialog
{...this.props}
{...this.state}
Modifyloginvalue={() => this.Modifyloginvalue()}
/> : ""}
{AccountProfiletype === true ?
<AccountProfile
hideAccountProfile={() => this.hideAccountProfile()}
{...this.props}
{...this.state}
/> : ""}
{
settings && settings.nav_logo_url ?
<a href={settings && settings.new_course.default_url} className={"fl mr50"} style={{minWidth:"45px"}}>
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
</a>
:
""
}
<div className="head-nav pr" id={"head-navpre1"}>
{
settings && settings.navbar && settings.navbar.length > 0 ?
<ul id="header-nav">
{
settings.navbar && settings.navbar.map((item, key) => {
var new_link = item.link;
var user_login = this.props.user && this.props.user.login;
var is_hidden = item.hidden
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
if (user_login) {
if (new_link.indexOf("courses") > -1) {
new_link = new_link.replace(/courses/g, "users/" + user_login + "/courses")
} else if (new_link.indexOf("contests") > -1) {
new_link = new_link.replace(/contests/g, "users/" + user_login + "/contests")
}
} else {
is_hidden = true
}
}
if (user_login && (new_link && new_link.indexOf("homes") > -1)) {
new_link = new_link.replace(/homes/g, "users/" + user_login + "/user_activities")
}
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
var wl = waiLian && waiLian.length>0;
return (
<li key={key} onClick={() => this.headtypesonClick(item.link, true)} className={`${this.matchpaths(item.link) === true ? 'pr active' : 'pr'}`} style={!is_hidden ? { display: 'flex' } : { display: 'none' }}>
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
</li>
)
})
}
</ul>
: ""
}
</div>
<div className="head-right">
{/* {search_url ? this.SearchInput(openSearch,search_url):""} */}
<HeadSearch {...this.props}/>
{
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
<i className="iconfont icon-tianjiafangda color-grey-6 ml30"></i>
</Dropdown>:""
}
{this.props.user && this.props.user.login && notice_url ?
<div className="ml30 edu-menu-panel">
{user && user.login &&
<a href={`${notice_url}`} style={{ position: 'relative' }}>
<i className="iconfont icon-xiaoxilingdang color-grey-6"></i>
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
</span>
</a>
}
</div>:""
}
</div>
{!user || (user && !user.login) ?
<span className="font-15 ml30">
<a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a>
{
settings && settings.common && settings.common.register &&
<span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.common.register}`} target="_blank"></a></span>
}
</span>
:
<Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}>
<a href={`/users/${this.props.current_user && this.props.current_user.login}`}>
<img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img>
</a>
</Dropdown>
}
</div>
</div>
);
}
}
export default NewHeader;

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