Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

290 changed files with 9727 additions and 16682 deletions

1190
.idea/workspace.xml Normal file

File diff suppressed because it is too large Load Diff

View File

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

124
LICENSE
View File

@ -1,124 +0,0 @@
木兰宽松许可证, 第2版
2020年1月 http://license.coscl.org.cn/MulanPSL2
您对“软件”的复制、使用、修改及分发受木兰宽松许可证第2版“本许可证”的如下条款的约束
0. 定义
“软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
“贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
“贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
“法人实体” 是指提交贡献的机构及其“关联实体”。
“关联实体” 是指对“本许可证”下的行为方而言控制、受控制或与其共同受控制的机构此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
1. 授予版权许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
2. 授予专利许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
3. 无商标许可
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可但您为满足第4条规定的声明义务而必须使用除外。
4. 分发限制
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
5. 免责声明与责任限制
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
6. 语言
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
条款结束
如何将木兰宽松许可证第2版应用到您的软件
如果您希望将木兰宽松许可证第2版应用到您的新软件为了方便接收者查阅建议您完成如下三步
1 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
2 请您在软件包的一级目录下创建以“LICENSE”为名的文件将整个许可证文本放入该文件中
3 请将如下声明文本放入每个源文件的头部注释中。
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
Mulan Permissive Software LicenseVersion 2
Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2)
January 2020 http://license.coscl.org.cn/MulanPSL2
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
0. Definition
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
Contribution means the copyrightable work licensed by a particular Contributor under this License.
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
Legal Entity means the entity making a Contribution and all its Affiliates.
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, control means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
1. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
2. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
3. No Trademark License
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4.
4. Distribution Restriction
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
5. Disclaimer of Warranty and Limitation of Liability
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW ITS CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
6. Language
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
END OF THE TERMS AND CONDITIONS
How to Apply the Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2) to Your Software
To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
Create a file named "LICENSE" which contains the whole context of this License in the first directory of your software package;
Attach the statement to the appropriate annotated syntax at the beginning of each source file.
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.

View File

@ -19,8 +19,7 @@ const getClientEnvironment = require("./env");
let publicPath = "/react/build/"; let publicPath = "/react/build/";
const publicUrl = publicPath.slice(0, -1); const publicUrl = publicPath.slice(0, -1);
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false"; const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
const shouldUseSourceMap = process.env.NODE_ENV !== "production";
const env = getClientEnvironment(publicPath); const env = getClientEnvironment(publicPath);
// This is the production configuration. // This is the production configuration.
@ -55,8 +54,7 @@ module.exports = {
}, },
bail: true, bail: true,
mode: "production", mode: "production",
// devtool: false, //测试版 devtool: false, //测试版
devtool: shouldUseSourceMap?'source-map':false,
entry: [require.resolve("./polyfills"), paths.appIndexJs], entry: [require.resolve("./polyfills"), paths.appIndexJs],
output: { output: {
path: paths.appBuild, path: paths.appBuild,

9823
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,11 +22,10 @@
"case-sensitive-paths-webpack-plugin": "2.1.1", "case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3", "chalk": "1.1.3",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"clipboard": "^2.0.8", "clipboard": "^2.0.6",
"code-prettify": "^0.1.0", "code-prettify": "^0.1.0",
"codemirror": "^5.53.0", "codemirror": "^5.53.0",
"connected-react-router": "4.4.1", "connected-react-router": "4.4.1",
"cross-env": "^7.0.3",
"css-loader": "^3.5.2", "css-loader": "^3.5.2",
"dompurify": "^2.0.15", "dompurify": "^2.0.15",
"dotenv": "4.0.0", "dotenv": "4.0.0",
@ -104,7 +103,6 @@
"redux-thunk": "2.3.0", "redux-thunk": "2.3.0",
"rsuite": "^4.3.4", "rsuite": "^4.3.4",
"sass-loader": "7.3.1", "sass-loader": "7.3.1",
"save-dev": "0.0.1-security",
"scroll-into-view": "^1.14.2", "scroll-into-view": "^1.14.2",
"showdown": "^1.9.1", "showdown": "^1.9.1",
"showdown-katex": "^0.8.0", "showdown-katex": "^0.8.0",
@ -124,8 +122,8 @@
}, },
"scripts": { "scripts": {
"start": "node --max_old_space_size=15360 scripts/start.js", "start": "node --max_old_space_size=15360 scripts/start.js",
"build": "cross-env NODE_ENV=production node --max_old_space_size=15360 scripts/build.js", "build": "NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
"test-build": "cross-env NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js", "test-build": "NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
"pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js", "pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js",
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json", "gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
"ana": "webpack-bundle-analyzer ./stats.json", "ana": "webpack-bundle-analyzer ./stats.json",
@ -187,7 +185,7 @@
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
}, },
"proxy": "http://localhost:3001", "proxy": "http://localhost:3000",
"port": "3007", "port": "3007",
"devDependencies": { "devDependencies": {
"@babel/runtime": "7.0.0-beta.51", "@babel/runtime": "7.0.0-beta.51",

View File

@ -114,6 +114,14 @@ a:visited {
color: #898989; color: #898989;
} }
a:hover {
color: #FF7500;
}
a:hover.fa {
color: #FF7500;
}
input, input,
textarea, textarea,
select { select {

View File

@ -97,6 +97,10 @@ a:visited {
color: #05101a; color: #05101a;
} }
a:hover {
color: #459be5;
}
ol, ol,
ul, ul,
li { li {

View File

@ -1,4 +1,3 @@
@charset "utf-8";
/* 头部 */ /* 头部 */
.header { .header {
width: 100%; width: 100%;
@ -1272,7 +1271,7 @@ html body {
font-size: 14px; font-size: 14px;
line-height: 2.0; line-height: 2.0;
background: #fafafa; background: #fafafa;
font-family: "Microsoft YaHei", "SimSun"; font-family: "微软雅黑", "宋体";
color: #05101a; color: #05101a;
height: 100%; height: 100%;
position: relative; position: relative;
@ -1308,7 +1307,6 @@ td,
span { span {
margin: 0; margin: 0;
padding: 0; padding: 0;
margin-bottom: 0px!important;
} }
table, table,
@ -1365,6 +1363,10 @@ a:visited {
color: #05101a; color: #05101a;
} }
a:hover {
color: #459be5;
}
ol, ol,
ul, ul,
li { li {
@ -1471,7 +1473,7 @@ a.edu-txt-w80,
/*隐藏*/ /*隐藏*/
.none { .none {
display: none!important; display: none
} }
.block { .block {
@ -1520,15 +1522,7 @@ a.edu-txt-w80,
.font-16 { .font-16 {
font-size: 16px !important; font-size: 16px !important;
} }
.weight400{
font-weight: 400;
}
.weight500{
font-weight: 500;
}
.weight{
font-weight: bold;
}
.font-17 { .font-17 {
font-size: 17px !important; font-size: 17px !important;
} }
@ -1548,9 +1542,6 @@ a.edu-txt-w80,
.font-25 { .font-25 {
font-size: 25px !important; font-size: 25px !important;
} }
.font-26 {
font-size: 26px !important;
}
.font-24 { .font-24 {
font-size: 24px !important; font-size: 24px !important;
@ -1572,9 +1563,6 @@ a.edu-txt-w80,
font-size: 36px !important; font-size: 36px !important;
} }
.font-40 {
font-size: 40px !important;
}
.font-50 { .font-50 {
font-size: 50px !important; font-size: 50px !important;
} }
@ -1760,14 +1748,6 @@ a.decoration {
margin-bottom: 10px; margin-bottom: 10px;
} }
.mb12 {
margin-bottom: 12px;
}
.mb13 {
margin-bottom: 13px;
}
.mb14 { .mb14 {
margin-bottom: 14px; margin-bottom: 14px;
} }
@ -2456,11 +2436,7 @@ a.hoverLine:hover{
.color-grey-9 { .color-grey-9 {
color: #999 !important; color: #999999 !important;
}
a:hover{
color: #466AFF !important;
} }
.color-grey-98 { .color-grey-98 {
@ -2495,23 +2471,33 @@ a:hover{
a.color-grey-name:hover, a.color-grey-name:hover,
a.color-dark:hover, a.color-dark:hover,
a.color-grey-6:hover, a.color-grey-6:hover,
a.color-grey-3:hover,a.color-ooo:hover { a.color-grey-3:hover {
color: #2A61FF !important; color: #4cacff !important;
}
a.color-grey-9:hover,
a.color-grey-8:hover,
a.color-grey-c:hover {
color: #111C24 !important;
} }
/*蓝色*/ /*蓝色*/
.color-blue { .color-blue {
color: #2A61FF !important; color: #4CACFF !important;
}
.color-blue-file {
color: #4598FA!important;
} }
/* 绿色 */ /* 绿色 */
.color-green-file{
color: #28BD6C;
}
/*主*/ /*主*/
.color-blue_4C { .color-blue_4C {
color: #4CACFF !important; color: #4CACFF !important;
} }
a.color-blue:hover,
a.color-blue_4C:hover {
color: #459BE6 !important;
}
/*橙色*/ /*橙色*/
.color-orange { .color-orange {

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 2340181 */ font-family: "iconfont"; /* Project id 2340181 */
src: url('iconfont.woff2?t=1634881729644') format('woff2'), src: url('iconfont.woff2?t=1627870211301') format('woff2'),
url('iconfont.woff?t=1634881729644') format('woff'), url('iconfont.woff?t=1627870211301') format('woff'),
url('iconfont.ttf?t=1634881729644') format('truetype'); url('iconfont.ttf?t=1627870211301') format('truetype');
} }
.iconfont { .iconfont {
@ -13,322 +13,6 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-wenjian7:before {
content: "\e8e0";
}
.icon-xiangyoujiantou:before {
content: "\e8de";
}
.icon-xiangzuojiantou:before {
content: "\e8df";
}
.icon-a-liulanicon2x:before {
content: "\e8dd";
}
.icon-wenjianicon:before {
content: "\e8dc";
}
.icon-a-yuanquan2x:before {
content: "\e8db";
}
.icon-xiangmubiaoqian:before {
content: "\e8da";
}
.icon-icon:before {
content: "\e8ce";
}
.icon-tar:before {
content: "\e8cf";
}
.icon-a-fuzhi2:before {
content: "\e8d0";
}
.icon-fujian1:before {
content: "\e8d1";
}
.icon-a-bianji1:before {
content: "\e8d2";
}
.icon-banbenicon:before {
content: "\e8d3";
}
.icon-shanchuicon2:before {
content: "\e8d4";
}
.icon-a-lajitong_icon3x:before {
content: "\e8d5";
}
.icon-xialaanniu2:before {
content: "\e8d6";
}
.icon-xiazai-icon:before {
content: "\e8d7";
}
.icon-master_icon1:before {
content: "\e8d8";
}
.icon-shangchuanicon:before {
content: "\e8d9";
}
.icon-gerenziliao1:before {
content: "\e8c7";
}
.icon-lichengbeiicon:before {
content: "\e885";
}
.icon-cangkushezhiicon:before {
content: "\e889";
}
.icon-dongtaiicon:before {
content: "\e88a";
}
.icon-gongzuoliuicon:before {
content: "\e88b";
}
.icon-yixiuicon1:before {
content: "\e89b";
}
.icon-a-wikiicon1:before {
content: "\e8c6";
}
.icon-daimakuicon1:before {
content: "\e8c5";
}
.icon-wodetongzhi:before {
content: "\e8c8";
}
.icon-tongzhiguanli:before {
content: "\e8c9";
}
.icon-xuanzhong3:before {
content: "\e8ca";
}
.icon-xitongtongzhiicon:before {
content: "\e8cb";
}
.icon-xiaoxi2:before {
content: "\e8cc";
}
.icon-sshmiyue:before {
content: "\e8cd";
}
.icon-gerenziliao:before {
content: "\e8c4";
}
.icon-xinshouzhiyin:before {
content: "\e8e4";
}
.icon-xinjianxiangmu:before {
content: "\e8e6";
}
.icon-jiaruketang1:before {
content: "\e8e9";
}
.icon-xiangmugonggao:before {
content: "\e8c2";
}
.icon-chengguo:before {
content: "\e8c3";
}
.icon-chengjiaogonggao:before {
content: "\e8c0";
}
.icon-jishuzichan:before {
content: "\e8c1";
}
.icon-feibiaogonggao:before {
content: "\e8bc";
}
.icon-zhongbiaogonggao:before {
content: "\e8bd";
}
.icon-gengzhenggonggao:before {
content: "\e8be";
}
.icon-zhaobiaogonggao:before {
content: "\e8bf";
}
.icon-wenjian6:before {
content: "\e8ba";
}
.icon-wenjianjia4:before {
content: "\e8bb";
}
.icon-quxiaoguanzhu:before {
content: "\e89a";
}
.icon-dianzan_icon:before {
content: "\e8a2";
}
.icon-wenjian5:before {
content: "\e896";
}
.icon-wenjianjia3:before {
content: "\e8a9";
}
.icon-fuzhiicon:before {
content: "\e886";
}
.icon-zhuye-fill:before {
content: "\e876";
}
.icon-daimakuicon:before {
content: "\e884";
}
.icon-xinjian2:before {
content: "\e8b0";
}
.icon-xieyiicon:before {
content: "\e870";
}
.icon-neicunicon:before {
content: "\e891";
}
.icon-zishuwenjian_icon:before {
content: "\e8a6";
}
.icon-biaoqianicon:before {
content: "\e882";
}
.icon-a-bianji:before {
content: "\e883";
}
.icon-lianjieicon:before {
content: "\e887";
}
.icon-hebingqingqiuicon:before {
content: "\e888";
}
.icon-morendianzan_icon:before {
content: "\e88e";
}
.icon-muluicon:before {
content: "\e894";
}
.icon-a-shezhi:before {
content: "\e899";
}
.icon-tijiaoicon:before {
content: "\e89e";
}
.icon-morenguanzhu_ICON:before {
content: "\e89f";
}
.icon-xialaanniu1:before {
content: "\e8a4";
}
.icon-zuohuaicon:before {
content: "\e8b5";
}
.icon-master_icon:before {
content: "\e8b6";
}
.icon-morenfuke_icon:before {
content: "\e8b7";
}
.icon-a-wikiicon:before {
content: "\e8b8";
}
.icon-yixiuicon:before {
content: "\e8b9";
}
.icon-suofang:before {
content: "\e87f";
}
.icon-fangdaicon:before {
content: "\e881";
}
.icon-sousuo_icon1:before {
content: "\e873";
}
.icon-huanying_icon:before {
content: "\e878";
}
.icon-wenjianjia2:before {
content: "\e879";
}
.icon-shanchuicon1:before {
content: "\e87a";
}
.icon-qingqiuicon:before { .icon-qingqiuicon:before {
content: "\e871"; content: "\e871";
} }
@ -365,10 +49,22 @@
content: "\e898"; content: "\e898";
} }
.icon-xialaanniu_icon:before {
content: "\e89a";
}
.icon-weixuanzhongqingqiuicon:before {
content: "\e89b";
}
.icon-xiezuozheguanliicon:before { .icon-xiezuozheguanliicon:before {
content: "\e8a1"; content: "\e8a1";
} }
.icon-xuanzhongxiangyingicon:before {
content: "\e8a2";
}
.icon-xuanzhongfenzhiicon:before { .icon-xuanzhongfenzhiicon:before {
content: "\e8a3"; content: "\e8a3";
} }
@ -385,6 +81,18 @@
content: "\e8af"; content: "\e8af";
} }
.icon-xinzengmulu_xuantingicon:before {
content: "\e884";
}
.icon-xinzengyemian_morenicon:before {
content: "\e885";
}
.icon-zhankai_morenicon:before {
content: "\e889";
}
.icon-shanchu_tc_icon:before { .icon-shanchu_tc_icon:before {
content: "\e88c"; content: "\e88c";
} }
@ -393,14 +101,26 @@
content: "\e88d"; content: "\e88d";
} }
.icon-xinzengyemian_shubiaodianjiicon:before {
content: "\e88e";
}
.icon-daorumoban_icon:before { .icon-daorumoban_icon:before {
content: "\e86f"; content: "\e86f";
} }
.icon-daochu_xuanfu:before {
content: "\e870";
}
.icon-cuowu:before { .icon-cuowu:before {
content: "\e872"; content: "\e872";
} }
.icon-chenggong1:before {
content: "\e873";
}
.icon-gengduo_icon:before { .icon-gengduo_icon:before {
content: "\e874"; content: "\e874";
} }
@ -409,10 +129,26 @@
content: "\e875"; content: "\e875";
} }
.icon-fuzhi_icon:before {
content: "\e876";
}
.icon-shanchuicon:before { .icon-shanchuicon:before {
content: "\e877"; content: "\e877";
} }
.icon-a-lajitong_icon3x:before {
content: "\e878";
}
.icon-shouqi_morenicon:before {
content: "\e879";
}
.icon-huanying_icon:before {
content: "\e87a";
}
.icon-sousuo_shanchuicon:before { .icon-sousuo_shanchuicon:before {
content: "\e87b"; content: "\e87b";
} }
@ -425,10 +161,22 @@
content: "\e87e"; content: "\e87e";
} }
.icon-wenjianjia_icon:before {
content: "\e87f";
}
.icon-xialaanniu:before { .icon-xialaanniu:before {
content: "\e880"; content: "\e880";
} }
.icon-xinzengmulu_morenicon:before {
content: "\e882";
}
.icon-xinzengmulu_shubiaodianjiicon:before {
content: "\e883";
}
.icon-erciqueren_icon:before { .icon-erciqueren_icon:before {
content: "\e867"; content: "\e867";
} }

File diff suppressed because one or more lines are too long

View File

@ -5,559 +5,6 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "24656750",
"name": "文件",
"font_class": "wenjian7",
"unicode": "e8e0",
"unicode_decimal": 59616
},
{
"icon_id": "630094",
"name": "向右箭头",
"font_class": "xiangyoujiantou",
"unicode": "e8de",
"unicode_decimal": 59614
},
{
"icon_id": "630095",
"name": "向左箭头",
"font_class": "xiangzuojiantou",
"unicode": "e8df",
"unicode_decimal": 59615
},
{
"icon_id": "24600282",
"name": "浏览icon@2x",
"font_class": "a-liulanicon2x",
"unicode": "e8dd",
"unicode_decimal": 59613
},
{
"icon_id": "24567893",
"name": "文件icon",
"font_class": "wenjianicon",
"unicode": "e8dc",
"unicode_decimal": 59612
},
{
"icon_id": "24527422",
"name": "圆圈@2x",
"font_class": "a-yuanquan2x",
"unicode": "e8db",
"unicode_decimal": 59611
},
{
"icon_id": "24378423",
"name": "项目标签",
"font_class": "xiangmubiaoqian",
"unicode": "e8da",
"unicode_decimal": 59610
},
{
"icon_id": "24368060",
"name": "icon",
"font_class": "icon",
"unicode": "e8ce",
"unicode_decimal": 59598
},
{
"icon_id": "24368061",
"name": "tar",
"font_class": "tar",
"unicode": "e8cf",
"unicode_decimal": 59599
},
{
"icon_id": "24289113",
"name": "复制 (2)",
"font_class": "a-fuzhi2",
"unicode": "e8d0",
"unicode_decimal": 59600
},
{
"icon_id": "24289114",
"name": "附件",
"font_class": "fujian1",
"unicode": "e8d1",
"unicode_decimal": 59601
},
{
"icon_id": "24289115",
"name": "编 辑",
"font_class": "a-bianji1",
"unicode": "e8d2",
"unicode_decimal": 59602
},
{
"icon_id": "24289116",
"name": "版本icon",
"font_class": "banbenicon",
"unicode": "e8d3",
"unicode_decimal": 59603
},
{
"icon_id": "24289117",
"name": "删除icon",
"font_class": "shanchuicon2",
"unicode": "e8d4",
"unicode_decimal": 59604
},
{
"icon_id": "24289118",
"name": "垃圾桶_icon@3x",
"font_class": "a-lajitong_icon3x",
"unicode": "e8d5",
"unicode_decimal": 59605
},
{
"icon_id": "24289119",
"name": "下拉按钮",
"font_class": "xialaanniu2",
"unicode": "e8d6",
"unicode_decimal": 59606
},
{
"icon_id": "24289120",
"name": "下载-icon",
"font_class": "xiazai-icon",
"unicode": "e8d7",
"unicode_decimal": 59607
},
{
"icon_id": "24289121",
"name": "master_icon",
"font_class": "master_icon1",
"unicode": "e8d8",
"unicode_decimal": 59608
},
{
"icon_id": "24289122",
"name": "上传icon",
"font_class": "shangchuanicon",
"unicode": "e8d9",
"unicode_decimal": 59609
},
{
"icon_id": "24059956",
"name": "个人资料",
"font_class": "gerenziliao1",
"unicode": "e8c7",
"unicode_decimal": 59591
},
{
"icon_id": "24059409",
"name": "里程碑icon",
"font_class": "lichengbeiicon",
"unicode": "e885",
"unicode_decimal": 59525
},
{
"icon_id": "24059410",
"name": "仓库设置icon",
"font_class": "cangkushezhiicon",
"unicode": "e889",
"unicode_decimal": 59529
},
{
"icon_id": "24059411",
"name": "动态icon",
"font_class": "dongtaiicon",
"unicode": "e88a",
"unicode_decimal": 59530
},
{
"icon_id": "24059412",
"name": "工作流icon",
"font_class": "gongzuoliuicon",
"unicode": "e88b",
"unicode_decimal": 59531
},
{
"icon_id": "24059413",
"name": "易修icon",
"font_class": "yixiuicon1",
"unicode": "e89b",
"unicode_decimal": 59547
},
{
"icon_id": "24059414",
"name": "wiki icon",
"font_class": "a-wikiicon1",
"unicode": "e8c6",
"unicode_decimal": 59590
},
{
"icon_id": "24047186",
"name": "代码库icon",
"font_class": "daimakuicon1",
"unicode": "e8c5",
"unicode_decimal": 59589
},
{
"icon_id": "24047189",
"name": "我的通知",
"font_class": "wodetongzhi",
"unicode": "e8c8",
"unicode_decimal": 59592
},
{
"icon_id": "24047190",
"name": "通知管理",
"font_class": "tongzhiguanli",
"unicode": "e8c9",
"unicode_decimal": 59593
},
{
"icon_id": "24047191",
"name": "选中",
"font_class": "xuanzhong3",
"unicode": "e8ca",
"unicode_decimal": 59594
},
{
"icon_id": "24047192",
"name": "系统通知icon",
"font_class": "xitongtongzhiicon",
"unicode": "e8cb",
"unicode_decimal": 59595
},
{
"icon_id": "24047193",
"name": "消息",
"font_class": "xiaoxi2",
"unicode": "e8cc",
"unicode_decimal": 59596
},
{
"icon_id": "24047194",
"name": "ssh密钥",
"font_class": "sshmiyue",
"unicode": "e8cd",
"unicode_decimal": 59597
},
{
"icon_id": "24014152",
"name": "个人资料",
"font_class": "gerenziliao",
"unicode": "e8c4",
"unicode_decimal": 59588
},
{
"icon_id": "23655968",
"name": "新手指引",
"font_class": "xinshouzhiyin",
"unicode": "e8e4",
"unicode_decimal": 59620
},
{
"icon_id": "23655969",
"name": "新建项目",
"font_class": "xinjianxiangmu",
"unicode": "e8e6",
"unicode_decimal": 59622
},
{
"icon_id": "23658111",
"name": "加入课堂",
"font_class": "jiaruketang1",
"unicode": "e8e9",
"unicode_decimal": 59625
},
{
"icon_id": "23791639",
"name": "项目公告",
"font_class": "xiangmugonggao",
"unicode": "e8c2",
"unicode_decimal": 59586
},
{
"icon_id": "23791640",
"name": "成果",
"font_class": "chengguo",
"unicode": "e8c3",
"unicode_decimal": 59587
},
{
"icon_id": "23791410",
"name": "成交公告",
"font_class": "chengjiaogonggao",
"unicode": "e8c0",
"unicode_decimal": 59584
},
{
"icon_id": "23791411",
"name": "技术资产",
"font_class": "jishuzichan",
"unicode": "e8c1",
"unicode_decimal": 59585
},
{
"icon_id": "23790928",
"name": "废标公告",
"font_class": "feibiaogonggao",
"unicode": "e8bc",
"unicode_decimal": 59580
},
{
"icon_id": "23790929",
"name": "中标公告",
"font_class": "zhongbiaogonggao",
"unicode": "e8bd",
"unicode_decimal": 59581
},
{
"icon_id": "23790930",
"name": "更正公告",
"font_class": "gengzhenggonggao",
"unicode": "e8be",
"unicode_decimal": 59582
},
{
"icon_id": "23790931",
"name": "招标公告",
"font_class": "zhaobiaogonggao",
"unicode": "e8bf",
"unicode_decimal": 59583
},
{
"icon_id": "23732532",
"name": "文件",
"font_class": "wenjian6",
"unicode": "e8ba",
"unicode_decimal": 59578
},
{
"icon_id": "23732533",
"name": "文件夹",
"font_class": "wenjianjia4",
"unicode": "e8bb",
"unicode_decimal": 59579
},
{
"icon_id": "23642443",
"name": "取消关注",
"font_class": "quxiaoguanzhu",
"unicode": "e89a",
"unicode_decimal": 59546
},
{
"icon_id": "23642444",
"name": "点赞_icon",
"font_class": "dianzan_icon",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{
"icon_id": "23639530",
"name": "文件",
"font_class": "wenjian5",
"unicode": "e896",
"unicode_decimal": 59542
},
{
"icon_id": "23639533",
"name": "文件夹",
"font_class": "wenjianjia3",
"unicode": "e8a9",
"unicode_decimal": 59561
},
{
"icon_id": "23639440",
"name": "复制icon",
"font_class": "fuzhiicon",
"unicode": "e886",
"unicode_decimal": 59526
},
{
"icon_id": "23639422",
"name": "主页-fill",
"font_class": "zhuye-fill",
"unicode": "e876",
"unicode_decimal": 59510
},
{
"icon_id": "23639423",
"name": "代码库icon",
"font_class": "daimakuicon",
"unicode": "e884",
"unicode_decimal": 59524
},
{
"icon_id": "23572260",
"name": "新建",
"font_class": "xinjian2",
"unicode": "e8b0",
"unicode_decimal": 59568
},
{
"icon_id": "23567674",
"name": "协议icon",
"font_class": "xieyiicon",
"unicode": "e870",
"unicode_decimal": 59504
},
{
"icon_id": "23567675",
"name": "内存icon",
"font_class": "neicunicon",
"unicode": "e891",
"unicode_decimal": 59537
},
{
"icon_id": "23567676",
"name": "自述文件_icon",
"font_class": "zishuwenjian_icon",
"unicode": "e8a6",
"unicode_decimal": 59558
},
{
"icon_id": "23472253",
"name": "标签icon",
"font_class": "biaoqianicon",
"unicode": "e882",
"unicode_decimal": 59522
},
{
"icon_id": "23472254",
"name": "编 辑",
"font_class": "a-bianji",
"unicode": "e883",
"unicode_decimal": 59523
},
{
"icon_id": "23472258",
"name": "链接icon",
"font_class": "lianjieicon",
"unicode": "e887",
"unicode_decimal": 59527
},
{
"icon_id": "23472259",
"name": "合并请求icon",
"font_class": "hebingqingqiuicon",
"unicode": "e888",
"unicode_decimal": 59528
},
{
"icon_id": "23472263",
"name": "默认点赞_icon",
"font_class": "morendianzan_icon",
"unicode": "e88e",
"unicode_decimal": 59534
},
{
"icon_id": "23472265",
"name": "目录icon",
"font_class": "muluicon",
"unicode": "e894",
"unicode_decimal": 59540
},
{
"icon_id": "23472267",
"name": "设 置",
"font_class": "a-shezhi",
"unicode": "e899",
"unicode_decimal": 59545
},
{
"icon_id": "23472269",
"name": "提交icon",
"font_class": "tijiaoicon",
"unicode": "e89e",
"unicode_decimal": 59550
},
{
"icon_id": "23472270",
"name": "默认关注_ICON",
"font_class": "morenguanzhu_ICON",
"unicode": "e89f",
"unicode_decimal": 59551
},
{
"icon_id": "23472272",
"name": "下拉按钮",
"font_class": "xialaanniu1",
"unicode": "e8a4",
"unicode_decimal": 59556
},
{
"icon_id": "23472276",
"name": "左滑icon",
"font_class": "zuohuaicon",
"unicode": "e8b5",
"unicode_decimal": 59573
},
{
"icon_id": "23472277",
"name": "master_icon",
"font_class": "master_icon",
"unicode": "e8b6",
"unicode_decimal": 59574
},
{
"icon_id": "23472278",
"name": "默认复刻_icon",
"font_class": "morenfuke_icon",
"unicode": "e8b7",
"unicode_decimal": 59575
},
{
"icon_id": "23472279",
"name": "wiki icon",
"font_class": "a-wikiicon",
"unicode": "e8b8",
"unicode_decimal": 59576
},
{
"icon_id": "23472280",
"name": "易修icon",
"font_class": "yixiuicon",
"unicode": "e8b9",
"unicode_decimal": 59577
},
{
"icon_id": "23436350",
"name": "缩放",
"font_class": "suofang",
"unicode": "e87f",
"unicode_decimal": 59519
},
{
"icon_id": "23436351",
"name": "放大icon",
"font_class": "fangdaicon",
"unicode": "e881",
"unicode_decimal": 59521
},
{
"icon_id": "23384231",
"name": "搜索_icon",
"font_class": "sousuo_icon1",
"unicode": "e873",
"unicode_decimal": 59507
},
{
"icon_id": "23384232",
"name": "欢迎_icon",
"font_class": "huanying_icon",
"unicode": "e878",
"unicode_decimal": 59512
},
{
"icon_id": "23384233",
"name": "文件夹",
"font_class": "wenjianjia2",
"unicode": "e879",
"unicode_decimal": 59513
},
{
"icon_id": "23384234",
"name": "删除icon",
"font_class": "shanchuicon1",
"unicode": "e87a",
"unicode_decimal": 59514
},
{ {
"icon_id": "23261798", "icon_id": "23261798",
"name": "请求icon", "name": "请求icon",
@ -621,6 +68,20 @@
"unicode": "e898", "unicode": "e898",
"unicode_decimal": 59544 "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", "icon_id": "23144158",
"name": "协作者管理icon", "name": "协作者管理icon",
@ -628,6 +89,13 @@
"unicode": "e8a1", "unicode": "e8a1",
"unicode_decimal": 59553 "unicode_decimal": 59553
}, },
{
"icon_id": "23144159",
"name": "选中响应icon",
"font_class": "xuanzhongxiangyingicon",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{ {
"icon_id": "23144160", "icon_id": "23144160",
"name": "选中分支icon", "name": "选中分支icon",
@ -656,6 +124,27 @@
"unicode": "e8af", "unicode": "e8af",
"unicode_decimal": 59567 "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", "icon_id": "23046290",
"name": "shanchu_tc_icon", "name": "shanchu_tc_icon",
@ -670,6 +159,13 @@
"unicode": "e88d", "unicode": "e88d",
"unicode_decimal": 59533 "unicode_decimal": 59533
}, },
{
"icon_id": "23046311",
"name": "新增页面_鼠标点击icon",
"font_class": "xinzengyemian_shubiaodianjiicon",
"unicode": "e88e",
"unicode_decimal": 59534
},
{ {
"icon_id": "23046244", "icon_id": "23046244",
"name": "导入模版_icon", "name": "导入模版_icon",
@ -677,6 +173,13 @@
"unicode": "e86f", "unicode": "e86f",
"unicode_decimal": 59503 "unicode_decimal": 59503
}, },
{
"icon_id": "23046247",
"name": "导出_悬浮",
"font_class": "daochu_xuanfu",
"unicode": "e870",
"unicode_decimal": 59504
},
{ {
"icon_id": "23046252", "icon_id": "23046252",
"name": "错误", "name": "错误",
@ -684,6 +187,13 @@
"unicode": "e872", "unicode": "e872",
"unicode_decimal": 59506 "unicode_decimal": 59506
}, },
{
"icon_id": "23046254",
"name": "成功",
"font_class": "chenggong1",
"unicode": "e873",
"unicode_decimal": 59507
},
{ {
"icon_id": "23046255", "icon_id": "23046255",
"name": "更多_icon", "name": "更多_icon",
@ -698,6 +208,13 @@
"unicode": "e875", "unicode": "e875",
"unicode_decimal": 59509 "unicode_decimal": 59509
}, },
{
"icon_id": "23046262",
"name": "复制_icon",
"font_class": "fuzhi_icon",
"unicode": "e876",
"unicode_decimal": 59510
},
{ {
"icon_id": "23046268", "icon_id": "23046268",
"name": "删除icon", "name": "删除icon",
@ -705,6 +222,27 @@
"unicode": "e877", "unicode": "e877",
"unicode_decimal": 59511 "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", "icon_id": "23046273",
"name": "搜索_删除icon", "name": "搜索_删除icon",
@ -726,6 +264,13 @@
"unicode": "e87e", "unicode": "e87e",
"unicode_decimal": 59518 "unicode_decimal": 59518
}, },
{
"icon_id": "23046277",
"name": "文件夹_icon",
"font_class": "wenjianjia_icon",
"unicode": "e87f",
"unicode_decimal": 59519
},
{ {
"icon_id": "23046278", "icon_id": "23046278",
"name": "下拉按钮", "name": "下拉按钮",
@ -733,6 +278,20 @@
"unicode": "e880", "unicode": "e880",
"unicode_decimal": 59520 "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", "icon_id": "22906287",
"name": "二次确认_icon", "name": "二次确认_icon",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3319,9 +3319,9 @@
text = text.replace(emailReg, function ($1, $2, $3, $4) { text = text.replace(emailReg, function ($1, $2, $3, $4) {
return $1.replace(/@/g, "_#_@_#_"); return $1.replace(/@/g, "_#_@_#_");
}); });
// " + editormd.urls.atLinkBase + "" + $2 + "
text = text.replace(atLinkReg, function ($1, $2) { text = text.replace(atLinkReg, function ($1, $2) {
return "<span title=\"&#64;" + $2 + "\" class=\"at-link\"> " + $1 + " </span>"; return "<a href=\"" + editormd.urls.atLinkBase + "" + $2 + "\" title=\"&#64;" + $2 + "\" class=\"at-link\">" + $1 + "</a>";
}).replace(/_#_&#64;_#_/g, "@"); }).replace(/_#_&#64;_#_/g, "@");
} }

View File

@ -3,7 +3,7 @@ import './App.css';
import { ConfigProvider } from 'antd' import { ConfigProvider } from 'antd'
import zhCN from 'antd/lib/locale-provider/zh_CN'; import zhCN from 'antd/lib/locale-provider/zh_CN';
import { import {
// BrowserRouter as Router, BrowserRouter as Router,
Route, Route,
Switch Switch
} from 'react-router-dom'; } from 'react-router-dom';
@ -19,7 +19,7 @@ import moment from 'moment'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'; import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import SiderBar from './forge/Component/SiderBar' import SiderBar from './forge/Component/SiderBar'
import { SnackbarHOC } from 'educoder'; import { SnackbarHOC } from 'educoder'
import { initAxiosInterceptors } from './AppConfig' import { initAxiosInterceptors } from './AppConfig'
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import configureStore from './redux/stores/configureStore'; import configureStore from './redux/stores/configureStore';
@ -39,11 +39,6 @@ const Projects = Loadable({
loader: () => import('./forge/Index'), loader: () => import('./forge/Index'),
loading: Loading, loading: Loading,
}) })
// forge项目详情
const ProjectDetail = Loadable({
loader: () => import("./forge/Main/DetailAdaptor"),
loading: Loading,
});
//forge安全设置 //forge安全设置
const Security = Loadable({ const Security = Loadable({
loader: () => import('./forge/SecuritySetting/Index'), loader: () => import('./forge/SecuritySetting/Index'),
@ -87,24 +82,11 @@ const Search = Loadable({
loader: () => import('./modules/search/'), loader: () => import('./modules/search/'),
loading: Loading, loading: Loading,
}) })
const WikiPreview = Loadable({
loader: () => import('./forge/Wiki/Preview'),
loading: Loading,
})
const ProjectIndex = Loadable({ const ProjectIndex = Loadable({
loader: () => import("./forge/Index"), loader: () => import("./forge/Index"),
loading: Loading, loading: Loading,
}); });
// const CreateMerge = Loadable({
// loader: () => import('./forge/Merge/NewMerge'),
// loading: Loading,
// })
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize"];
class App extends Component { class App extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -114,51 +96,6 @@ class App extends Component {
mydisplay: false, mydisplay: false,
occupation: 0, occupation: 0,
mygetHelmetapi: null, mygetHelmetapi: null,
pathType: null,
pathName: null,
}
}
UNSAFE_componentWillMount() {
initAxiosInterceptors(this.props);
let pathname = window.location.pathname ? window.location.pathname.split('/')[1] : '';
pathname && this.getPathnameType(pathname);
// 添加路由监听,决定组织还是个人
this.unlisten = this.props.history.listen((location) => {
let newPathname = location.pathname.split('/')[1];
if (this.state.pathName !== newPathname) {
// this.setState({ pathType: '' });
newPathname && this.getPathnameType(newPathname);
}
});
}
shouldComponentUpdate(nextProps, nextState) {
// (!keyWord.includes(this.props.location.pathname.split('/')[1])) &&
if (nextProps.location.pathname.split('/')[1] !== this.props.location.pathname.split('/')[1] && nextState.pathType === this.state.pathType) {
return false;
} else {
return true;
}
}
getPathnameType = (pathname) => {
if (!keyWord.includes(pathname)) {
let url = `/owners/${pathname}.json`;
axios.get(url).then((response) => {
if (response && response.status === 200) {
this.setState({
pathType: response.data.type || '404',
pathName: pathname,
})
}
});
}else{
this.setState({
pathType: pathname,
pathName: pathname,
});
} }
} }
@ -178,19 +115,13 @@ class App extends Component {
componentDidMount() { componentDidMount() {
document.title = "loading..."; document.title = "loading...";
initAxiosInterceptors(this.props);
this.getAppdata(); this.getAppdata();
window.addEventListener('error', (event) => { window.addEventListener('error', (event) => {
const msg = `${event.type}: ${event.message}`; const msg = `${event.type}: ${event.message}`;
}); });
} }
componentWillUnmount() {
this.unlisten && this.unlisten(); // 执行解绑
}
//修改登录方法 //修改登录方法
Modifyloginvalue = () => { Modifyloginvalue = () => {
this.setState({ this.setState({
@ -261,139 +192,87 @@ class App extends Component {
}; };
render() { render() {
const { mygetHelmetapi, pathType} = this.state; const { mygetHelmetapi } = this.state;
let personal = mygetHelmetapi && mygetHelmetapi.personal; let personal = mygetHelmetapi && mygetHelmetapi.personal;
return ( return (
<Provider store={store}> <Provider store={store}>
<ConfigProvider locale={zhCN}> <ConfigProvider locale={zhCN}>
<MuiThemeProvider theme={theme}> <MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog> <LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
<SiderBar /> <SiderBar/>
{/* <Router> */} <Router>
<Switch> <Switch>
{/* wiki预览 */} {/*项目*/}
<Route path="/:owner/:projectsId/wiki/preview/:projectName/:projectId" render={ <Route
(props) => { path={"/projects/:owner/:projectId/devops/:opsId/detail"}
return (<WikiPreview {...this.props} {...props} {...this.state} />) render={
} (props) => {
} /> return (<OpsDetail {...this.props} {...props} {...this.state} />)
}
{/* 项目PR */} }>
<Route path="/:owner/:projectsId/compare" </Route>
render={ <Route
(props) => (<ProjectDetail {...this.props} {...props} {...this.state} />) path={"/settings"}
} render={
></Route> (props) => {
return (<Security {...this.props} {...props} {...this.state} />)
{/*项目*/} }
<Route }>
path={"/:owner/:projectId/devops/:opsId/detail"} </Route>
render={ {/*项目*/}
(props) => { <Route
return (<OpsDetail {...this.props} {...props} {...this.state} />) path={"/projects"}
} render={
}> (props) => {
</Route> return (<Projects {...this.props} {...props} {...this.state} />)
<Route }
path={"/settings"} }>
render={ </Route>
(props) => { <Route
return (<Security {...this.props} {...props} {...this.state} />) path="/register"
} render={
}> (props) => {
</Route> return (<EducoderLogin {...this.props} {...props} {...this.state} />)
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
{/*403*/}
<Route path="/403" component={Shixunauthority} />
<Route path="/500" component={http500} />
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 查询 */}
<Route path="/search" component={Search} />
<Route exact path="/explore"
render={
(props) => (
<ProjectIndex {...this.props} {...props} />
)
}
/>
{/* 组织 */}
<Route path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route>
{/*新建项目等*/}
<Route
path={"/projects"}
render={
(props) => {
return (<Projects {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/* 判断为用户/组织,并进入对应页面 */}
{
pathType === 'User' ?
<Route exact path="/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
} }
/> : pathType === 'Organization' ? <Route path={"/:OIdentifier"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route> : pathType === '404' ? <Route component={Shixunnopage} />:
<Route exact path="/"
render={
(props) => (
personal && personal.length > 0 ?
<InfosIndex {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
)
}
/>
// <Route path="/" component={Loading} />
// <Route path="/" component={Shixunnopage} />
}
{/* 个人主页 */}
<Route path="/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
} }
/>
{/*403*/}
<Route path="/403" component={Shixunauthority} />
<Route path="/500" component={http500} />
<Route path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</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 exact path="/"
render={
<Route component={Shixunnopage} /> (props) => (
</Switch> personal && personal.length > 0 ?
{/* </Router> */} <InfosIndex {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
)
}
/>
<Route component={Shixunnopage} />
</Switch>
</Router>
</MuiThemeProvider> </MuiThemeProvider>
</ConfigProvider> </ConfigProvider>
</Provider> </Provider>

View File

@ -85,10 +85,7 @@ export function initAxiosInterceptors(props) {
} }
if (response.data.status === 404) { if (response.data.status === 404) {
let responseURL = response.request ? response.request.responseURL:''; locationurl('/nopage');
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
locationurl('/nopage');
}
} }
if (response.data.status === 500) { if (response.data.status === 500) {

View File

@ -195,7 +195,7 @@ class College extends Component {
align: 'center', align: 'center',
className: "edu-txt-center font-14 maxnamewidth105", className: "edu-txt-center font-14 maxnamewidth105",
render: (text, record) => ( render: (text, record) => (
<a href={`/${record.login}`} title={record.name} target="_blank" className="task-hide maxnamewidth105" style={{ <a href={`/users/${record.login}`} title={record.name} target="_blank" className="task-hide maxnamewidth105" style={{
color:'#007bff', color:'#007bff',
}}> { }}> {

View File

@ -218,7 +218,7 @@ a:hover {
} }
.color-blue { .color-blue {
color: #2A61FF; color: #4CACFF;
} }
.color-huang { .color-huang {

View File

@ -1,5 +1,4 @@
import moment from "moment"; import moment from "moment";
import { number } from "prop-types";
// 处理整点 半点 // 处理整点 半点
// 取传入时间往后的第一个半点 // 取传入时间往后的第一个半点
@ -98,41 +97,3 @@ export function formatDuring(mss){
} }
return days + "天" + hours + "小时" + minutes + "分"; return days + "天" + hours + "小时" + minutes + "分";
} }
/*
返回多久以前
backDate以前的某个日期
*/
export function timeAgo(backDate) {
try {
moment(backDate);
} catch (e) {
return '刚刚';
}
if(typeof backDate ==='number'){
backDate=backDate*1000
}else{
backDate= moment(backDate);
}
let time = new Date() - backDate;
var days = Math.floor(time / (1000 * 60 * 60 * 24));
var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000);
if (time <= 0) {
return "刚刚";
}
if (days) {
return days + "天前";
}
if (hours) {
return hours + "小时前";
}
if (minutes) {
return minutes + "分前";
}
if (seconds) {
return seconds + "秒前";
}
return "刚刚";
}

View File

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

View File

@ -18,23 +18,6 @@ export function getImageUrl(path) {
return `${path}`; return `${path}`;
} }
export function numFormat(num, digits){
let d = digits || 1;
var si = [
{ value: 1, symbol: "" },
{ value: 1E3, symbol: "k" },
{ value: 1E4, symbol: "W" }
];
var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
var i;
for (i = si.length - 1; i > 0; i--) {
if (num >= si[i].value) {
break;
}
}
return (num / si[i].value).toFixed(d).replace(rx, "$1") + si[i].symbol;
}
export function getImage(path) { export function getImage(path) {
// https://www.educoder.net // https://www.educoder.net
// https://testbdweb.trustie.net // https://testbdweb.trustie.net

View File

@ -3,7 +3,7 @@
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil'; // export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export { export {
getUploadLogoActionUrl as getUploadLogoActionUrl,numFormat as numFormat, getUploadLogoActionUrl as getUploadLogoActionUrl,
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth , getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl , getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl
@ -27,7 +27,7 @@ export {
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension, markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
} from './TextUtil' } from './TextUtil'
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil' export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil'
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil' export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'

View File

@ -435,11 +435,11 @@ class TPIContextProvider extends Component {
image_url: "avatars/User/1" image_url: "avatars/User/1"
login: "innov" login: "innov"
name: "Coder" name: "Coder"
user_url: "/innov" user_url: "/users/innov"
*/ */
let user = resData.user; let user = resData.user;
user.username = resData.user.name; user.username = resData.user.name;
user.user_url = `/${resData.user.login}`; user.user_url = `/users/${resData.user.login}`;
// user.image_url = resData.image_url; // user.image_url = resData.image_url;
user.is_teacher = resData.is_teacher; user.is_teacher = resData.is_teacher;
resData.user = user; resData.user = user;

View File

@ -10,10 +10,6 @@ import ActivityItem from './ActivityItem';
import axios from 'axios'; import axios from 'axios';
const LIMIT = 15; const LIMIT = 15;
const ARRAY = [ const ARRAY = [
{
id:"",
name:'全部'
},
{ {
id:1, id:1,
name:'1天' name:'1天'
@ -36,15 +32,10 @@ class Activity extends Component{
constructor(props){ constructor(props){
super(props); super(props);
this.state={ this.state={
time:undefined, time:'30',
type:undefined, type:undefined,
state:undefined, state:undefined,
page:1, page:1,
pr_count:undefined,
new_pr_count:undefined,
close_issues_count:undefined,
open_issues_count:undefined,
pr_all_count:undefined,issues_count:undefined,
data:undefined, data:undefined,
project_trends:undefined, project_trends:undefined,
@ -72,15 +63,8 @@ class Activity extends Component{
this.setState({ this.setState({
data:result.data, data:result.data,
project_trends:result.data.project_trends, project_trends:result.data.project_trends,
isSpin:false, isSpin:false
pr_count:result.data.pr_count,
new_pr_count:result.data.new_pr_count,
close_issues_count:result.data.close_issues_count,
open_issues_count:result.data.open_issues_count,
pr_all_count:result.data.pr_all_count,
issues_count:result.data.issues_count,
}) })
window.scrollTo(0,0);
} }
}).catch(error=>{ }).catch(error=>{
console.log(error); console.log(error);
@ -90,19 +74,19 @@ class Activity extends Component{
// 切换周期 // 切换周期
changeTime=(e)=>{ changeTime=(e)=>{
this.setState({ this.setState({
time:e.key ==="item_0"?undefined:e.key, time:e.key,
isSpin:true isSpin:true
}) })
const { type,status,page } = this.state; const { type,status,page } = this.state;
this.getInfo(e.key ==="item_0"?undefined:e.key,type,status,page); this.getInfo(e.key,type,status,page);
} }
//筛选 //筛选
changeTrends=(type,status)=>{ changeTrends=(type,status)=>{
this.setState({ this.setState({
type,status,page:1 type,status
}) })
const {time}=this.state; const {time,page}=this.state;
this.getInfo(time,type,status,1); this.getInfo(time,type,status,page);
} }
// 分页 // 分页
ChangePage=(page)=>{ ChangePage=(page)=>{
@ -124,14 +108,12 @@ class Activity extends Component{
</Menu> </Menu>
) )
render(){ render(){
const { time , data , page , project_trends , isSpin , pr_count , new_pr_count , close_issues_count , open_issues_count , pr_all_count ,issues_count } = this.state; const { time , data , page , project_trends , isSpin } = this.state;
let name = time ? ARRAY.filter(item=>item.id === parseInt(time)) :[{name:"全部"}];
const first_per = pr_all_count > 0 ? `${parseFloat(pr_count/pr_all_count).toFixed(2)*100}%` :"50%"; let name = time && ARRAY.filter(item=>item.id === parseInt(time)) ;
const second_per =pr_all_count > 0 ? `${parseFloat(new_pr_count/pr_all_count).toFixed(2)*100}%` :"50%"; const second_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
const third_per =issues_count > 0 ?`${parseFloat(close_issues_count/issues_count).toFixed(2)*100}%` :"50%"; const third_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
const fourth_per =issues_count > 0 ?`${parseFloat(open_issues_count/issues_count).toFixed(2)*100}%` :"50%"; const fourth_per = (parseInt(data && data.open_issues_count)/parseInt(data && data.issues_count)*100)+'%';
return( return(
<div className="main"> <div className="main">
@ -140,7 +122,7 @@ class Activity extends Component{
<div className="orderInfo"> <div className="orderInfo">
<div> <div>
<div className="percentLine prPercent"> <div className="percentLine prPercent">
<p className="percent_purple" style={{width:first_per}}></p> <p className="percent_purple" style={{width:'100%'}}></p>
<p className="percent_green resetStyle" style={{width:`${second_per}`}}></p> <p className="percent_green resetStyle" style={{width:`${second_per}`}}></p>
</div> </div>
<span>{data && data.pr_all_count}合并请求</span> <span>{data && data.pr_all_count}合并请求</span>
@ -150,25 +132,25 @@ class Activity extends Component{
<p className="percent_red" style={{width:`${third_per}`}}></p> <p className="percent_red" style={{width:`${third_per}`}}></p>
<p className="percent_green" style={{width:`${fourth_per}`}}></p> <p className="percent_green" style={{width:`${fourth_per}`}}></p>
</div> </div>
<span>{data && data.issues_count}易修</span> <span>{data && data.issues_count}任务</span>
</div> </div>
</div> </div>
<ul className="percentBox"> <ul className="percentBox">
<li> <li>
<span className="purple">{data && data.pr_count}</span> <span className="purple">{data && data.pr_count}</span>
<span className="change" onClick={()=>this.changeTrends("PullRequest","delay")}>已处理的合并请求</span> <span className="change" onClick={()=>this.changeTrends("PullRequest","close")}>已处理的合并请求</span>
</li> </li>
<li> <li>
<span className="green">{data && data.new_pr_count}</span> <span className="green">{data && data.new_pr_count}</span>
<span className="change" onClick={()=>this.changeTrends("PullRequest","not_delay")}>未处理的合并请求</span> <span className="change" onClick={()=>this.changeTrends("PullRequest","create")}>未处理的合并请求</span>
</li> </li>
<li> <li>
<span className="red">{data && data.close_issues_count}</span> <span className="red">{data && data.close_issues_count}</span>
<span className="change" onClick={()=>this.changeTrends("Issue","delay")}>已关闭的易修</span> <span className="change" onClick={()=>this.changeTrends("Issue","close")}>已关闭的任务</span>
</li> </li>
<li> <li>
<span className="green">{data && data.open_issues_count}</span> <span className="green">{data && data.open_issues_count}</span>
<span className="change" onClick={()=>this.changeTrends("Issue","not_delay")}>未处理的易修</span> <span className="change" onClick={()=>this.changeTrends("Issue","create")}>未处理的任务</span>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -14,25 +14,25 @@ class ActivityItem extends Component {
{/* 如果是版本发布 */} {/* 如果是版本发布 */}
{item.trend_type === "VersionRelease" ? {item.trend_type === "VersionRelease" ?
<p className="itemLine"> <p className="itemLine">
<Link to={`/${owner}/${projectsId}/releases`} className="color-blue font-16">{item.name}</Link> <Link to={`/projects/${owner}/${projectsId}/version`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span> <span className="activity_type">{item.trend_type}</span>
</p > </p >
: :
// 如果是任务 // 如果是任务
item.trend_type === "Issue" ? item.trend_type === "Issue" ?
<p className="itemLine"> <p className="itemLine">
<Link to={`/${owner}/${projectsId}/issues/${item.trend_id}`} className="color-blue font-16">{item.name}</Link> <Link to={`/projects/${owner}/${projectsId}/issues/${item.trend_id}/detail`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span> <span className="activity_type">{item.trend_type}</span>
</p > </p >
: :
// 如果是合并请求 // 如果是合并请求
<p className="itemLine"> <p className="itemLine">
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}`} className="color-blue font-16">{item.name}</Link> <Link to={`/projects/${owner}/${projectsId}/pulls/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span> <span className="activity_type">{item.trend_type}</span>
</p > </p >
} }
<p className="itemLine mt10"> <p className="itemLine mt10">
<Link to={`/${item && item.user_login}`} className="show-user-link"> <Link to={`/users/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" /> <img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span> <span className="mr20">{item.user_name}</span>
</Link> </Link>

View File

@ -1,20 +1,28 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Menu } from 'antd'; import { Dropdown, Menu, Tooltip } from 'antd';
import "./branch.scss"; import "./branch.scss";
import CopyTool from '../Component/CopyTool';
function CloneAddress({http_url , ssh_url , zip_url , tar_url}) { function CloneAddress({http_url , ssh_url , zip_url , tar_url}) {
const [ key , setKey ] = useState("HTTP"); const [ key , setKey ] = useState("HTTP");
// 点击按钮复制功能
function jsCopy(){
var e = document.getElementById("copy_rep_content");
e.select();
document.execCommand("Copy");
}
return ( return (
<div className="downMenu"> <div className="downMenu">
<div style={{borderBottom:"1px solid #eee"}}> <div style={{padding:"10px 20px 20px 20px",borderBottom:"1px solid #eee"}}>
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}> <Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
<Menu.Item key="HTTP" onClick={(e)=>{setKey(e.key)}}>HTTP</Menu.Item> <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.Item key="SSH" onClick={(e)=>{setKey(e.key)}}>SSH</Menu.Item>
</Menu> </Menu>
<div className="gitAddressClone"> <div className="gitAddressClone">
<input type="text" id="copy_rep_content" value={key==="HTTP" ? http_url:ssh_url} /> <input type="text" id="copy_rep_content" value={key==="HTTP" ? http_url:ssh_url} />
<CopyTool inputId="copy_rep_content" className="copytool"/> <Tooltip title="复制链接">
<span className="color-blue" onClick={jsCopy}><i className="iconfont icon-fuzhi"></i></span>
</Tooltip>
</div> </div>
</div> </div>
<Menu className="edu-txt-center"> <Menu className="edu-txt-center">

View File

@ -1,65 +1,116 @@
import React , { useState , useEffect , useRef } from 'react'; import React , { useState , useEffect } from 'react';
import { Dropdown} from 'antd'; import { Popover , Input , Spin } from 'antd';
import './branch.scss'; import './branch.scss';
import SelectOverlay from './SelectOverlay'; import { getBranch , getTag } from '../GetData/getData';
import { findDOMNode } from 'react-dom';
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{ export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
const [ showValue , setShowValue ] = useState(branch); const [ showValue , setShowValue ] = useState(branch);
const [ visible , setVisible ] = useState(false); const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const [ flag , setFlag ] = useState(false);
const refFa = useRef(null); const [ data , setData ] = useState(undefined);
const refBox = useRef(null); const [ datas , setDatas ] = useState(undefined);
useEffect(() => {
document.addEventListener('click', clickMe , false);
}, [])
const clickMe = ({ target }) => {
//
const faComponent = findDOMNode(refFa.current);
const boxComponent = findDOMNode(refBox.current);
if (faComponent && boxComponent) {
const isChild = faComponent.contains(target);
const isBox = boxComponent.contains(target);
if(!isChild && !isBox){
setVisible(false);
}
}
}
useEffect(()=>{ useEffect(()=>{
setShowValue(branch); setShowValue(branch);
},[branch]) },[branch])
function ChangeB(params) { useEffect(()=>{
setVisible(false); document.body.addEventListener('click', e => {
changeBranch(params); let name = e.target.className;
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
if(turn){
return;
}else{
setFlag(false);
}
})
})
useEffect(()=>{
if(branchList){
setData(branchList);
setDatas(branchList);
setIsSpin(false);
}
},[branchList])
async function getBranchs(id,owner){
let result = await getBranch(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
async function getTags(id,owner){
let result = await getTag(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
} }
function changeInputValue(e){
setInputValue(e.target.value);
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
setDatas(filter);
}
function changeNav(nav){
setNav(nav);
setIsSpin(true);
if(nav === 0){
getBranchs(projectsId,owner);
}else{
getTags(projectsId,owner);
}
}
function chooseitem(value){
// setShowValue(value);
changeBranch(value);
}
const menu = ( const menu = (
<div ref={refFa}> <div>
<SelectOverlay <div className="padding10 bor-bottom-greyE">
visible={visible} <Input
changeBranch={ChangeB} placeholder="请输入分支或标签名称搜索"
tagflag={tagflag} autocomplete="off" className="OptionsInput" value={inputValue}
projectsId={projectsId} onChange={changeInputValue} style={{width:"220px"}}
owner={owner} />
branchList={branchList} <ul className="navUl">
/> <li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
</ul>
</div>
<Spin spinning={isSpin}>
<ul className="OptionsUl" id="ul-btn">
{
datas && datas.length>0 ?
datas.map((item,key)=>{
return(
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
)
}):
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
}
</ul>
</Spin>
</div> </div>
); );
return( return(
<Dropdown placement='bottomLeft' visible={visible} overlay={menu} overlayClassName="branch-tagBox-list" trigger={['click']} > <Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<div className="branch-tagBox" ref={refBox} onClick={()=>setVisible(visible ? false : true)}> <div className="branch-tagBox">
{/* {nav === 0 ?"分支":"标签"} */} {/* {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"><i className="iconfont icon-fenzhi2 font-18"></i></span>
<span className="ant-dropdown-link task-hide" style={{fontWeight:"500",minWidth:"45px",maxWidth:"270px"}}> <a className="ant-dropdown-link">
{showValue} {showValue}
</span> </a>
<i className="showtag iconfont icon-sanjiaoxing-down font-15 color-grey-9 mr5 ml5 mt1" /> <i className="showtag iconfont icon-xiajiantou font-14 color-grey-9 mr8" />
</div> </div>
</Dropdown> </Popover>
) )
}) })

View File

@ -1,90 +0,0 @@
import React , { useState , useEffect } from 'react';
import { Input , Spin , Menu } from 'antd';
import { getBranch , getTag } from '../GetData/getData';
function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }) {
const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const [ data , setData ] = useState(undefined);
const [ datas , setDatas ] = useState(undefined);
const [ keys ,setKeys] = useState("branch");
useEffect(()=>{
if(visible){
setKeys("branch");
getBranchs(projectsId,owner);
setIsSpin(true);
}
},[visible])
async function getBranchs(id,owner){
let result = await getBranch(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
async function getTags(id,owner){
let result = await getTag(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
function chooseitem(value){
changeBranch(value);
}
function changeInputValue(e){
setInputValue(e.target.value);
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
setDatas(filter);
}
function changeNav(e){
setKeys(e.key);
setIsSpin(true);
if(e.key === "branch"){
getBranchs(projectsId,owner);
setNav(0);
}else{
getTags(projectsId,owner);
setNav(1);
}
}
return(
<div className="overlayBranch">
<div className="padding15" style={{paddingBottom:"0px"}}>
<Input
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
placeholder={`请输入分支${tagflag ? "或标签" :""}名称搜索`}
autocomplete="off" className="OptionsInput"
value={inputValue}
onChange={changeInputValue}
/>
</div>
<Menu mode="horizontal" className="navUl" selectedKeys={[keys]} onClick={changeNav}>
<Menu.Item key={"branch"}>分支</Menu.Item>
{ tagflag && <Menu.Item key={"tag"}>标签</Menu.Item> }
</Menu>
<Spin spinning={isSpin}>
<ul className="OptionsUl" id="ul-btn">
{
datas && datas.length>0 &&
datas.map((item,key)=>{
return(
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
)
})
}
{
datas && datas.length === 0 &&
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
}
</ul>
</Spin>
</div>
)
}
export default SelectOverlay;

View File

@ -23,16 +23,14 @@
max-height: 300px; max-height: 300px;
} }
.OptionsUl{ .OptionsUl{
min-height: 50px;
max-height: 220px; max-height: 220px;
overflow-y: auto; overflow-y: auto;
} }
.OptionsUl li{ .OptionsUl li{
height: 30px; height: 35px;
line-height: 30px; line-height: 35px;
cursor: pointer; cursor: pointer;
padding:0px 20px; padding:0px 10px;
margin:5px 0px;
} }
.OptionsUl li:hover{ .OptionsUl li:hover{
background-color: #F0F0F0; background-color: #F0F0F0;
@ -47,56 +45,38 @@
width: 100%; width: 100%;
} }
.branch-tagBox{ .branch-tagBox{
border:1px solid #D0D0D0; border:1px solid #eee;
border-radius: 3px; border-radius: 3px;
height: 32px; height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
min-width: 104px; min-width: 140px;
} }
.branch-tagBox:hover{ .branch-tagBox-list .ant-popover-arrow{
background-color: #F3F4F6; display: none;
} }
.branch-tagBox-list{ .branch-tagBox-list.ant-popover.ant-popover-placement-bottom{
background: #FFFFFF; padding-top:0px;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
.ant-popover-arrow{
display: none;
}
&.ant-popover.ant-popover-placement-bottom{
padding-top:0px;
}
.branch-tagBox .ant-dropdown-link{
display: block;
flex:1;
max-width: 105px;
}
.ant-popover-inner-content{
padding:0px;
}
} }
.overlayBranch{ .branch-tagBox .ant-dropdown-link{
width: 325px; display: block;
.navUl{ flex:1;
margin-top: 8px; }
height: 30px; .branch-tagBox-list .ant-popover-inner-content{
line-height: 30px; padding:0px;
li{ }
height: 30px; .navUl{
line-height: 30px; display: flex;
padding:0px 5px; justify-content: space-between;
margin-left: 20px!important; align-items: center;
&.ant-menu-item-selected{ margin-top: 5px;
border-color:#466aff!important; }
color:#466aff!important; .navUl li{
} cursor: pointer;
&.ant-menu-item-active{ }
border-color:transparent ; .navUl li.active{
} color:#5091FF;
}
}
} }
.listTips{ .listTips{
padding:20px 0px; padding:20px 0px;
@ -106,7 +86,6 @@
.urlMenu{ .urlMenu{
line-height: 30px; line-height: 30px;
margin-bottom: 10px; margin-bottom: 10px;
padding:15px 20px 0px 20px;
border-bottom: none; border-bottom: none;
li.ant-menu-item{ li.ant-menu-item{
height: 30px; height: 30px;
@ -117,13 +96,10 @@
color: #333; color: #333;
} }
&.ant-menu-item-selected{ &.ant-menu-item-selected{
border-color:#466aff!important; border-color:#1890ff!important;
} }
&.ant-menu-item-active{ &.ant-menu-item-active{
border-color:transparent ; border-color:transparent ;
} }
} }
}
.copytool{
margin:0px 10px;
} }

View File

@ -55,7 +55,6 @@ function AddGroup({organizeId,getGroupID}){
function addCollaborator(){ function addCollaborator(){
getGroupID && getGroupID(id); getGroupID && getGroupID(id);
setID(undefined);
} }
return( return(

View File

@ -113,14 +113,7 @@ li.ant-menu-item{
z-index: 10000; z-index: 10000;
} }
.laterest{ .laterest{
background-color: #EF3131; color: #05690d;
color: #fff;
font-size: 12px;
margin-left: 10px;
padding:0px 5px;
border-radius: 2px;
height: 18px;
line-height: 18px;
} }
@media screen and (max-width: 1800px){ @media screen and (max-width: 1800px){
@ -162,112 +155,41 @@ li.ant-menu-item{
margin:0px 20px!important; margin:0px 20px!important;
} }
} }
.hoverA{
display:flex;
align-items: center;
max-width: 78px;
&:hover a{
color:#2A61FF !important ;
}
}
.menuPanels{ .menuPanels{
width: 295px; width: 240px;
.leftline{ height: 180px;
position: relative;
color: #666;
height: 16px;
margin-left: 14px;
font-size: 12px;
&::before{
position: absolute;
left: -7px;
top:3px;
height: 12px;
width: 1px;
background-color: #999;
content: "";
}
}
.ant-btn{
height: 36px;
line-height: 34px;
width: 83px;
text-align: center;
padding:0px ;
font-weight: 500;
font-size: 14px;
&.currentBtn{
cursor: default;
color: #333;
&:hover{
color: #333;
border-color: #d0d0d0;
}
}
}
.ant-btn-default{
color: #333;
border-color: #d0d0d0;
&:hover{
background: #F3F4F6;
}
}
.ant-btn{
width: 102px;
height: 32px;
line-height: 30px;
}
.ant-btn-primary{
color: #fff;
background-color: #466AFF;
border:none;
&:hover{
background-color: rgba(70,106,255,0.85);
}
}
.focusPanelHeadInfo{
padding:14px 16px;
border-bottom: 1px solid #eee;
}
.ant-popover-content,.ant-popover-inner{ .ant-popover-content,.ant-popover-inner{
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.ant-popover-inner-content{
padding:0px;
}
} }
.halfs{ .halfs{
margin-top: 24px; margin-top: 24px;
padding:24px 0px 0px 0px; padding:24px 0px 0px 0px;
border-top: 1px solid #e8e8e8; border-top: 1px solid #e8e8e8;
} .attrPerson{
.aboutSubTitle{ padding-bottom: 24px;
display: flex; }
align-items: center;
}
.menuMaininfos{
padding:10px 16px 14px;
border-bottom: 1px solid #eee;
} }
.menuinfos{ .menuinfos{
padding:10px 20px 16px; padding:15px 0px;
&>a{ &>a{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
border-right: 1px solid #eee;
flex: 1; flex: 1;
& >span:first-child{ & >span:first-child{
font-size: 16px; font-size: 18px;
font-weight: 500; font-weight: 400;
color: #333; color: #333;
line-height: 22px;
} }
& >span:last-child{ & >span:last-child{
color: #666; color: #666;
font-weight: 400; }
line-height: 20px; &:last-child{
margin-top: 6px; border-right: none;
} }
} }
} }

View File

@ -1,13 +1,13 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '../Component/layout'; import { AlignCenter , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Popover , Spin , Button } from 'antd'; import { Popover , Spin } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import './Component.scss'; import './Component.scss';
import { getUser } from '../GetData/getData'; import { getUser } from '../GetData/getData';
import axios from 'axios'; import axios from 'axios';
function Contributors({contributors,owner,projectsId,currentLogin}){ function Contributors({contributors,owner,projectsId}){
const [ menuList ,setMenuList ]= useState([]); const [ menuList ,setMenuList ]= useState([]);
const [ list , setList ]= useState(undefined); const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0); const [ total , setTotal ]= useState(0);
@ -46,60 +46,46 @@ function Contributors({contributors,owner,projectsId,currentLogin}){
} }
} }
function renderOrganize(list) {
let str = "";
list.map(i=>{
str = str+i.name + "、";
})
return str && str.substr(0,str.length - 1);
}
function setMenusFunc(data){ function setMenusFunc(data){
if(data){ if(data){
let ele = ( let ele = (
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<FlexAJ className="menuMaininfos"> <FlexAJ>
<AlignCenter> <AlignCenter>
<Link to={`/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link> <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>
<div className="ml10">
<Link to={`/${data.login}`}>{data.name}</Link>
{ data.location && <span className="leftline">{data.location}</span> }
{
data.organizations && data.organizations.length>0&&
<p className="task-hide" style={{maxWidth:"215px"}}>
所属组织{renderOrganize(data.organizations)}
</p>
}
</div>
</AlignCenter> </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> </FlexAJ>
<AlignCenter className="menuinfos"> <AlignCenter className="menuinfos">
<Link to={`/${data.login}/projects`}> <a href={data.projects_url}>
<span>{data.projects_count}</span> <span>{data.projects_count}</span>
<span>项目数</span> <span>项目数</span>
</Link> </a>
<Link to={`/${data.login}/followers`}> <a href={data.followers_url}>
<span>{data.followers_count}</span> <span>{data.followers_count}</span>
<span>粉丝数</span> <span>粉丝数</span>
</Link> </a>
<Link to={`/${data.login}/following`}> <a href={data.following_url}>
<span>{data.following_count}</span> <span>{data.following_count}</span>
<span>关注数</span> <span>关注数</span>
</Link> </a>
</AlignCenter> </AlignCenter>
<div className={"pb20"} style={{display:"flex",justifyContent:'center'}}> {
{ data.organizations && data.organizations.length > 0 ?
currentLogin && (currentLogin === data.login) <AlignCenter className="font-12 pt4 pb4">
? <span>所属组织</span>
<Button className="currentBtn">当前用户</Button> <div className="task-hide flex1">
: {renderArray(data.organizations)}
data.is_watch ? </div>
<Button type={"default"} onClick={()=>FocusFunc(false,data.login)}>已关注</Button> </AlignCenter>
: :""
<Button type={"primary"} onClick={()=>FocusFunc(true,data.login)}>关注TA</Button> }
} {
</div> data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
}
</Spin> </Spin>
) )
setMenu(ele); setMenu(ele);
@ -149,17 +135,17 @@ function Contributors({contributors,owner,projectsId,currentLogin}){
return( return(
<div className="halfs"> <div className="halfs">
<Link to={`/${owner}/${projectsId}/contribute`} className="font-16 color-ooo hoverA"> <FlexAJ>
<span>贡献者</span> <AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter>
{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>} <Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/contribute`}>全部</Link>
</Link> </FlexAJ>
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}> <div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
{ {
total > 0 ? total > 0 ?
list.map((item,key)=>{ list.map((item,key)=>{
return( return(
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top"> <Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
<Link key={key} to={`/${item.login}`}> <Link key={key} to={`/users/${item.login}`}>
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/> <img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
</Link> </Link>
</Popover> </Popover>

View File

@ -1,51 +0,0 @@
import React, { useState, useCallback, memo } from 'react';
import { Tooltip } from 'antd';
CopyTool.defaultProps = {
beforeText: '复制链接', //
afterText: '复制成功', //
className: '', //svgclass
inputId: 'copyText', //ID
timeOut:true, //beforeText
};
function CopyTool({ beforeText, afterText, className , inputId , timeOut }) {
const [title, setTitle] = useState(() => {
return beforeText;
});
//
const copyUrl = useCallback(() => {
const copyEle = document.querySelector(`#${inputId}`); //
if (!copyEle) {
console.error("您的CopyTool未设置正确的inputId");
return;
}
copyEle.select(); //
if (document.execCommand('copy')) {
document.execCommand('copy');
}
document.getSelection().removeAllRanges();
setTitle(afterText);
if(timeOut){
setTimeout(function(){
setTitle(beforeText);
},1500)
}
}, []);
return (
<Tooltip
placement="top"
title={title}
onVisibleChange={() => { setTitle(beforeText) }}
>
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i>
</Tooltip>
);
}
export default memo(CopyTool);

View File

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

View File

@ -0,0 +1,45 @@
.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

@ -78,7 +78,7 @@ function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , li
if(dataref.type==="file"){ if(dataref.type==="file"){
onClose(); onClose();
let value = turnbar(branch); let value = turnbar(branch);
history.push(`/${owner}/${projectsId}/tree/${value}/${dataref.path}`); history.push(`/projects/${owner}/${projectsId}/tree/${value}/${dataref.path}`);
} }
} }

View File

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

View File

@ -25,7 +25,7 @@ function LanguagePower({languages}){
} }
return( return(
<div> <div>
<p className="font-16 color-ooo aboutSubTitle">开发语言</p> <p className="font-16 color-grey-6">开发语言</p>
<div className="progress"> <div className="progress">
{ {
array && array.map((item,key)=>{ array && array.map((item,key)=>{

View File

@ -45,15 +45,15 @@ const Div = styled.div`{
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => { export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
return ( return (
<Div> <Div>
<Link to={`/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link> <Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
<div className="m-infos"> <div className="m-infos">
<Link to={`/${user && user.login}`}><Name>{name}</Name></Link> <Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time> <Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
{ {
is_current_user ? is_current_user ?
<Button type="default">当前用户</Button> <Button type="default">当前用户</Button>
: :
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc} notReset={true}/> <FocusButton is_watch={focusStatus} id={login} successFunc={successFunc}/>
} }
</div> </div>
</Div> </Div>

View File

@ -1,125 +0,0 @@
/* eslint-disable react/jsx-no-duplicate-props */
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { Modal, Button } from 'antd';
import './index.scss';
//
InitModal.defaultProps = {
okText: '确认', //
cancelText: '取消', //
className: '', //
inputId: 'copyText', //ID
onCancel:()=>{}, //
onOk:()=>{}, //
title:'提示', //
contentTitle:'', //
content:'', //
afterClose:()=>{}, //
};
// 使
export default function DelModal(props) {
renderModal({ ...props, type: 'delete' })
}
// 使
export function Confirm(props) {
renderModal({ ...props, type: 'confirm' })
}
function renderModal(props) {
const { type, afterClose } = props;
const div = document.createElement('div');
document.body.appendChild(div);
function destroy() {
afterClose && afterClose();
const unmountResult = ReactDOM.unmountComponentAtNode(div);
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
}
}
function modalType(type) {
if (type === 'delete') {
return <InitModal
title="删除"
contentTitle="确定要删除吗?"
okText="确认删除"
{...props}
afterClose={destroy}
contentTitle={<React.Fragment>
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{props.contentTitle}
</React.Fragment>}
/>
} else if (type === 'confirm') {
return <InitModal title="选择" afterClose={destroy} {...props} />
} else {
return <InitModal title="选择" afterClose={destroy} {...props} />
}
}
function render() {
setTimeout(() => {
ReactDOM.render(
modalType(type),
div,
);
});
}
render();
}
//
function InitModal({
onCancel,
onOk,
title,
contentTitle,
content,
okText,
cancelText,
afterClose,
className,
}) {
const [visible, setVisible] = useState(true);
function onCancelModal() {
setVisible(false);
onCancel && onCancel()
}
function onSuccess() {
setVisible(false);
onOk && onOk();
}
return (
<Modal
visible={visible}
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className={`myself-modal ${className}`}
centered
footer={[
<Button type="default" key="back" onClick={onCancelModal}>
{cancelText}
</Button>,
<Button className="foot-submit" key="submit" onClick={onSuccess}>
{okText}
</Button>,
]}
>
<div>
{contentTitle && <p className="content-title">{contentTitle}</p>}
<p className="content-descibe">{content}</p>
</div>
</Modal>
)
}

View File

@ -1,63 +0,0 @@
.myself-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.content-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.content-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.foot-submit {
margin-left: 3rem;
color: #df0002;
&:hover {
border-color: #df0002;
}
}
.ant-btn-default:hover,
.ant-btn-default:active,
.ant-btn-default:focus {
background: #f3f4f6;
color: #333;
border-color: #d0d0d0;
}
}

View File

@ -1,90 +0,0 @@
.systemBox{
.ant-modal-body{
padding:1px 0px 0px 0px;
.sysBox{
background-image: url('./bg.png');
background-repeat: no-repeat;
background-size: 100% 334px;
margin-top: -55px;
}
.sysnoticeBox{
width: 100%;
padding:80px 0px 34px;
display: flex;
flex-direction: column;
width: 780px;
margin: 0px auto;
p.ntitle{
height: 33px;
font-size: 24px;
font-weight: 500;
color: #31FFF7;
line-height: 33px;
text-align: center;
}
p.nSubtitle{
height: 25px;
line-height: 25px;
font-size: 18px;
font-weight: 500;
color: #FFFFFF;
margin-top: 60px;
padding-left: 20px;
}
.markdown-body{
box-shadow: 0px 0px 17px rgba(0,0,0,0.2);
border-radius: 4px;
margin-top: 17px!important;
}
.nContent{
padding:20px 34px;
background-color: #fff;
line-height: 30px;
font-size: 15px;
font-weight: 400;
color: #333;
.realmName{
margin-top: 20px;
display: flex;
ul{
width: 50%;
padding-left: 0px!important;
li{
font-size: 15px;
font-weight: 500;
line-height: 32px;
text-align: left;
color: #000;
list-style-type: none!important;
&:first-child{
color: #E65714;
}
}
}
}
.nSubdesc{
font-size: 15px;
font-weight: 400;
color: #000000;
line-height: 31px;
margin-top: 20px;
}
.nInfo{
font-size: 14px;
font-weight: 400;
color: #333333;
text-align: right;
margin-top: 25px;
p{
height: 20px;
line-height: 20px;
}
}
}
.nBtn{
text-align: center;
margin-top: 33px;
}
}
}
}

View File

@ -1,76 +0,0 @@
import React , { useEffect , useState } from 'react';
import { Modal , Button } from 'antd';
import './Index.scss';
import '../../css/index.scss';
import RenderHtml from '../../../components/render-html';
import cookie from 'react-cookies';
function SystemNotice({system_notification,history}){
const [ visible , setVisible ] = useState(false);
useEffect(()=>{
if(system_notification && !cookie.load('notice_stage')){
setVisible(true);
}
},[system_notification,history.location])
function sureContinue() {
cookie.remove('notice_stage');
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);//
// let inFifteenMinutes = new Date(new Date().getTime() + 60 * 1000);//
cookie.save('notice_stage', true,{ expires: inFifteenMinutes,path:"/" });
setVisible(false);
}
return (
<Modal
visible = {visible}
width="1000px"
footer={false}
title={false}
centered={true}
closable={false}
wrapClassName={'systemBox'}
>
<div className="sysBox">
<div className="sysnoticeBox">
<p className="ntitle">{system_notification && system_notification.subject}</p>
<p className="nSubtitle">{system_notification && system_notification.sub_subject}</p>
{/* <div className="nContent">
<div className="nMaindesc">
为了给用户提供更加稳定优质的服务我们即将对平台门户首页平台名称平台域名进行一次全面升级与变更原平台名称Trustie中文名确实将于2021年10月xx日统一更改为Gitlink中文名确实开源届时平台域名将统一进行更换更换规则如下
</div>
<div className="realmName">
<ul>
<li>原域名</li>
<li>官网顶级域名https://www.trustie.net</li>
<li>版本库子域名https://forgeplus.trustie.net</li>
<li>论坛子域名https://forum.trustie.net/forums</li>
</ul>
<ul>
<li>更换后域名</li>
<li>官网顶级域名https://www.gitlink.org.cn</li>
<li>版本库子域名https://www.git.gitlink.org.cn</li>
<li>论坛子域名https://forum.gitlink.org.cn</li>
</ul>
</div>
<div className="nSubdesc">
自2021年10月xx日起旧域名将停止访问因平台名称与域名变更给您带来的不便我们深表歉意!非常感谢您一直以来对本平台的信任与支持我们将一如既往地为您提供优质的服务 特此通知!
</div>
<div className="nInfo">
<p>Gitlink运营团队</p>
<p>2021年10月xx日</p>
</div>
</div> */}
<RenderHtml className="break_word_comments imageLayerParent" value={system_notification && system_notification.content} url={history.location}/>
<div className="nBtn">
<Button type="primary" className="btnblue" onClick={sureContinue}>确认并继续</Button>
</div>
</div>
</div>
</Modal>
)
}
export default SystemNotice;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

View File

@ -1,72 +0,0 @@
import React , { useEffect , useState } from 'react';
import Modals from '../PublicModal/Index';
import { Button } from 'antd';
import axios from 'axios';
import ProfileImg from './images/profile.png';
import './Index.scss';
function ProfileModal({visible,onCancel,history}) {
const [ modalVis , setModalVis ] = useState(visible);
const [ addMemberCheck , setAddMemberCheck ] = useState(false);
useEffect(()=>{
axios.interceptors.response.use((response) => {
if (response && (response.data.status === 411 || response.data.status === 412)) {
setModalVis(true);
if(response.data.status === 412){
setAddMemberCheck(true);
}
}
return response;
}, (error) => {
});
},[])
useEffect(()=>{
setModalVis(visible);
},[visible])
function onOk(){
onCancel();
setModalVis(false);
setTimeout(function(){
window.open(`/settings/profile`,"_blank");
},200)
}
function onNo() {
onCancel();
setModalVis(false);
}
return(
<Modals
title="完善资料"
onCancel={onNo}
visible={modalVis}
btn={
addMemberCheck?
<div>
<Button type={'primary'} size={"large"} onClick={onNo}>好的</Button>
</div>
:
<div>
<Button size={"large"} onClick={onNo}>暂不补充</Button>
<Button type={'primary'} size={"large"} onClick={onOk}>好的</Button>
</div>
}
>
<div className="contents">
<img src={ProfileImg} alt=""/>
{
addMemberCheck ?
<p>目标用户个人资料不完整需提醒目标用户补充资料后以进行后续操作</p>
:
<p>您目前的个人资料不完整需要补充资料以进行后续操作是否前往补充个人信息</p>
}
</div>
</Modals>
)
}
export default ProfileModal;

View File

@ -1,18 +0,0 @@
.contents{
display: flex;
align-items: center;
justify-content: center;
margin:10px auto 0px;
img{
margin-right: 13px;
width: 44px;
}
p{
line-height: 29px;
max-width: 327px;
font-size: 16px!important;
}
}
.font-44{
font-size: 44px!important;
}

View File

@ -1,17 +0,0 @@
import React from 'react';
function Profile({children,sureFunc,showCompeleteDialog , completeProfile, className}) {
function checkProfile() {
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
sureFunc();
}
}
return(
<a className={className} onClick={checkProfile}>{children}</a>
)
}
export default Profile;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -1,20 +0,0 @@
import React from 'react';
import { Modal } from 'antd';
import './Index.scss';
function Modals({title,children,btn,onCancel,visible}) {
return(
<Modal
visible={visible}
onCancel={onCancel}
title={title}
width={"520px"}
footer={btn}
centered={true}
wrapClassName={"deleteBox"}
>
{children}
</Modal>
)
}
export default Modals;

View File

@ -1,75 +0,0 @@
.deleteBox{
z-index: 1033;
.ant-modal-close-x{
font-size: 17px!important;
}
.ant-modal-header{
background-color: #f8f8f8;
padding:10px 30px;
.ant-modal-title{
text-align: left;
font-size: 16px;
font-weight: bold;
}
}
.ant-modal-close{
top:0px !important;
font-size: 24px !important;
}
.ant-modal-body{
padding:30px 50px;
p{
font-size: 14px;
line-height: 26px;
color:#666;
word-break: break-all;
}
.desc{
.descMain{
align-items: center;
justify-content: center;
font-size: 20px;
margin-bottom: 10px;
i.red{
color:#DF0002;
}
}
}
}
.ant-modal-footer{
border-top: none;
text-align: center;
padding-bottom: 40px;
button,a{
width: 96px;
height: 32px;
margin:0px 20px;
font-weight: 400;
font-size: 14px;
&.ant-btn{
border-color: #D0D0D0;
color: #666;
&:hover,&:active,&:focus{
background: #f3f4f6;
}
}
&.ant-btn-danger{
background-color: #fff;
color: #DF0002;
border-color: #D0D0D0;
&:hover,&:active,&:focus{
border-color: #DF0002;
background-color: #fff;
}
}
&.ant-btn.ant-btn-primary{
background-color: #466AFF;
color: #fff;
border-color: #466AFF;
&:hover,&:focus,&:active{
background-color: rgba(70,106,255,0.85);
}
}
}
}
}

View File

@ -1,35 +1,38 @@
import React from 'react'; import React from 'react';
import { AlignTop } from '../Component/layout'; import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
function Releases({ owner, projectsId, releaseVersions, distribution }) { function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
return( return(
<div> <div>
<Link to={`/${owner}/${projectsId}/releases`} className="font-16 color-ooo hoverA"> <FlexAJ>
<span>发行版</span> <AlignCenter><span className="font-16 color-grey-6">发行版</span>
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>} { releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
</Link> </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 && releaseVersions.total_count>0 ?
releaseVersions.list.map((item,key)=>{ releaseVersions.list.map((item,key)=>{
return( return(
key === 0 &&<AlignTop className="mt10"> key === 0 &&<AlignTop className="mt10">
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
<div> <div>
<p className="font-16 color-grey-6" style={{display:'flex',alignItems:'center'}}> <p className="font-16 color-grey-6">
{/* 如果是点击最新则发行版列表页只展示最新的一个 */} <Link to={`/projects/${owner}/${projectsId}/releases`}>{item.name}</Link>
<Link to={{pathname:`/${owner}/${projectsId}/releases`,query:{turnFromNew:true}}} style={{maxWidth:'200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis'}}>{item.name}</Link>
<span className="font-12 laterest ml5">最新</span> <span className="font-12 laterest ml5">最新</span>
</p> </p>
<p className="color-grey-3 font-12">{item.created_at}</p> <p className="color-grey-9 font-13">{item.created_at}</p>
</div> </div>
</AlignTop> </AlignTop>
) )
}) })
: :""
<div className="mt8">
您暂未发布任何版本
{distribution && <Link className="color-blue ml20" to={{pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}}}>创建新版本</Link>}
</div>
} }
</div> </div>

View File

@ -2,9 +2,9 @@ import React from 'react';
import {Popover} from 'antd'; import {Popover} from 'antd';
import './Component.scss'; import './Component.scss';
export default (({menu , children, overlayClassName})=>{ export default (({menu , children})=>{
return( return(
<Popover content={menu} trigger={['click']} placement='bottom' overlayClassName={overlayClassName}> <Popover content={menu} trigger={['click']} placement='bottom'>
{children} {children}
</Popover> </Popover>
) )

View File

@ -5,7 +5,6 @@ import { Link } from 'react-router-dom';
export default ({ url , name , column , id , login })=>{ export default ({ url , name , column , id , login })=>{
const Img = styled.span` const Img = styled.span`
display:flex; display:flex;
font-weight: bold;
${column && "flex-direction: column;text-align:center;"} ${column && "flex-direction: column;text-align:center;"}
align-items: center; align-items: center;
& img{ & img{
@ -21,7 +20,7 @@ export default ({ url , name , column , id , login })=>{
`; `;
return( return(
id? id?
<Link to={`/${login}`}> <Link to={`/users/${login}`}>
<Img> <Img>
{ url && <img src={url} alt=""/> } { url && <img src={url} alt=""/> }
<span>{name}</span> <span>{name}</span>

View File

@ -149,7 +149,7 @@ function About(props, ref) {
axios.post(url).then(result=>{ axios.post(url).then(result=>{
setIsSpining(false); setIsSpining(false);
if(result && result.data.status === 0){ if(result && result.data.status === 0){
props.history.push(`/${owner}/${projectsId}/devops`); props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
// open_devops // open_devops
let { changeOpenDevops } = props; let { changeOpenDevops } = props;
changeOpenDevops && changeOpenDevops(true); changeOpenDevops && changeOpenDevops(true);

View File

@ -96,7 +96,7 @@ function Dispose(props){
setVisible(false); setVisible(false);
if(result && result.data){ if(result && result.data){
props.showNotification("流水线新增成功,请进行工作流配置!"); props.showNotification("流水线新增成功,请进行工作流配置!");
props.history.push(`/${owner}/${projectsId}/devops/${result.data.id}`); props.history.push(`/projects/${owner}/${projectsId}/devops/dispose/${result.data.id}`);
}else{ }else{
props.showNotification("流水线新增失败,请稍后再试!"); props.showNotification("流水线新增失败,请稍后再试!");
} }
@ -134,12 +134,12 @@ function Dispose(props){
// //
function toModalManage(){ function toModalManage(){
props.history.push(`/${owner}/${projectsId}/devops/mould`); props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
} }
// //
function toparameter(){ function toparameter(){
props.history.push(`/${owner}/${projectsId}/devops/params`); props.history.push(`/projects/${owner}/${projectsId}/devops/params`);
} }
const operate = current_user && (permission && permission !== "Reporter"); const operate = current_user && (permission && permission !== "Reporter");

View File

@ -73,7 +73,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
render:(value,item)=>{ render:(value,item)=>{
let v = turnbar(item.branch); let v = turnbar(item.branch);
return( return(
<Link to={`/${owner}/${projectsId}/tree/${v}/${value}`} className="color-blue">{value}</Link> <Link to={`/projects/${owner}/${projectsId}/tree/${v}/${value}`} className="color-blue">{value}</Link>
) )
} }
}, },
@ -117,7 +117,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
return( return(
<span> <span>
{ operate ? { operate ?
<Link to={`/${owner}/${projectsId}/devops/${item.id}`} className="mr10 color-grey-6"> <Link to={`/projects/${owner}/${projectsId}/devops/dispose/${item.id}`} className="mr10 color-grey-6">
<i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</Link> :"" <i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</Link> :""
} }
{ operate ? { operate ?
@ -125,7 +125,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a> <a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
</Popconfirm>:"" </Popconfirm>:""
} }
<Link to={`/${owner}/${projectsId}/devops/list/${item.branch}`} className="color-grey-6"><i className="iconfont icon-yunhang font-13 mr3"></i>查看运行记录</Link> <Link to={`/projects/${owner}/${projectsId}/devops/list/${item.branch}`} className="color-grey-6"><i className="iconfont icon-yunhang font-13 mr3"></i>查看运行记录</Link>
</span> </span>
) )
} }

View File

@ -51,7 +51,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
}) })
} }
</Select> </Select>
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{setEventValue(e)}}> <Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
{ {
EVENT.map((item,key)=>{ EVENT.map((item,key)=>{
return( return(

View File

@ -36,37 +36,39 @@ export default ((props)=>{
return( return(
<WhiteBack className="opsPanel"> <WhiteBack className="opsPanel">
<Switch {...props}> <Switch {...props}>
<Route path="/projects/:owner/:projectsId/devops/dispose/:disposeId"
<Route path="/:owner/:projectsId/devops/params" render={
(p) => (<New {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/params"
render={ render={
(p) => (<Params {...props} {...p}/>) (p) => (<Params {...props} {...p}/>)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/devops/mould" <Route path="/projects/:owner/:projectsId/devops/mould"
render={ render={
(p) => (<Mould {...props} {...p}/>) (p) => (<Mould {...props} {...p}/>)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/devops/new" <Route path="/projects/:owner/:projectsId/devops/dispose/new"
render={ render={
(p) => (<New {...props} {...p}/>) (p) => (<New {...props} {...p}/>)
} }
></Route> ></Route>
<Route path="/projects/:owner/:projectsId/devops/dispose"
<Route path="/:owner/:projectsId/devops/list/:branch" render={
(p) => (<Dispose {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/list/:branch"
render={ render={
(p) => (<Stucture {...props} {...p}/>) (p) => (<Stucture {...props} {...p}/>)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/devops/:disposeId" <Route path="/projects/:owner/:projectsId/devops"
render={ render={
(p) => (<New {...props} {...p}/>) (p) => (<About {...props} {...p}/>)
}
></Route>
{/* 原本的两种合为一个 */}
<Route path="/:owner/:projectsId/devops"
render={
(p) =>{return( p.location.state.open_devops?<Dispose {...props} {...p}/>:<About {...props} {...p}/>)}
} }
></Route> ></Route>
</Switch> </Switch>

View File

@ -26,7 +26,7 @@ export default ((props)=>{
return( return(
<div className="disposePanel"> <div className="disposePanel">
<Banner> <Banner>
{ permission !=="Reporter" && <Link to={`/${owner}/${props.match.params.projectsId}/devops`}>工作流配置</Link>} { permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
</Banner> </Banner>
<Div> <Div>
<Dispost {...props}/> <Dispost {...props}/>

View File

@ -104,7 +104,7 @@ function Params(props){
<Banner> <Banner>
<FlexAJ> <FlexAJ>
<span className="font-18">工作流 - 参数管理</span> <span className="font-18">工作流 - 参数管理</span>
<Link to={`/${owner}/${projectsId}/devops`} className="font-14 color-grey-9 ml20">返回</Link> <Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9 ml20">返回</Link>
</FlexAJ> </FlexAJ>
</Banner> </Banner>
<Div className="disposeList"> <Div className="disposeList">

View File

@ -126,7 +126,7 @@ function Mould(props){
<div> <div>
<New wrappedComponentRef={(f) => childRef.current = f} ref={childRef} visible={visible} onCancel={()=>setVisible(false)} onOk={onOk}></New> <New wrappedComponentRef={(f) => childRef.current = f} ref={childRef} visible={visible} onCancel={()=>setVisible(false)} onOk={onOk}></New>
<Banner> <Banner>
<FlexAJ><span>工作流 - 模板管理</span><Link to={`/${owner}/${projectsId}/devops`} className="font-14 color-grey-9">返回</Link></FlexAJ> <FlexAJ><span>工作流 - 模板管理</span><Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9">返回</Link></FlexAJ>
</Banner> </Banner>
<Div className="disposeList"> <Div className="disposeList">
<FlexAJ> <FlexAJ>

View File

@ -198,7 +198,7 @@ function Structure(props,ref){
} }
function clickRows(event,e){ function clickRows(event,e){
props.history.push(`/${owner}/${projectsId}/devops/${e.number}/detail`); props.history.push(`/projects/${owner}/${projectsId}/devops/${e.number}/detail`);
} }
const column = [ const column = [
{ {
@ -290,7 +290,7 @@ function Structure(props,ref){
<Banner> <Banner>
<FlexAJ> <FlexAJ>
<span>构建列表</span> <span>构建列表</span>
<Link to={`/${owner}/${projectsId}/devops`} className="font-15 color-grey-9">返回</Link> <Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-15 color-grey-9">返回</Link>
</FlexAJ> </FlexAJ>
</Banner> </Banner>
<Div> <Div>

View File

@ -275,7 +275,7 @@ function disposePipeline(props){
...params ...params
}).then(result=>{ }).then(result=>{
if(result){ if(result){
props.history.push(`/${owner}/${projectsId}/devops`); props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
} }
setLoading(false); setLoading(false);
}).catch(error=>{ }).catch(error=>{

View File

@ -48,7 +48,7 @@ export default (props) => {
axios.post(url).then((result) => { axios.post(url).then((result) => {
if (result && result.data) { if (result && result.data) {
props.showNotification("工作流正在重新构建!"); props.showNotification("工作流正在重新构建!");
props.history.push(`/${owner}/${projectId}/devops/${result.data.number}/detail`); props.history.push(`/projects/${owner}/${projectId}/devops/${result.data.number}/detail`);
} }
}) })
.catch((error) => { .catch((error) => {
@ -87,7 +87,7 @@ export default (props) => {
</AlignCenter> </AlignCenter>
<Link <Link
style={{ color: "#ddd" }} style={{ color: "#ddd" }}
to={`/${owner}/${projectId}/devops`} to={`/projects/${owner}/${projectId}/devops/dispose`}
> >
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出 <i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
</Link> </Link>

View File

@ -24,6 +24,7 @@ function onLayout(term, el) {
entry.target.offsetHeight, entry.target.offsetHeight,
term, term,
); );
console.log('cols, rows', cols, rows);
term.resize(cols, rows); term.resize(cols, rows);
mediator.publish('ssh-xterm-resize', { mediator.publish('ssh-xterm-resize', {
columns: cols, columns: cols,
@ -138,10 +139,12 @@ export default ({ sshConfigData, sid }) => {
}, 1000); }, 1000);
} }
isFirstConnected.current = true; isFirstConnected.current = true;
console.log('event:', event);
const data = Base64.decode(event.data.toString()); const data = Base64.decode(event.data.toString());
let w = term._core._renderService.dimensions.actualCellWidth || 9.5; let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
console.log('data:', data, w, term);
term.write(data); term.write(data);
}; };

View File

@ -41,15 +41,14 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
// //
function onOk(){ function onOk(){
validateFields((error,values)=>{ validateFields((error,values)=>{
console.log(...values);
if(!error){ if(!error){
const url = `/${owner}/${repo}/applied_transfer_projects.json`; const url = `/${owner}/${repo}/applied_transfer_projects.json`;
Axios.post(url,{ Axios.post(url,{
...values ...values
}).then(result=>{ }).then(result=>{
if(result && result.data.id){ if(result){
onSuccess(result.data && result.data.owner); onSuccess(result.data && result.data.owner);
}else{
onSuccess();
} }
}).catch(error=>{}) }).catch(error=>{})
} }
@ -105,7 +104,7 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
</ul> </ul>
: :
<ul className="descUl"> <ul className="descUl">
<li>仓库仅可以转移到您具有管理权限的组织中</li> <li>仓库仅可以转移到您已经加入的组织中不可以转移到未加入的组织中</li>
<li>涉及到仓库改名操作请提前做好仓库备份并且在转移后对本地仓库的remote进行修改</li> <li>涉及到仓库改名操作请提前做好仓库备份并且在转移后对本地仓库的remote进行修改</li>
<li>转移仓库到组织后你和组织创建者/管理员同时拥有对该仓库的管理操作</li> <li>转移仓库到组织后你和组织创建者/管理员同时拥有对该仓库的管理操作</li>
</ul> </ul>

View File

@ -1,7 +1,6 @@
import React, { useState , forwardRef, useEffect } from 'react'; import React, { useState , forwardRef, useEffect } from 'react';
import { Form , Modal , Input , Radio } from 'antd'; import { Form , Modal , Input , Radio } from 'antd';
import Axios from 'axios'; import Axios from 'axios';
import CheckProfile from '../Component/ProfileModal/Profile';
export default Form.create()( export default Form.create()(
forwardRef((props)=>{ forwardRef((props)=>{
@ -78,7 +77,7 @@ export default Form.create()(
</Form.Item> </Form.Item>
</Form> </Form>
</Modal> </Modal>
<CheckProfile {...props} sureFunc={()=>setVisible(true)}>加入项目</CheckProfile> <a onClick={()=>setVisible(true)}>加入项目</a>
</React.Fragment> </React.Fragment>
) )
}) })

View File

@ -1,108 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'antd';
import _ from 'lodash';
import Nodata from '../Nodata';
class PullRefresh extends Component {
constructor(props) {
super(props);
this.state = {
}
this.pullRef = {};
//
this.onScrollList = _.throttle(this.handleScroll, 200, {
leading: false,
trailing: true,
});
}
componentDidMount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.addEventListener('scroll', this.onScrollList);
}
componentWillUnmount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.removeEventListener('scroll', this.onScrollList)
}
handleScroll = () => {
if (this.props.count < this.props.pageSize) return;
if (this.props.type === 1 || this.props.type === 2) return;
const wrap = this.pullRef;
const currentScroll = wrap.scrollTop + wrap.clientHeight
//
if (currentScroll >= (wrap.scrollHeight - 200)) {
this.loadData()
}
}
handleLoadClick = () => {
this.loadData();
}
loadData = () => {
this.props.onPullRefresh()
}
renderLoading() {
switch (this.props.type) {
case 0: //
return <div className='text-center' onClick={this.handleLoadClick}>显示更多</div>
case 1: //
return (
<div className='text-center'>
<Icon type="loading" />
<span className='text-center'>加载中...</span>
</div>
)
case 2: //
return <div className='text-center'>没有更多了</div>
default:
return <div className='text-center'>没有更多了</div>
}
}
render() {
const { className, count, children } = this.props;
return (
<div
className={`pull-refresh-wrap ${className}`}
ref={dom => { this.pullRef = dom }}
>
{children}
{
count < 1 && <Nodata _html="暂无未读消息"/>
}
{/* 大于分页数据才显示loading */}
{/* {this.props.count >= this.props.pageSize ? this.renderLoading() : null} */}
</div>
)
}
}
PullRefresh.propTypes = {
className: PropTypes.string,
children: PropTypes.any,
onPullRefresh: PropTypes.func.isRequired,
type: PropTypes.oneOf([0, 1, 2]),
count: PropTypes.number.isRequired,
pageSize: PropTypes.number.isRequired,
}
export default PullRefresh

View File

@ -19,7 +19,7 @@ function Footer(){
return( return(
<div> <div>
<div style={{height:"543px"}}></div> <div style={{height:"497px"}}></div>
<div className="newFooter edu-txt-center"> <div className="newFooter edu-txt-center">
{value && showhtml(value)} {value && showhtml(value)}
{/* <div className="footerInfos"> {/* <div className="footerInfos">

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import AccountProfile from "../../modules/user/AccountProfile"; import AccountProfile from "../../modules/user/AccountProfile";
import { getImageUrl } from 'educoder' import { getImageUrl } from 'educoder'
import axios from 'axios'; import axios from 'axios';
import { Input , notification , Dropdown ,Popover, Menu,Badge, Button } from 'antd'; import { Input , notification , Dropdown , Menu } from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import LoginDialog from '../../modules/login/LoginDialog'; import LoginDialog from '../../modules/login/LoginDialog';
@ -10,10 +10,8 @@ import HeadSearch from '../Component/HeadSearch';
import AddProjectModal from './AddProjectModal'; import AddProjectModal from './AddProjectModal';
import '../../modules/tpm/TPMIndex.css'; import '../../modules/tpm/TPMIndex.css';
import CheckProfile from '../Component/ProfileModal/Profile';
import './header.scss'; import './header.scss';
import NoticeContent from './NoticeContent';
const $ = window.$ const $ = window.$
// TODO 这部分脚本从公共脚本中直接调用 // TODO 这部分脚本从公共脚本中直接调用
const { Search } = Input; const { Search } = Input;
@ -48,7 +46,6 @@ class NewHeader extends Component {
settings: null, settings: null,
visiblemyss: false, visiblemyss: false,
openSearch:false, openSearch:false,
visible:false, //浮动消息框展示控制
} }
} }
componentDidMount() { componentDidMount() {
@ -94,6 +91,9 @@ class NewHeader extends Component {
this.setState({ this.setState({
user: newProps.user user: newProps.user
}) })
if (newProps.Headertop !== undefined) {
old_url = newProps.Headertop.old_url
}
} }
educoderlogin = () => { educoderlogin = () => {
@ -120,6 +120,7 @@ class NewHeader extends Component {
}) })
}; };
HideAddcoursestypess = (i) => { HideAddcoursestypess = (i) => {
console.log("调用了");
this.setState({ this.setState({
Addcoursestypes: false, Addcoursestypes: false,
mydisplay: true, mydisplay: true,
@ -221,15 +222,6 @@ class NewHeader extends Component {
} }
} }
} }
checkProfile=(url)=>{
const { showCompeleteDialog , completeProfile } = this.props;
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
window.location.href(url);
}
}
addMenu=(list)=>{ addMenu=(list)=>{
return( return(
@ -239,27 +231,21 @@ class NewHeader extends Component {
{ {
list.map((item,key)=>{ list.map((item,key)=>{
return( return(
(item.name !=="加入课堂" && item.name !=="加入开发项目") && (item.name !=="加入课堂" && item.name !=="加入开发项目") && <Menu.Item key={item.name+key}><a href={item.url}>{item.name}</a></Menu.Item>
<Menu.Item key={item.name+key}>
<CheckProfile {...this.props} sureFunc={()=>{window.location.href=item.url}}>{item.name}</CheckProfile>
</Menu.Item>
) )
}) })
} }
<Menu.Item> <Menu.Item><AddProjectModal showNotification={this.props.showNotification}/></Menu.Item>
<AddProjectModal {...this.props} showNotification={this.props.showNotification}/>
</Menu.Item>
</Menu> </Menu>
</div> </div>
) )
} }
renderMenu=(personal)=>{ renderMenu=(personal)=>{
const { current_user } = this.props; const { current_user } = this.props;
return( return(
<Menu className="currentMenu"> <Menu className="currentMenu">
<Menu.Item> <Menu.Item>
<span className="currentName" title={current_user && current_user.username}>{current_user && current_user.username}</span> <span title={current_user && current_user.username}>{current_user && current_user.username}</span>
</Menu.Item> </Menu.Item>
{ {
personal && personal.length > 0 && personal.map((item,key)=>{ personal && personal.length > 0 && personal.map((item,key)=>{
@ -268,18 +254,14 @@ class NewHeader extends Component {
) )
}) })
} }
{/* <li><Link to={`/settings/profile`}>设置</Link></li> */} <li><Link to={`/settings/SSH`}>设置</Link></li>
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item> <Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
</Menu> </Menu>
) )
} }
handleVisibleChange = visible => {
this.setState({ visible });
};
render() { render() {
const { match ,resetUserInfo ,showNotification} = this.props; const { match} = this.props;
let current_user = this.props.user; let current_user = this.props.user;
let { let {
AccountProfiletype, AccountProfiletype,
@ -288,7 +270,6 @@ class NewHeader extends Component {
headtypesonClickbool, headtypesonClickbool,
headtypess, headtypess,
settings, settings,
visible,
} = this.state; } = this.state;
/*用户名称 用户头像url*/ /*用户名称 用户头像url*/
let activeIndex = false; let activeIndex = false;
@ -366,7 +347,8 @@ class NewHeader extends Component {
}) })
} }
let search_url = settings && settings.common && settings.common.search; // let search_url = settings && settings.common && settings.common.search;
let notice_url = settings && settings.common && settings.common.notice;
return ( return (
<div className="newHeaders" id="nHeader"> <div className="newHeaders" id="nHeader">
<div className="headerContent"> <div className="headerContent">
@ -398,21 +380,21 @@ class NewHeader extends Component {
{ {
settings.navbar && settings.navbar.map((item, key) => { settings.navbar && settings.navbar.map((item, key) => {
var new_link = item.link; var new_link = item.link;
var user_login = current_user && current_user.login; var user_login = this.props.user && this.props.user.login;
var is_hidden = item.hidden var is_hidden = item.hidden
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) { if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
if (user_login) { if (user_login) {
if (new_link.indexOf("courses") > -1) { if (new_link.indexOf("courses") > -1) {
new_link = new_link.replace(/courses/g, user_login + "/courses") new_link = new_link.replace(/courses/g, "users/" + user_login + "/courses")
} else if (new_link.indexOf("contests") > -1) { } else if (new_link.indexOf("contests") > -1) {
new_link = new_link.replace(/contests/g, user_login + "/contests") new_link = new_link.replace(/contests/g, "users/" + user_login + "/contests")
} }
} else { } else {
is_hidden = true is_hidden = true
} }
} }
if (user_login && (new_link && new_link.indexOf("homes") > -1)) { if (user_login && (new_link && new_link.indexOf("homes") > -1)) {
new_link = new_link.replace(/homes/g, user_login + "/user_activities") 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 waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
@ -429,30 +411,25 @@ class NewHeader extends Component {
} }
</div> </div>
<div className="head-right"> <div className="head-right">
{ search_url && <HeadSearch {...this.props}/>} {/* {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)? 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"> <Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
<i className="iconfont icon-tianjiafangda color-grey-6 ml30 mr15"></i> <i className="iconfont icon-tianjiafangda color-grey-6 ml30"></i>
</Dropdown>:"" </Dropdown>:""
} }
{ (settings && settings.common && settings.common.notice) && (current_user && current_user.login)? {this.props.user && this.props.user.login && notice_url ?
<Popover <div className="ml30 edu-menu-panel">
overlayClassName="notice-popover" {user && user.login &&
placement={`bottomRight`} <a href={`${notice_url}`} style={{ position: 'relative' }}>
content={<NoticeContent visible={visible} current_user={current_user} showNotification={showNotification} resetUserInfo={resetUserInfo}/>} <i className="iconfont icon-xiaoxilingdang color-grey-6"></i>
visible={visible} <span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
onVisibleChange={this.handleVisibleChange} </span>
destroyTooltipOnHide </a>
> }
<Link to={"/settings/notice"} className="message-icon"> </div>:""
{current_user && <Badge count={current_user.message_unread_total}>
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
</Badge>}
</Link>
</Popover>
: ""
} }
</div> </div>
{!user || (user && !user.login) ? {!user || (user && !user.login) ?
@ -465,7 +442,7 @@ class NewHeader extends Component {
</span> </span>
: :
<Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}> <Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}>
<a href={`/${this.props.current_user && this.props.current_user.login}`}> <a href={`/users/${this.props.current_user && this.props.current_user.login}`}>
<img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img> <img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img>
</a> </a>
</Dropdown> </Dropdown>

View File

@ -1,262 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Badge, Menu } from 'antd';
import { Link } from 'react-router-dom';
import axios from 'axios';
import AppPullRefresh from './AppPullRefresh';
import { noticeSourceType } from '../common/static';
import './header.scss';
import '../SecuritySetting/notice/manager/Index.scss';
import '../SecuritySetting/Index.scss';
import '../SecuritySetting/notice/myNotice/Index.scss';
function NoticeContent({ visible, showNotification, resetUserInfo, current_user: { login } }) {
const [initialize, setInitialize] = useState(true);
const [noticeType, setNoticeType] = useState("notification");
const [letterUnreadCount, setLetterUnreadCount] = useState(0);//
const [noticeUnreadCount, setNoticeUnreadCount] = useState(0);//
const [noticePage, setNoticePage] = useState(0);
const [noticeUnreadList, setNoticeUnreadList] = useState([]);//
const [atUnreadCount, setAtUnreadCount] = useState();//@
const [atPage, setAtPage] = useState(0);
const [atUnreadList, setAtUnreadList] = useState([]);//@
useEffect(() => {
resetUserInfo();
}, [noticeUnreadCount,atUnreadCount]);
useEffect(()=>{
setNoticePage(0);
setAtPage(0);
},[visible])
useEffect(() => {
const params = {
type: noticeType,
limit: 10,
page: noticeType === "notification" ? noticePage : noticeType === "atme" ? atPage : "",
status: 1,
}
getMessageList(params);
}, [noticePage, atPage]);
useEffect(() => {
const params = {
type: noticeType,
limit: 10,
page: 0,
status: 1,
};
if (initialize) {
params.type = "atme"
}
visible && getMessageList(params);
}, [visible]);
function getMessageList(params) {
axios.get(`/users/${login}/messages.json`, {
params: params,
}).then((response) => {
if (response && response.data) {
setNoticeUnreadCount(response.data.unread_notification);
setAtUnreadCount(response.data.unread_atme);
if (params.type === "notification") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...noticeUnreadList, ...list];
}
setNoticeUnreadList(list);
if (initialize) {
// tab
setInitialize(false);
if (response.data.unread_notification === 0 && response.data.unread_atme !== 0) {
setNoticeType("atme");
}
}
} else if (params.type === "atme") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...atUnreadList, ...list];
}
setAtUnreadList(list);
}
}
})
}
function readAll() {
axios.post(`/users/${login}/messages/read.json`, {
type: noticeType,
ids: [-1]
}).then((response) => {
let data = response.data;
if (!data) return;
if (data.status === 0) {
changeReadMarkAll(noticeType);
} else {
showNotification(data.message);
}
});
}
function changeReadMarkAll(noticeType) {
if (noticeType === "notification") {
let list = noticeUnreadList.slice();
list.forEach(item => {
item.status = 2;
})
setNoticeUnreadList(list);
setNoticeUnreadCount(0);
} else if (noticeType === "atme") {
let list = atUnreadList.slice();
list.forEach(item => {
item.status = 2;
})
setAtUnreadList(list);
setAtUnreadCount(0);
}
}
// const [letter_unread_list, setLetter_unread_list] = useState([
// {
// id: 122,
// read: 0, //01
// send_name: "", //
// send_login: "jiangYuHang", //login
// content: "", //
// create_time: "2019-03-04 18:08", //
// },
// ]);
function readItem(item) {
axios.post(`/users/${login}/messages/read.json`, {
type: noticeType,
ids: [item.id]
}).then((response) => {
let data = response.data;
if (!data) return;
if (data.status === 0) {
changeReadMark(item);
item.notification_url && window.open(item.notification_url);
} else {
showNotification(data.message);
}
});
}
function changeReadMark(item) {
if (item.type === "notification") {
let list = noticeUnreadList.slice();
let index = noticeUnreadList.indexOf(item);
list[index].status = 2;
setNoticeUnreadList(list);
if (noticeUnreadCount > 0) {
setNoticeUnreadCount(noticeUnreadCount - 1);
}
} else if (item.type === "atme") {
let list = atUnreadList.slice();
let index = atUnreadList.indexOf(item);
list[index].status = 2;
setAtUnreadList(list);
if (atUnreadCount > 0) {
setAtUnreadCount(atUnreadCount - 1);
}
}
}
return (
<div className="messageHoverDiv notice01">
<div className="sshHead hoverNotice-head">
<Menu mode="horizontal" selectedKeys={noticeType} onClick={(e) => setNoticeType(e.key)}>
<Menu.Item key="notification"><Badge count={noticeUnreadCount}>系统通知</Badge></Menu.Item>
{/* <Menu.Item key="1" id="item-private"><Badge count={letterUnreadCount}>私信</Badge></Menu.Item> */}
<Menu.Item key="atme"><Badge count={atUnreadCount}>@</Badge></Menu.Item>
</Menu>
</div>
{/* 系统通知 */}
{noticeType === "notification" && <AppPullRefresh
className='hoverNotice-body' // className
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //ajaxfunction
// type={2} //
count={noticeUnreadList.length} //
pageSize={10} //
>
{
noticeUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className={`noticeCont ${item.notification_url?'pointer':''}`}>
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" />
</span>
<i className={"iconfont " + noticeSourceType[item.source]}></i>
<div className="noticeCont-text">
<span className="content-span notice-cont-span" dangerouslySetInnerHTML={{ __html: item.content }}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
})
}
</AppPullRefresh>
}
{/* @我 */}
{noticeType === "atme" && <AppPullRefresh
className='hoverNotice-body' // className
onPullRefresh={() => { setAtPage(atPage + 1); }} //ajaxfunction
// type={1} //
count={atUnreadList.length} //
pageSize={10} //
>
{atUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className="noticeCont">
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" />
</span>
<div className="noticeCont-text">
<span className="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: "<b>" + (item.sender ? item.sender.name : '') + "</b>&nbsp;&nbsp;&nbsp;" + item.content + " 中@我" }}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
})
}
</AppPullRefresh>
}
{/* 私信 */}
{/* {noticeType === "1" ? letter_unread_list.length > 0 ? letter_unread_list.map(item => {
return (
<div className="noticeCont-back">
<div className="noticeCont" style={{ height: item.content.length >= 30 && item.content.length <= 34 ? '65px' : "" }}>
<Badge color="#FA2020" />
<div className="noticeCont-text">
<span>{item.send_name}</span>
<span className="boldSpan" dangerouslySetInnerHTML={{ __html: item.content.length >= 50 ? item.content.substr(0, 50) + "..." : item.content }}></span>
<span className="timeSpan">{item.create_time ? timeAgo(item.create_time) : "刚刚"}</span>
</div>
</div>
</div>
)
}) : "暂无数据" : ""} */}
<div className="hoverNotice-buttom">
<Link to={{pathname:"/settings/notice",query:{noticeType:noticeType}}}>全部消息</Link>
{noticeUnreadCount > 0 && noticeType === "notification" && <a onClick={readAll}>所有系统消息一键已读</a>}
{atUnreadCount > 0 && noticeType === "atme" && <a onClick={readAll}>所有@我一键已读</a>}
</div>
</div>
)
}
export default NoticeContent;

View File

@ -24,20 +24,12 @@
width: 34px; width: 34px;
height: 34px; height: 34px;
border-radius: 50%; border-radius: 50%;
margin-left: 15px; margin-left: 30px;
} }
.currentMenu{ .currentMenu{
width: 120px; width: 120px;
text-align: center; text-align: center;
padding:0px; padding:0px;
.currentName{
padding:0px 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
}
li{ li{
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
@ -127,139 +119,4 @@
width: 110px; width: 110px;
text-align: right; text-align: right;
} }
}
// 右上角小铃铛单独样式
.notice-popover{
//popover小尖尖
.ant-popover-arrow{
display: none;
}
//popover框
.ant-popover-inner-content {
width: 386px;
height: 446px;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
margin-top: -10px;
padding: 12px 1px 12px 0;
}
}
.messageHoverDiv .ant-menu-item{
margin-right: 24px !important;
}
.hoverNotice-head{
margin-left: 18px;
& .ant-badge{
font-size: 14px !important;
}
&>.ant-menu-horizontal {
border-bottom: 1px solid #e8e8e8 !important;
}
}
.hoverNotice-body{
height: 342px;
overflow-y: scroll;
& b{
font-weight: 400;
text-shadow: 0.5px 0 0 #333;
}
.none_panels{
height: 100%;
}
}
.message-icon{
position: relative;
.ant-scroll-number{
right:12px;
padding: 0 0px;
}
}
.hoverNotice-buttom{
display: flex;
justify-content: space-between;
padding: 12px 18px;
a{
color: #466AFF;
&:hover{
opacity:0.85;
}
}
}
.noticeCont-back{
.pointer{
cursor: pointer;
}
&:hover{
background: #F3F4F6;
}
}
.noticeCont{
display: flex;
margin: 0 16px 0 18px;
padding: 12px 0 10px 0;
line-height: 24px;
border-bottom: 1px solid #EEEEEE;
cursor: default;
i{
font-size: 14px !important;
margin-right: 6px;
color: #333333;
}
.boldSpan{
font-weight: 400;
text-shadow: 0.5px 0 0 #333;
}
.noticeCont-text{
display: flex;
color:#333333;
flex:auto;
justify-content: space-between;
& .content-span{
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
& .atme-cont-span{
width: 272px;
}
& .notice-cont-span{
width: 255px;
}
.timeSpan{
font-size: 12px;
color: #666666;
}
.at-name{
margin-right: 12px;
}
}
}
.text-center{
text-align: center;
} }

View File

@ -12,9 +12,8 @@ import Loadable from "react-loadable";
import Loading from "../Loading"; import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC"; import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
const ProjectNew = Loadable({ const ProjectNew = Loadable({
loader: () => import("./New/Index"), loader: () => import("./New/Index"),
loading: Loading, loading: Loading,
}); });
const ProjectIndex = Loadable({ const ProjectIndex = Loadable({
@ -22,23 +21,21 @@ const ProjectIndex = Loadable({
loading: Loading, loading: Loading,
}); });
// 项目详情放在用户和组织下作为二级菜单存在 const ProjectDetail = Loadable({
// const ProjectDetail = Loadable({ loader: () => import("./Main/Detail"),
// loader: () => import("./Main/Detail"), loading: Loading,
// loading: Loading, });
// });
class Index extends Component { class Index extends Component {
componentDidUpdate = () => { componentDidUpdate=()=>{
this.props.history.listen(() => { this.props.history.listen(()=>{
if (document.body.scrollTop || document.documentElement.scrollTop > 0) { if (document.body.scrollTop || document.documentElement.scrollTop > 0) {
window.scrollTo(0, 0) window.scrollTo(0, 0)
} }
}) })
} }
render() { render() {
return ( return (
<div className="newMain clearfix"> <div className="newMain clearfix">
<Switch {...this.props}> <Switch {...this.props}>
@ -55,24 +52,23 @@ class Index extends Component {
)} )}
></Route> ></Route>
<Route <Route
path="/projects/mirror/new" path="/projects/new"
render={(props) => ( render={(props) => (
<ProjectNew {...this.props} {...props} /> <ProjectNew {...this.props} {...props} />
)} )}
></Route> ></Route>
{/* <Route <Route
path="/:owner/:projectsId" path="/projects/:owner/:projectsId"
render={(props) => ( render={(props) => (
<ProjectDetail {...this.props} {...props} /> <ProjectDetail {...this.props} {...props} />
)} )}
></Route> */} ></Route>
<Route <Route
path="/explore" path="/projects"
render={(props) => ( render={(props) => (
<ProjectIndex {...this.props} {...props} /> <ProjectIndex {...this.props} {...props} />
)} )}
></Route> ></Route>
<Route <Route
path="/" path="/"
render={(props) => ( render={(props) => (
@ -90,10 +86,3 @@ export default withRouter(
parentSelector: ".newMain", parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index)))) })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
); );
// export default withRouter(
// ImageLayerOfCommentHOC({
// imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
// parentSelector: ".newMain",
// })(Index)
// );

View File

@ -1,9 +1,8 @@
import React , { useEffect , useState } from 'react'; import React , { useEffect , useState } from 'react';
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout'; import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
import { Dropdown , Menu , Divider , Spin, Button , Typography } from 'antd'; import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
import { getImageUrl } from "educoder"; import { getImageUrl } from "educoder";
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { truncateCommitId } from "../common/util";
import CloneAddress from '../Branch/CloneAddress'; import CloneAddress from '../Branch/CloneAddress';
import SelectBranch from '../Branch/Select'; import SelectBranch from '../Branch/Select';
@ -21,13 +20,10 @@ import DrawerPanel from '../Component/DrawerPanel';
import UpdateDescModal from './sub/UpdateDescModal'; import UpdateDescModal from './sub/UpdateDescModal';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import Invite from './sub/Invite'; import Invite from './sub/Invite';
import CheckProfile from '../Component/ProfileModal/Profile';
import RenderHtml from '../../components/render-html';
import Badge from "./sub/Badge";
/** /**
* projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能) * projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能)
*/ */
const { Paragraph } = Typography;
function turnbar(str){ function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){ if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F'); return str.replaceAll('/','%2F');
@ -69,7 +65,6 @@ function CoderDepot(props){
const [ editReadme , setEditReadme ] = useState(false); const [ editReadme , setEditReadme ] = useState(false);
const [ pullsFlag , setPullsFlag ] = useState(true); const [ pullsFlag , setPullsFlag ] = useState(true);
const [ issuesFlag , setIssuesFlag ] = useState(true); const [ issuesFlag , setIssuesFlag ] = useState(true);
const [ releaseVersions , setReleaseVersions] = useState(undefined);
const owner = props.match.params.owner; const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId; const projectsId = props.match.params.projectsId;
@ -77,16 +72,9 @@ function CoderDepot(props){
branchName = returnbar(branchName); branchName = returnbar(branchName);
const details = props.projectDetail; const details = props.projectDetail;
let pathname = props.history.location.pathname; let pathname = props.history.location.pathname;
//distribution
const distribution = details && details.type != 2 && (details.permission === "Admin" || details.permission === "Owner" || details.permission === "Manager");
const { bannerList } = props; const { bannerList } = props;
// test data
const badges = {badge:[{ "login": "many_stars", "image_url": "https://www.gitlink.org.cn/system/lets/letter_avatars/2/J/236_194_58/120.png", "description": "test description1"}, {"login": "many_stars", "image_url": "https://www.gitlink.org.cn/system/lets/letter_avatars/2/X/181_166_38/120.png", "description": "test description2"}], total_count: 3}
console.log(badges.badge)
console.log(badges.total_count)
useEffect(()=>{ useEffect(()=>{
if(bannerList && bannerList.length>0){ if(bannerList && bannerList.length>0){
let a = bannerList.filter(i=>i.menu_name === "pulls"); let a = bannerList.filter(i=>i.menu_name === "pulls");
@ -124,52 +112,19 @@ function CoderDepot(props){
useEffect(()=>{ useEffect(()=>{
if (projectsId && owner && defaultBranch){ if (projectsId && owner && defaultBranch){
let b = turnbar(branchName) ; let b = turnbar(branchName) ;
if(pathname.indexOf(`/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) { if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
let url = pathname.split(`/tree/${b}/`)[1]; let url = pathname.split(`/tree/${b}/`)[1];
setTreeValue(url); setTreeValue(url);
getFileInfo(url,branchName); getFileInfo(url,branchName);
setType("file"); setType("file");
// getReadmeInfo(url,branchName);
// setReadme(undefined);
}else{ }else{
setTreeValue(undefined); setTreeValue(undefined);
getDirInfo(branchName || defaultBranch); getDirInfo(branchName || defaultBranch);
setType("dir"); setType("dir");
// getReadmeInfo('', branchName || defaultBranch);
} }
} }
},[projectsId,owner,pathname,defaultBranch]) },[projectsId,owner,pathname,defaultBranch])
useEffect(()=>{
axios.get(`/${owner}/${projectsId}/releases.json`).then((result)=>{
if(result && result.data){
const release = {
"list":result.data.releases,
"total_count":result.data.releases.length
}
setReleaseVersions(release);
}
})
},[])
// readme
function getReadmeInfo(path, ref) {
axios.get(`/${owner}/${projectsId}/readme.json`, {
params:{
owner: owner,
repo: projectsId,
filepath:path,
ref:ref || branchName
}
}).then((result) => {
if (result) {
setReadme(result.data);
} else {
setReadme(undefined);
}
})
}
// //
function getDirInfo(branch){ function getDirInfo(branch){
setIsSpin(true); setIsSpin(true);
@ -189,10 +144,9 @@ function CoderDepot(props){
setLastCommitAuthor(c && c.committer); setLastCommitAuthor(c && c.committer);
setMainFlag(true); setMainFlag(true);
setReadOnly(true); setReadOnly(true);
// setReadme(result.data.readme); setReadme(result.data.readme);
setEditReadme(false); setEditReadme(false);
setHide(true); setHide(true);
getReadmeInfo('', branchName || defaultBranch);
} }
setTimeout(function(){setIsSpin(false);},500); setTimeout(function(){setIsSpin(false);},500);
}).catch(error=>{setIsSpin(false);}) }).catch(error=>{setIsSpin(false);})
@ -204,7 +158,7 @@ function CoderDepot(props){
let ele = document.getElementById("ptxt"); let ele = document.getElementById("ptxt");
if(ele){ if(ele){
let h = ele.offsetHeight; let h = ele.offsetHeight;
if( h > 35 ) setHideBtn(true); if( h > 18 ) setHideBtn(true);
} }
} }
},[projectDetail,lastCommit]) },[projectDetail,lastCommit])
@ -225,18 +179,15 @@ function CoderDepot(props){
setDirInfo(undefined); setDirInfo(undefined);
setFileInfo(en); setFileInfo(en);
setType(en.type); setType(en.type);
setReadme(undefined);
}else{ }else{
setFileInfo(undefined); setFileInfo(undefined);
setDirInfo(en); setDirInfo(en);
setType("dir"); setType("dir");
getReadmeInfo(path, branchName || defaultBranch);
} }
let c = result.data.last_commit let c = result.data.last_commit
setLastCommit(c && c.commit); setLastCommit(c && c.commit);
setLastCommitAuthor(c && c.committer); setLastCommitAuthor(c && c.committer);
setMainFlag(false); setMainFlag(false);
setReadOnly(true);
setReadOnly(!editReadme); setReadOnly(!editReadme);
setHide(true); setHide(true);
} }
@ -247,7 +198,7 @@ function CoderDepot(props){
// //
function changeBranch(value){ function changeBranch(value){
let checkvalue = turnbar(value); let checkvalue = turnbar(value);
let url = `/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}`:""}`; let url = `/projects/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}`:""}`;
props.history.push(url); props.history.push(url);
} }
@ -256,13 +207,9 @@ function CoderDepot(props){
let b = branchName || defaultBranch; let b = branchName || defaultBranch;
let checkvalue = turnbar(b); let checkvalue = turnbar(b);
return ( return (
<Menu className="fileMenu"> <Menu>
<Menu.Item> <Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</CheckProfile> <Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
</Menu.Item>
<Menu.Item>
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</CheckProfile>
</Menu.Item>
</Menu> </Menu>
) )
} }
@ -281,12 +228,12 @@ function CoderDepot(props){
setTreeValue(undefined); setTreeValue(undefined);
let branch = branchName || defaultBranch; let branch = branchName || defaultBranch;
let checkvalue = turnbar(branch); let checkvalue = turnbar(branch);
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}`); props.history.push(`/projects/${owner}/${projectsId}/tree/${checkvalue}`);
}; };
// //
function returnUlr(url){ function returnUlr(url){
let enBranch = turnbar(branchName); let enBranch = turnbar(branchName);
props.history.push(`/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`); props.history.push(`/projects/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`);
} }
// //
function goToSubRoot(path,type,filename){ function goToSubRoot(path,type,filename){
@ -294,7 +241,7 @@ function CoderDepot(props){
let enBranch = branchName || defaultBranch; let enBranch = branchName || defaultBranch;
let checkvalue = turnbar(enBranch); let checkvalue = turnbar(enBranch);
setType(type); setType(type);
props.history.push(`/${owner}/${projectsId}${`/tree/${checkvalue}`}${path?`/${path}`:""}`); props.history.push(`/projects/${owner}/${projectsId}${`/tree/${checkvalue}`}${path?`/${path}`:""}`);
} }
} }
@ -306,7 +253,7 @@ function CoderDepot(props){
// //
let enBranch = branchName || defaultBranch; let enBranch = branchName || defaultBranch;
let checkvalue = turnbar(enBranch); let checkvalue = turnbar(enBranch);
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}/${path}`); props.history.push(`/projects/${owner}/${projectsId}/tree/${checkvalue}/${path}`);
setType("file"); setType("file");
setEditReadme(true); setEditReadme(true);
}; };
@ -348,12 +295,9 @@ function CoderDepot(props){
const mdFlag = n && n.substring(n.length-3,n.length) === ".md"; const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
const { current_user } = props; const { current_user } = props;
const baseOper = current_user && current_user.login && issuesFlag; const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter";
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type !== 2 && pullsFlag;
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin)); const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
return( return(
<WhiteBack> <WhiteBack>
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/> <UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
@ -371,21 +315,20 @@ function CoderDepot(props){
list = {mainFlag ? dirInfo : undefined} list = {mainFlag ? dirInfo : undefined}
/> />
<div className="drawerBtn" onClick={()=>setVisible(true)}> <div className="drawerBtn" onClick={()=>setVisible(true)}>
<i className="iconfont icon-zuohuaicon font-14"></i> <i className="iconfont icon-youjiantou font-16"></i>
<span>目录</span> <span>目录</span>
</div> </div>
</React.Fragment> </React.Fragment>
} }
<div style={{minHeight:"500px"}}> <div style={{minHeight:"500px"}}>
{ {
projectDetail && projectDetail &&
<Box className="Panels"> <Box className="Panels">
<LongWidth> <LongWidth>
<div className="panelmenu"> <div className="panelmenu">
<FlexAJ> <FlexAJ>
<AlignCenter> <AlignCenter>
<div className="mr30"> <div className="mr20">
{ {
props && props.platform ? props && props.platform ?
<SelectBranch <SelectBranch
@ -398,89 +341,76 @@ function CoderDepot(props){
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list} branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
></SelectBranch> ></SelectBranch>
: :
<span>分支<span className="color-grey-6">{branchName || defaultBranch}</span></span> <span>分支<span className="color-grey-6">{branchName || defaultBranch}</span></span>
} }
</div> </div>
{ <AlignCenter className="mr20">
treeValuePath && treeValuePath.length > 0 ? <Link to={`/projects/${owner}/${projectsId}/branchs`} className="color-grey-9">
<Path <i className="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>
identifier={projectDetail && projectDetail.identifier} <span className="color-grey-6 mr3">{projectDetail && projectDetail.branches && projectDetail.branches.total_count}</span>分支
treeValuePath={treeValuePath} </Link>
returnUlr={returnUlr} </AlignCenter>
returnMain={returnMain} <AlignCenter className="mr20">
getPathUrl={getPathUrl} <Link to={`/projects/${owner}/${projectsId}/tag`} className="color-grey-9">
/> <i className="iconfont icon-biaoqian3 font-16 color-grey-9 mr3"></i>
: <span className="color-grey-6 mr3">{projectDetail && projectDetail.tags && projectDetail.tags.total_count}</span>标签
<React.Fragment> </Link>
<AlignCenter className="mr20"> </AlignCenter>
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
<i className="iconfont icon-master_icon font-16"></i>
<span>分支</span>
<span>{projectDetail && projectDetail.branches_count}</span>
</Link>
</AlignCenter>
<AlignCenter className="mr20">
<Link to={`/${owner}/${projectsId}/tags`} className="iconBtn">
<i className="iconfont icon-biaoqianicon font-16"></i>
<span>标签</span>
<span>{projectDetail && projectDetail.tags_count}</span>
</Link>
</AlignCenter>
</React.Fragment>
}
</AlignCenter> </AlignCenter>
<AlignCenter className="depotBtn"> <AlignCenter>
{ {
(baseOperate || baseOper) && baseOperate && ((projectDetail.type !== 2 && pullsFlag) || issuesFlag )&&
<div className="addOptionBtn"> <div className="mr20 addOptionBtn">
{ {
baseOperate && projectDetail.type !== 2 && pullsFlag &&
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/compare/master...${branchName || defaultBranch}`)} >+ 合并请求</CheckProfile> <a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
} }
{ {
baseOper && issuesFlag &&
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 易修</CheckProfile> <a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
} }
</div> </div>
} }
{ fileOperate && { fileOperate &&
<Dropdown <Dropdown overlay={fileMenu()} className="mr20" trigger={['click']}>
overlay={fileMenu()} <Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
className="mr10"
trigger={['click']}
getPopupContainer={document.parentNode}
>
<a>文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-6 mr-5"></i></a>
</Dropdown> </Dropdown>
} }
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}> <Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white mr-3"></i></Button> <Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
</Dropdown> </Dropdown>
</AlignCenter> </AlignCenter>
</FlexAJ> </FlexAJ>
{ {
(dirInfo && dirInfo.length>0) || fileInfo ? dirInfo || fileInfo ?
<div className="listtable"> <div className="listtable">
{ {
lastCommit && lastCommit &&
<div className="listtablehead"> <div className="listtablehead">
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/> <User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}> <div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}><RenderHtml value={lastCommit.message}/></Link></pre> <pre id="ptxt">{lastCommit && lastCommit.message}</pre>
</div> </div>
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> } { hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
<span className="ml20 color-grey-6 font-12 mt3">{lastCommit.time_from_now}</span> <span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
{ { commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml12 color-grey-9">
commitCount ? <i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交
<Link to={`/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml20 color-grey-3"style={{height:"28px",lineHeight:"28px"}}> </Link>:"" }
<i className="iconfont icon-tijiaoicon mr3 font-16"></i><span style={{fontWeight:"500"}}>{commitCount}次提交</span>
</Link>:""
}
</div> </div>
} }
<ul className="listtablebody"> <ul className="listtablebody">
{
treeValuePath && treeValuePath.length > 0 &&
<Path
identifier={projectDetail && projectDetail.identifier}
treeValuePath={treeValuePath}
returnUlr={returnUlr}
returnMain={returnMain}
getPathUrl={getPathUrl}
/>
}
{ {
dirInfo && dirInfo.length > 0 && dirInfo && dirInfo.length > 0 &&
dirInfo.map((item,key)=>{ dirInfo.map((item,key)=>{
@ -511,93 +441,78 @@ function CoderDepot(props){
: "" : ""
} }
{ {
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :"" (dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
} }
{/* readme文件显示(显示文件详情时不显示readme文件) */} {/* readme文件显示(显示文件详情时不显示readme文件) */}
{ (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" } { dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
</div> </div>
</LongWidth> </LongWidth>
{ {
(!(treeValuePath && treeValuePath.length > 0) && !fileInfo) && !fileInfo &&
<ShortWidth> <ShortWidth>
<Gap style={{paddingLeft:"30px"}}> <Gap style={{paddingLeft:"30px"}}>
<div className="panelmenu"> <div className="panelmenu">
<FlexAJ className="font-18 color-ooo mb20" style={{lineHeight:"28px"}}>关于 <FlexAJ className="font-18 color-grey-6 mb20" style={{lineHeight:"28px"}}>简介
{ {projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner") && <i onClick={()=>setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>}
projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner" || projectDetail.permission==="Manager") &&
<i onClick={()=>setOpenModal(true)} className="iconfont icon-a-shezhi color-grey-9 font-15"></i>
}
</FlexAJ> </FlexAJ>
{desc && <p className="font-14 color-grey-3 mb15 task-hide-2" style={{lineHeight:"24px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>} {desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
{ {
website && website &&
<div className="color-grey-6 df pinfos mb5"> <p className="color-grey-6 df">
<i className="iconfont icon-lianjie2 font-15 mr10"></i> <i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i>
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a> <a href={website} className="color-grey-6" target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
</div> </p>
} }
<div className="pinfos mb5"> <p>
<i className="iconfont icon-zishuwenjian_icon font-15 mr10"></i> <i className="iconfont icon-wenjian4 font-15 mr10 color-grey-9"></i>
<a href="#readme">README.md</a> <a href="#readme" className="color-grey-6">README.md</a>
</div> </p>
<div className="color-grey-6 mb5"> <p className="color-grey-6">
<i className="iconfont icon-neicunicon font-15 mr10"></i> <i className="iconfont icon-dataBase font-15 mr10 color-grey-6"></i>
<span>{projectDetail && projectDetail.size}</span> <span>{projectDetail && projectDetail.size}</span>
</div> </p>
{ {
projectDetail && projectDetail.license_name && projectDetail && projectDetail.license_name &&
<div className="pinfos"> <p className="color-grey-6">
<i className="iconfont icon-xieyiicon font-16 mr10"></i> <i className="iconfont icon-tianping font-16 mr10 color-grey-3"></i>
<Link to={`/${owner}/${projectsId}/tree/${branchName || defaultBranch}/LICENSE`} className="color-grey-6">{projectDetail.license_name}</Link> <span>{projectDetail.license_name}</span>
</div> </p>
} }
</div> </div>
{ {
inviteCode && inviteCode &&
<div> <div>
<Divider /> <Divider />
<Invite code={inviteCode}/> <Invite code={inviteCode} className={"detailsCode"}/>
</div> </div>
} }
{/*{*/}
{/* inviteCode &&*/}
{/* <div>*/}
{/* <Badge code={inviteCode}/>*/}
{/* </div>*/}
{/*}*/}
{/* 徽章 */}
{
badges && badges.total_count >0 &&
<Badge badges={badges} owner={owner} />
}
{ {
lesson_url && lesson_url &&
<div> <div>
<Divider /> <Divider />
<p className="font-16 color-ooo">实践课程</p> <p className="font-16 color-grey-6">实践课程</p>
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a> <a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
</div> </div>
} }
{/* 发布 */} {/* 发布 */}
{ {
releaseVersions && projectDetail && projectDetail.release_versions &&
<React.Fragment> <React.Fragment>
<Divider /> <Divider />
<Releases <Releases
owner={owner} owner={owner}
projectsId={projectsId} projectsId={projectsId}
releaseVersions={releaseVersions} releaseVersions={projectDetail.release_versions}
history={props.history} history={props.history}
distribution={distribution} baseOperate={baseOperate}
projectType={projectDetail.type}
/> />
</React.Fragment> </React.Fragment>
} }
{/* 贡献者 */} {/* 贡献者 */}
{ {
projectDetail && projectDetail.contributors && projectDetail.contributors.total_count >0 && projectDetail && projectDetail.contributors &&
<Contributors contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} /> <Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
} }
{/* 语言 */} {/* 语言 */}
{ projectDetail && projectDetail.languages && { projectDetail && projectDetail.languages &&

View File

@ -4,8 +4,8 @@ import { truncateCommitId } from '../common/util';
const typeIco = { const typeIco = {
"submodule":"icon-file-submodule font-17", "submodule":"icon-file-submodule font-17",
"file":'icon-wenjian6 font-15 color-blue-file', "file":'icon-wenjia font-15',
"dir":"icon-wenjianjia4 font-15 color-blue_4C" "dir":"icon-wenjianjia1 font-15"
} }
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
@ -13,15 +13,15 @@ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
<li> <li>
<span> <span>
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}> <a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
<i className={`iconfont ${typeIco[`${item.type}`]} mr8`}></i>{item.name} <i className={`iconfont ${typeIco[`${item.type}`]} color-green-file mr5`}></i>{item.name}
</a> </a>
</span> </span>
<span title="init project"> <span title="init project">
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit && item.commit.sha}`)}`} title={item.commit && item.commit.message}> <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit && item.commit.sha}`)}`} title={item.commit && item.commit.message}>
{item.commit && item.commit.message} {item.commit && item.commit.message}
</Link> </Link>
</span> </span>
<span title={item.commit && item.commit.created_at}>{item.commit && item.commit.time_from_now}</span> <span>{item.commit && item.commit.time_from_now}</span>
</li> </li>
) )
} }

View File

@ -1,4 +1,3 @@
import { result } from 'lodash';
import React from 'react'; import React from 'react';

View File

@ -1,9 +1,8 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import RenderHtml from '../../components/render-html'; import RenderHtml from '../../components/render-html';
import { AlignCenter } from '../Component/layout'; import { AlignCenter } from '../Component/layout';
import { Dropdown , Anchor , Spin } from 'antd'; import { Dropdown , Menu , Spin } from 'antd';
import { Link } from 'react-router-dom';
import ReadmeCatelogue from './sub/ReadmeCatelogue';
const $ = window.$; const $ = window.$;
function CoderDepotReadme({ operate , history , readme , ChangeFile }){ function CoderDepotReadme({ operate , history , readme , ChangeFile }){
@ -24,45 +23,49 @@ function CoderDepotReadme({ operate , history , readme , ChangeFile }){
const anchor = el.id; const anchor = el.id;
const level = el.tagName.replace("H", ""); const level = el.tagName.replace("H", "");
const href = `#${anchor}`; const href = `#${anchor}`;
return { href:`${href}`,text:el.textContent , level:level } return { href:`${path}${href}`,text:el.textContent , level:level }
}); });
setMenuList(items); setMenuList(items);
},[content]) },[content])
function menu(){ function menu(){
if(menuList && menuList.length > 0){ if(menuList && menuList.length > 0){
let hash = history.location.hash;
return( return(
<ReadmeCatelogue menuList={menuList} hash={history.location.hash}/> <Menu className="menuslist">
{
menuList.map((item,key)=>{
return(
<Menu.Item key={item.id} className={decodeURI(hash).indexOf(item.text)>-1 ?"active":""}><Link to={`${item.href}`} style={{paddingLeft:`${item.level *10}px`}} title={item.text}>{item.text}</Link></Menu.Item>
)
})
}
</Menu>
) )
}else{ }else{
return <Spin /> return <Spin />
} }
} }
return( return(
<div className="commonBox readBox" id="readme"> <div className="commonBox" id="readme">
<Anchor offsetTop={70} targetOffset={160}> <div className="commonBox-title boxTitle">
<div className="commonBox-title boxTitle"> <AlignCenter>
<AlignCenter> <Dropdown overlay={menu()}>
<Dropdown overlay={menu()} trigger={['hover']} overlayClassName="menuslist"> <span className="catelogue">
<span className="catelogue"> <i className="iconfont icon-zhangjie1 font-14 mr5"></i>
<i className="iconfont icon-muluicon font-12 mr5"></i> <span>目录</span>
<span>目录</span> </span>
</span> </Dropdown>
</Dropdown> <span className="commonBox-title-read">README.md</span>
</AlignCenter>
<span className="commonBox-title-read"><a href="#readme ">README.md</a></span> {
operate ?
</AlignCenter> <a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
{ <i className="iconfont icon-bianji6 font-16 color-blue"></i>
operate ? </a>
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}> :""
<i className="iconfont icon-a-bianji font-17 color-grey-6"></i> }
</a> </div>
:""
}
</div>
</Anchor>
{ {
content && content &&
<div className="commonBox-info"> <div className="commonBox-info">

View File

@ -4,7 +4,7 @@ import { Dropdown , Menu , Icon , Tooltip , Spin } from 'antd';
import { truncateCommitId } from '../common/util'; import { truncateCommitId } from '../common/util';
import { getBranch } from '../GetData/getData'; import { getBranch } from '../GetData/getData';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import './list.scss'; import './list.css';
function turnbar(str){ function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){ if(str && str.length>0 && str.indexOf("/")>-1){
@ -38,9 +38,9 @@ export default ((props)=>{
return( return(
<li key={key}> <li key={key}>
<div> <div>
<Link to={`/${owner}/${projectsId}/tree/${turnbar(item.name)}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link> <Link to={`/projects/${owner}/${projectsId}/tree/${turnbar(item.name)}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
<p className="f-wrap-alignCenter mt15"> <p className="f-wrap-alignCenter mt15">
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link> <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span> <span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span> <span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
</p> </p>
@ -48,7 +48,7 @@ export default ((props)=>{
<span> <span>
{ {
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) && (isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
<Link to={`/${owner}/${projectsId}/pulls/new/${item.name}`} className="mr20 color-blue mr30">创建合并请求</Link> <Link to={`/projects/${owner}/${projectsId}/pulls/new/${item.name}`} className="mr20 color-blue mr30">创建合并请求</Link>
} }
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file"> <Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file">
<a className="ant-dropdown-link"> <a className="ant-dropdown-link">

View File

@ -1,19 +1,13 @@
import React , { Component } from 'react'; import React , { Component } from 'react';
import { Spin , Pagination, Timeline } from 'antd'; import { Spin , Pagination } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import { truncateCommitId ,timeFormat } from '../common/util'; import { truncateCommitId } from '../common/util';
import { AlignTop } from '../Component/layout'; import { AlignTop } from '../Component/layout';
import SelectBranch from '../Branch/Select'; import SelectBranch from '../Branch/Select';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import User from '../Component/User';
import RenderHtml from '../../components/render-html.jsx';
import Tree from './img/tree.png';
import axios from 'axios'; import axios from 'axios';
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import CopyTool from '../Component/CopyTool';
import './tree/Index.scss'
function returnbar(str){ function returnbar(str){
if(str && str.length>0 && str.indexOf("%2F")>-1){ if(str && str.length>0 && str.indexOf("%2F")>-1){
@ -21,16 +15,14 @@ function returnbar(str){
} }
return str; return str;
} }
//代码库--提交页面
class CoderRootCommit extends Component{ class CoderRootCommit extends Component{
constructor(props){ constructor(props){
super(props); super(props)
this.state={ this.state={
commitDatas:undefined, commitDatas:undefined,
dataCount:undefined, dataCount:undefined,
limit:10, limit:20,
page: 1, page:1,
isSpining:false, isSpining:false,
branchList:undefined branchList:undefined
} }
@ -58,34 +50,20 @@ class CoderRootCommit extends Component{
this.Init(); this.Init();
} }
} }
UrlParamHash(url){
const params = {};
let h;
let hash = url.slice(url.indexOf('?')+1).split('&');
for(let i = 0; i<hash.length;i++){
h = hash[i].split('=');
params[h[0]] = h[1];
}
return params;
}
Init =()=>{ Init =()=>{
const { branchName } = this.props.match.params; const { branchName } = this.props.match.params;
const { limit } = this.state; const { page , limit } = this.state;
const {search} = this.props.location;
const realPage = (search && this.UrlParamHash(search).page) ? parseInt(this.UrlParamHash(search).page) : 1;
this.setState({ this.setState({
isSpining:true, isSpining:true
page:realPage
}) })
this.getCommitList( branchName , realPage , limit ); this.getCommitList( branchName , page , limit );
} }
getCommitList=(branch , page , limit)=>{ getCommitList=(branch , page , limit)=>{
this.setState({ this.setState({
isSpining:true isSpining:true
}) })
console.log(returnbar(branch));
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/commits.json`; const url = `/${owner}/${projectsId}/commits.json`;
axios.get(url,{ axios.get(url,{
@ -108,8 +86,7 @@ class CoderRootCommit extends Component{
image_url:item.author && item.author.image_url, image_url:item.author && item.author.image_url,
sha:item.sha, sha:item.sha,
time_from_now:item.time_from_now, time_from_now:item.time_from_now,
message:item.message, message:item.message
timestamp:item.timestamp
}) })
}) })
this.setState({ this.setState({
@ -124,13 +101,14 @@ class CoderRootCommit extends Component{
// 切换分支 search:tag为根据标签搜索 // 切换分支 search:tag为根据标签搜索
changeBranch=(value)=>{ changeBranch=(value)=>{
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
this.props.history.push(`/${owner}/${projectsId}/commits/branch/${value}`); this.props.history.push(`/projects/${owner}/${projectsId}/commits/branch/${value}`);
} }
ChangePage=(page)=>{ ChangePage=(page)=>{
this.props.history.push({pathname: this.props.history.location.pathname,search: `page=${page}`}) const { branchName } = this.props.match.params;
const { limit } = this.state;
this.getCommitList(branchName , page , limit);
} }
render(){ render(){
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state; const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
const { projectDetail, commit_class , defaultBranch } = this.props; const { projectDetail, commit_class , defaultBranch } = this.props;
@ -151,50 +129,46 @@ class CoderRootCommit extends Component{
></SelectBranch> ></SelectBranch>
</div> </div>
<Spin spinning={isSpining}> <Spin spinning={isSpining}>
<Timeline className="commitList"> <div className="commonBox">
{ <div className="commonBox-title">
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{ <div className="f-wrap-between" style={{alignItems:"center"}}>
return( <span className="font-16">{dataCount}次提交代码({branch})</span>
<Timeline.Item key={k} dot={page ===1 && k===0 ?<span className="new-conmmit">最新</span>:<i className="iconfont icon-a-yuanquan2x"></i>}> </div>
<div className="commitList-item f-wrap-between"> </div>
<div> <div className="commitList">
<AlignTop> {
<div className="commitDesc"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="font-14 color-grey-3 font-bd"><RenderHtml value={item.message}/></Link></div> commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
</AlignTop> return(
<p className="f-wrap-alignCenter mt15 pb5"> <div key={k}>
<User <AlignTop>
id={item.id} <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0,marginTop:"3px"}}>{truncateCommitId(`${item.sha}`)}</Link>
url={(item.image_url && getImageUrl(`/${item.image_url}`)) || "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"} <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitDesc">{item.message}</Link>
name={item.name} </AlignTop>
login={item.login} <p className="f-wrap-alignCenter mt15">
/> {
{item.timestamp && <label className="font-14 color-grey-3 ml3">提交于 {timeFormat(item.timestamp)}</label>} item.id ?
</p> <Link to={`/users/${item.login}`} className="show-user-link">
</div> {item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<div> <label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
<div className="treecopy"> </Link>:
<div> <span className="show-user-link">
<span className="treecopy-cont shadow"> {item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<img src={Tree} alt="sha" width={"16px"}/> <label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`}>{truncateCommitId(`${item.sha}`)}</Link> </span>
<input type="text" id={`value${k}`} value={`${truncateCommitId(`${item.sha}`)}`}/> }
</span>
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${k}`}/> </p>
</div>
<button className="btn-83" onClick={()=>{window.location.href=`/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}`}}>浏览文件</button>
</div>
</div>
</div> </div>
</Timeline.Item> )
) })
}) }
} {commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>} </div>
</Timeline> </div>
{ {
dataCount > limit ? dataCount > limit ?
<div className="edu-txt-center pt30 mb30"> <div className="edu-txt-center pt30 mb30">
<Pagination simple current={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination> <Pagination simple defaultCurrent={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div> </div>
:"" :""
} }

View File

@ -1,12 +1,10 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Popconfirm , Select , Dropdown , Spin , Anchor } from "antd"; import { Popconfirm , Select } from "antd";
import "./list.scss"; import "./list.css";
import axios from "axios"; import axios from "axios";
import Meditor from "../Newfile/m_editor"; import Meditor from "../Newfile/m_editor";
import RenderHtml from "../../components/render-html"; import RenderHtml from "../../components/render-html";
import ReadmeCatelogue from "./sub/ReadmeCatelogue";
const $ = window.$;
function bytesToSize(bytes) { function bytesToSize(bytes) {
if (bytes === 0) return "0 B"; if (bytes === 0) return "0 B";
let k = 1024, let k = 1024,
@ -21,13 +19,11 @@ class CoderRootFileDetail extends Component {
value: undefined, value: undefined,
language: undefined, language: undefined,
languages: undefined, languages: undefined,
description: props.detail.content, description: props.detail.content
menuList:undefined
}; };
} }
componentDidMount = () => { componentDidMount = () => {
window.scrollTo(0, 0);
const { detail , mdFlag } = this.props; const { detail , mdFlag } = this.props;
this.setState({ this.setState({
value: detail.content, value: detail.content,
@ -153,7 +149,7 @@ class CoderRootFileDetail extends Component {
.then((result) => { .then((result) => {
if (result) { if (result) {
this.props.showNotification("删除成功!"); this.props.showNotification("删除成功!");
this.props.history.push(`/${owner}/${projectsId}`); this.props.history.push(`/projects/${owner}/${projectsId}`);
} }
}) })
.catch((error) => { .catch((error) => {
@ -173,31 +169,6 @@ class CoderRootFileDetail extends Component {
}); });
}; };
renderMenulist=()=>{
const { description } = this.state;
if(description){
const items = $.map($("#files-md").find("h1,h2,h3,h4,h5,h6"), function (el, _) {
const anchor = el.id;
const level = el.tagName.replace("H", "");
const href = `#${anchor}`;
return { href:`${href}`,text:el.textContent , level:level }
});
return items;
}
return [];
}
menu=()=>{
const menuList = this.renderMenulist();
if(menuList && menuList.length > 0){
return(
<ReadmeCatelogue menuList={menuList} hash={this.props.history.location.hash}/>
)
}else{
return <Spin />
}
}
render() { render() {
const { const {
readOnly, readOnly,
@ -215,88 +186,79 @@ class CoderRootFileDetail extends Component {
const Option = Select.Option; const Option = Select.Option;
return ( return (
<React.Fragment> <React.Fragment>
<Anchor className="griditemAnchor" offsetTop={70}> <div className="grid-item branchTitle">
<div className="griditemCate"> <div className="grid-item">
{ <span className="ml20 color-grey-6 font-16">
md && readOnly &&
<Dropdown overlay={this.menu()} trigger={['hover']} overlayClassName="menuslist">
<span className="catelogue mr20">
<i className="iconfont icon-muluicon font-12 mr5"></i>
<span>目录</span>
</span>
</Dropdown>
}
<span className="color-grey-6 font-16">
{bytesToSize(detail && detail.size)} {bytesToSize(detail && detail.size)}
</span> </span>
</div> </div>
<p className="text-right"> <p className="text-right">
{flag && platform && ( {flag && platform && (
<div> <div>
{readOnly ? ( {readOnly ? (
<span> <span>
{ {
!detail.direct_download? !detail.direct_download?
<span> <span>
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20"> <a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i> <i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
</a>
{
type !==2 &&
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a> </a>
{ }
type !==2 && </span>:""
<a onClick={() => this.EditFile(false)} className="ml20"> }
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i> </span>
</a> ) : (
} <React.Fragment>
</span>:"" <Select
} showSearch={true}
</span> placeholder={"请选择文本语言"}
) : ( style={{ width: 200 }}
<React.Fragment> value={language}
<Select onChange={this.select_language}
showSearch={true} >
placeholder={"请选择文本语言"} <Option value={undefined}>请选择文本语言</Option>
style={{ width: 200 }} {languages &&
value={language} languages.map((item, key) => {
onChange={this.select_language} return (
> <Option value={item} key={key}>
<Option value={undefined}>请选择文本语言</Option> {item}
{languages && </Option>
languages.map((item, key) => { );
return ( })}
<Option value={item} key={key}> </Select>
{item} <button
</Option> type="button"
); className="ant-btn ant-btn-sm ml20"
})} onClick={() => this.EditFile(true)}
</Select> >
<button <span> </span>
type="button" </button>
className="ant-btn ant-btn-sm ml20" </React.Fragment>
onClick={() => this.EditFile(true)} )}
> {
<span> </span> type !==2 &&
</button> <Popconfirm
</React.Fragment> title="确认删除这个文件?"
)} className="ml20"
{ okText="确定"
type !==2 && cancelText="取消"
<Popconfirm onConfirm={this.deleteFile}
title="确认删除这个文件?" >
className="ml20" <a>
okText="确定" <i className="iconfont icon-shanchu font-15 color-grey-6"></i>
cancelText="取消" </a>
onConfirm={this.deleteFile} </Popconfirm>
> }
<a>
<i className="iconfont icon-shanchu font-15 color-grey-6"></i> </div>
</a> )}
</Popconfirm> </p>
} </div>
</div>
)}
</p>
</Anchor>
<div> <div>
{detail.image_type ? ( {detail.image_type ? (
<div className="edu-txt-center pt20 pb20"> <div className="edu-txt-center pt20 pb20">
@ -310,7 +272,7 @@ class CoderRootFileDetail extends Component {
</div> </div>
) : ( ) : (
md && readOnly ? md && readOnly ?
<div className="files-md" id="files-md"> <div className="files-md">
<RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/> <RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/>
</div> </div>
: :

View File

@ -1,9 +1,9 @@
import React , { Component } from 'react'; import React , { Component } from 'react';
import { Route , Switch } from 'react-router-dom'; import { Route , Switch } from 'react-router-dom';
// import Top from './DetailTop'; import Top from './DetailTop';
import Loadable from 'react-loadable'; import Loadable from 'react-loadable';
import Loading from '../../Loading'; import Loading from '../../Loading';
import './Index.scss'; import axios from 'axios';
const FileNew = Loadable({ const FileNew = Loadable({
loader: () => import('../Newfile/Index'), loader: () => import('../Newfile/Index'),
@ -18,25 +18,25 @@ const CoderRootCommit = Loadable({
loading: Loading, loading: Loading,
}) })
const CoderRootBranch = Loadable({ const CoderRootBranch = Loadable({
loader: () => import('./tree/Index'), loader: () => import('./CoderRootBranch'),
loading: Loading, loading: Loading,
}) })
const CoderRootTag = Loadable({ const CoderRootTag = Loadable({
loader: () => import('./tag/Index'), loader: () => import('./CoderRootTag'),
loading: Loading, loading: Loading,
}) })
const CoderRootVersion = Loadable({ const CoderRootVersion = Loadable({
loader: () => import('./version/Index'), loader: () => import('../Version/version'),
loading: Loading,
})
const CoderRootVersionNew = Loadable({
loader: () => import('../Version/New'),
loading: Loading,
})
const CoderRootVersionUpdate = Loadable({
loader: () => import('../Version/New'),
loading: Loading, loading: Loading,
}) })
// const CoderRootVersionNew = Loadable({
// loader: () => import('./version/New'),
// loading: Loading,
// })
// const CoderRootVersionUpdate = Loadable({
// loader: () => import('./version/New'),
// loading: Loading,
// })
const Diff = Loadable({ const Diff = Loadable({
loader: () => import('./Diff'), loader: () => import('./Diff'),
loading: Loading, loading: Loading,
@ -50,94 +50,94 @@ class CoderRootIndex extends Component{
} }
} }
// componentDidMount=()=>{ componentDidMount=()=>{
// this.Init(); this.Init();
// } }
// componentDidUpdate=(prevProps)=>{ componentDidUpdate=(prevProps)=>{
// const { location } = this.props; const { location } = this.props;
// const prevlocation = prevProps && prevProps.location; const prevlocation = prevProps && prevProps.location;
// if (location !== prevlocation) { if (location !== prevlocation) {
// this.Init(); this.Init();
// } }
// } }
// Init=()=>{ Init=()=>{
// const { branchName } = this.props.match.params; const { branchName } = this.props.match.params;
// const { defaultBranch } = this.props; const { defaultBranch } = this.props;
// this.getTopCount(branchName || defaultBranch); this.getTopCount(branchName || defaultBranch);
// } }
// 获取<Top />组件里要显示的数据 // 获取<Top />组件里要显示的数据
// getTopCount=(branch)=>{ getTopCount=(branch)=>{
// const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
// const url = `/${owner}/${projectsId}/top_counts.json`; const url = `/${owner}/${projectsId}/top_counts.json`;
// axios.get(url,{params:{ axios.get(url,{params:{
// ref:branch ref:branch
// }}).then(result=>{ }}).then(result=>{
// if(result){ if(result){
// this.setState({ this.setState({
// coderCount:result.data coderCount:result.data
// }) })
// } }
// }).catch(error=>{console.log(error);}) }).catch(error=>{console.log(error);})
// } }
render(){ render(){
return( return(
<div className="coderSubPage"> <div>
{/* <Top {...this.props} {...this.state}/> */} <Top {...this.props} {...this.state}/>
<Switch {...this.props}> <Switch {...this.props}>
{/* 新建文件 */} {/* 新建文件 */}
<Route path="/:owner/:projectsId/:branch/newfile/:path" <Route path="/projects/:owner/:projectsId/:branch/newfile/:path"
render={ render={
(props) => (<FileNew {...this.props} {...props} {...this.state} />) (props) => (<FileNew {...this.props} {...props} {...this.state} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/:branch/uploadfile" <Route path="/projects/:owner/:projectsId/:branch/uploadfile"
render={ render={
(props) => (<UploadFile {...this.props} {...props} {...this.state} />) (props) => (<UploadFile {...this.props} {...props} {...this.state} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/:branch/newfile" <Route path="/projects/:owner/:projectsId/:branch/newfile"
render={ render={
(props) => (<FileNew {...this.props} {...props} {...this.state} />) (props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/commits/branch/:branchName" <Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={ render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />) () => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/commits/:sha" <Route path="/projects/:owner/:projectsId/commits/:sha"
render={ render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>) (props) => (<Diff {...this.props} {...props} {...this.state}/>)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/commits" <Route path="/projects/:owner/:projectsId/commits"
render={ render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />) () => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
} }
></Route> ></Route>
{/* <Route path="/:owner/:projectsId/releases/:versionId/update" <Route path="/projects/:owner/:projectsId/releases/:versionId/update"
render={ render={
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />) (props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/releases/new" <Route path="/projects/:owner/:projectsId/releases/new"
render={ render={
() => (<CoderRootVersionNew {...this.props} {...this.state} />) () => (<CoderRootVersionNew {...this.props} {...this.state} />)
} }
></Route> */} ></Route>
<Route path="/:owner/:projectsId/releases" <Route path="/projects/:owner/:projectsId/releases"
render={ render={
() => (<CoderRootVersion {...this.props} {...this.state} />) () => (<CoderRootVersion {...this.props} {...this.state} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/tags" <Route path="/projects/:owner/:projectsId/tag"
render={ render={
() => (<CoderRootTag {...this.props} {...this.state} />) () => (<CoderRootTag {...this.props} {...this.state} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/branches" <Route path="/projects/:owner/:projectsId/branchs"
render={ render={
() => (<CoderRootBranch {...this.props} {...this.state} />) () => (<CoderRootBranch {...this.props} {...this.state} />)
} }

View File

@ -34,7 +34,7 @@ export default (( props, { projectDetail }) => {
<div className="div_table"> <div className="div_table">
<ul className="ul_thead"> <ul className="ul_thead">
<li> <li>
<span className="flex1"></span> <span className="flex1"></span>
<span>提交信息</span> <span>提交信息</span>
<span className="ul_tbody_forth">下载</span> <span className="ul_tbody_forth">下载</span>
</li> </li>
@ -49,7 +49,7 @@ export default (( props, { projectDetail }) => {
<span className="font-16">{item.name}</span> <span className="font-16">{item.name}</span>
</span> </span>
<span className="ul_tbody_third"> <span className="ul_tbody_third">
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`} className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</Link> <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`} className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</Link>
</span> </span>
<span className="ul_tbody_forth"> <span className="ul_tbody_forth">
<a href={item.tarball_url} style={{ color: "#4CC1DA" }} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a> <a href={item.tarball_url} style={{ color: "#4CC1DA" }} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
import React from 'react';
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
// forge项目详情
const ProjectDetail = Loadable({
loader: () => import("../Main/Detail"),
loading: Loading,
});
export default withRouter(
(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props) => {
return (
<Switch>
<Route
path="/:owner/:projectsId"
render={(p) => (
<ProjectDetail {...props} {...p} />
)}
></Route>
</Switch>
)
}))))
)

View File

@ -12,19 +12,19 @@ class DetailTop extends Component {
{ {
platform ? platform ?
<React.Fragment> <React.Fragment>
<Link to={`/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}> <Link to={`/projects/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i> <i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{(coderCount && coderCount.commits_count) || 0}</span> <span>{(coderCount && coderCount.commits_count) || 0}</span>
</Link> </Link>
<Link to={`/${owner}/${projectsId}/branches`} className={pathname.indexOf("/branches") > 0 ? "active" : ""}> <Link to={`/projects/${owner}/${projectsId}/branchs`} className={pathname.indexOf("/branchs") > 0 ? "active" : ""}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i> <i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{(coderCount && coderCount.branches_count) || 0}</span> <span>{(coderCount && coderCount.branches_count) || 0}</span>
</Link> </Link>
<Link to={`/${owner}/${projectsId}/tags`} className={pathname.indexOf("/tags") > 0 ? "active" : ""}> <Link to={`/projects/${owner}/${projectsId}/tag`} className={pathname.indexOf("/tag") > 0 ? "active" : ""}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i> <i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{(coderCount && coderCount.tags_count) || 0}</span> <span>{(coderCount && coderCount.tags_count) || 0}</span>
</Link> </Link>
<Link to={`/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}> <Link to={`/projects/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}>
<i className="iconfont icon-fahangban font-18 mr3"></i> <i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span> <span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</Link> </Link>

View File

@ -1,65 +1,35 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { Button ,Spin } from "antd"; import { Button ,Spin } from "antd";
import { timeFormat, truncateCommitId } from '../common/util'; import { truncateCommitId } from '../common/util';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import Files from '../Merge/Files'; import Files from '../Merge/Files';
import Tree from "./img/tree.png";
import User from "../Component/User"; import User from "../Component/User";
import RenderHtml from "../../components/render-html"; import Keys from "../Component/Keys";
import axios from "axios"; import axios from "axios";
import { Link } from "react-router-dom";
const Infos = styled.div` const Infos = styled.div`
border: 1px solid #FAFCFF; border: 1px solid #dddddd;
margin-bottom:15px; margin-bottom:15px;
& .commitinfos { & .commitinfos {
background-color: #f1f8ff; background-color: #f1f8ff;
border: 1px solid rgba(42, 97, 255, 0.23); border-bottom: 1px solid #ddd;
border-radius: 3px 3px 0px 0px; padding: 20px;
padding: 10px 20px 10px 16px;
& .markdown-body table{
background: #f1f8ff;
}
& .btnblue{
margin-top: 12px;
}
& .task-hide{
width: 65rem;
overflow:hidden;
white-space:normal;
word-break:break-all;
font-weight: bold;
color: #333333;
font-size: 16px;
}
} }
& > .f-wrap-between { & > .f-wrap-between {
padding: 14px 20px 14px 16px; padding: 10px 20px;
border-radius: 3px 3px 0px 0px;
border: 1px solid #D0D0D0;
.df{
align-items: center;
& .underline:hover{
text-decoration: underline;
}
}
} }
`; `;
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){ export default ({ match , history }) => {
return str.replaceAll('/','%2F');
}
return str;
}
//
export default (props) => {
const {match , history } = props;
const [data, setData] = useState({undefined}); const [data, setData] = useState({undefined});
const [commit, setCommit] = useState(undefined); const [commit, setCommit] = useState(undefined);
const [parents, setParents] = useState(undefined); const [parents, setParents] = useState(undefined);
const [committer, setCommitter] = useState(undefined); const [committer, setCommitter] = useState(undefined);
const [isSpin, setIsSpin] = useState(true); const [isSpin, setIsSpin] = useState(true);
const { sha , projectsId, owner } = match.params; const { sha , projectsId, owner } = match.params;
useEffect(() => { useEffect(() => {
if (projectsId && owner && sha) { if (projectsId && owner && sha) {
@ -73,7 +43,6 @@ export default (props) => {
setParents(result.data.parents); setParents(result.data.parents);
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer)); setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
setIsSpin(false); setIsSpin(false);
} }
}) })
.catch(error => { .catch(error => {
@ -87,42 +56,29 @@ export default (props) => {
<Infos> <Infos>
<div className="commitinfos"> <div className="commitinfos">
<div className="f-wrap-between"> <div className="f-wrap-between">
<div> {commit && commit.message &&
{commit && commit.message && <pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
<RenderHtml className="task-hide" value={commit.message}/> }
} <Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
<Link to={`/${owner}/${projectsId}/tree/${data.branch}`}><i className="iconfont icon-fenzhi2 font-18"></i>{data.branch}</Link>
</div>
<Button type="primary" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="btnblue" style={{height:"36px"}}>浏览文件</Button>
</div> </div>
</div> </div>
<div className="f-wrap-between" style={{ alignItems: "center" }}> <div className="f-wrap-between" style={{ alignItems: "center" }}>
<ul className="df"> <ul className="df">
<User <User
id = {committer && committer.id} url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
url={(committer && getImageUrl(`/${committer.image_url}`))}
name={committer && committer.name} name={committer && committer.name}
login={committer && committer.login}
/> />
{commit && commit.timestamp && <li className="ml4">提交于{timeFormat(commit.timestamp)}</li>} {committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
</ul> </ul>
<li className="df"> <li className="df">
{ {
parents && parents.length > 0 && parents.map((item,key)=>{ parents && parents.length > 0 && parents.map((item,key)=>{
return( return(
<div className="ml40 f-wrap-alignCenter"> <Keys title="父节点" value={truncateCommitId(item.sha)} key={key} className="mr20"></Keys>
<label className="mr8">父节点</label>
<img src={Tree} alt="sha" width={"16px"} className="mr4"/>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}/${data.branch}`} className="underline">{truncateCommitId(item.sha)}</Link>
</div>
) )
}) })
} }
<div className="ml40 f-wrap-alignCenter"> <Keys title="当前节点" value={truncateCommitId(sha)}></Keys>
<label className="mr8">当前节点</label>
<img src={Tree} alt="sha" width={"16px"} className="mr4"/>
<span>{truncateCommitId(sha)}</span>
</div>
</li> </li>
</div> </div>
</Infos> </Infos>
@ -131,7 +87,6 @@ export default (props) => {
data={data} data={data}
owner={owner} owner={owner}
projectsId={projectsId} projectsId={projectsId}
parentsSha={parents && parents.length > 0 && parents[0].sha}
/> />
</Spin> </Spin>
</div> </div>

View File

@ -1,19 +1,18 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd'; import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
import Slider from "react-slick"; import Slider from "react-slick";
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import "slick-carousel/slick/slick.css"; import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css"; import "slick-carousel/slick/slick-theme.css";
import '../css/index.scss' import '../css/index.scss'
import './list.scss'; import './list.css';
import './Index.scss'; import './Index.scss';
import ListItem from './IndexItem' import ListItem from './IndexItem'
import axios from 'axios'; import axios from 'axios';
import img_new from '../Images/new.png'; import img_new from '../Images/new.png';
import img_array from '../Images/array.png'; import img_array from '../Images/array.png';
import banner from '../Images/banner_list.jpg'; import banner from '../Images/banner_list.jpg';
import CheckProfile from '../Component/ProfileModal/Profile';
const Search = Input.Search; const Search = Input.Search;
class Index extends Component { class Index extends Component {
@ -229,7 +228,7 @@ class Index extends Component {
} }
getoDetail=(login,identifier)=>{ getoDetail=(login,identifier)=>{
this.props.history.push(`/${login}/${identifier}`); this.props.history.push(`/projects/${login}/${identifier}`);
} }
// 选择语言类别 // 选择语言类别
@ -255,14 +254,10 @@ class Index extends Component {
newItem = ()=>{ newItem = ()=>{
return( return(
<ul> <Menu>
<li> <Menu.Item key="created_mirror"><Link to={`/projects/mirror/new`}>新建镜像项目</Link></Menu.Item>
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/deposit/new')}}>新建项目</CheckProfile> <Menu.Item key="created_deposit"><Link to={`/projects/deposit/new`}>新建托管项目</Link></Menu.Item>
</li> </Menu>
<li>
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/mirror/new')}}>导入项目</CheckProfile>
</li>
</ul>
) )
} }
@ -392,13 +387,7 @@ class Index extends Component {
<div> <div>
{ {
current_user && current_user.login && current_user && current_user.login &&
<Popover <Popover content={this.newItem()} trigger={["click"]} placement='bottom' className="mr50">
overlayClassName="newPopUl"
content={this.newItem()}
trigger={["click"]}
placement='bottom'
className="mr50"
>
<a className="ant-dropdown-link"> <a className="ant-dropdown-link">
<span className="color-blue font-16"><img src={img_new} alt="" width="13px" /> 新建</span> <span className="color-blue font-16"><img src={img_new} alt="" width="13px" /> 新建</span>
</a> </a>

View File

@ -13,21 +13,6 @@
} }
} }
} }
.iconBtn{
i{
color: #666;
}
span{
margin-left: 4px;
color: #333!important;
&:last-child{
font-weight: 500;
}
}
&:hover span,&:hover i{
color: #466AFF!important;
}
}
/* recommandProjects */ /* recommandProjects */
.recommandProjects.slick-slider{ .recommandProjects.slick-slider{
width: 1230px; width: 1230px;
@ -123,114 +108,63 @@
margin: 0 auto; margin: 0 auto;
.panelmenu{ .panelmenu{
padding-top:30px; padding-top:30px;
.depotBtn{
.mr-5{
margin-right: -5px;
}
.ant-btn{
height: 32px;
line-height: 32px;
width: 83px;
text-align: center;
padding:0px ;
font-weight: 500;
font-size: 14px;
}
.ant-btn-default{
color: #333;
border-color: #d0d0d0;
&:hover{
background: #F3F4F6;
}
}
.ant-btn-primary{
color: #fff;
background-color: #466AFF;
border: none;
&:hover{
background-color: rgba(70,106,255,0.85);
}
}
}
} }
.depotBtn,.addOptionBtn{ .addOptionBtn{
height: 32px;
line-height: 30px;
display: flex; display: flex;
border:1px solid #d9d9d9;
border-radius: 2px;
a{ a{
color: #333!important; padding:0px 13px;
font-weight: 500!important; color: rgba(0, 0, 0, 0.65);
border-radius: 5px; cursor: pointer;
width: 83px; }
height: 32px; & > a:first-child{
line-height: 30px; border-right: 1px solid #d9d9d9;
background: #fff; }
border: 1px solid #D0D0D0; & > a:last-child{
margin-right: 10px; border-right: none;
text-align: center;
&:hover,&:active{
background: #F3F4F6;
}
} }
} }
.infoCount{ .infoCount{
display: inline-block; display: inline-block;
width: 24px; padding:0px 5px;
text-align: center; height: 16px;
height: 24px; line-height: 16px;
line-height: 24px; background-color: #eee;
background-color:rgba(153, 153, 153, 0.13);; color:#999;
color:#666;
border-radius: 12px; border-radius: 12px;
margin-left: 6px; margin-left: 10px;
font-size: 12px; font-size: 12px;
} }
.attrPerson{ .attrPerson{
padding-top: 12px; padding-top: 15px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding-bottom: 2px;
a{ a{
margin: 0px 17px 10px 0px; margin: 10px 10px 0px 0px;
img{ img{
border-radius: 50%; border-radius: 50%;
width: 40px; width: 35px;
height: 40px; height: 35px;
} }
&:nth-child(5n){ &:nth-child(6){
margin-right: 0px; margin-right: 0px;
} }
} }
} }
.attrBadge{
padding-top: 12px;
display: flex;
flex-wrap: wrap;
padding-bottom: 2px;
a{
margin: 0px 17px 10px 0px;
img{
border-radius: 50%;
width: 40px;
height: 40px;
}
&:nth-child(5n){
margin-right: 0px;
}
}
}
.progress{ .progress{
display: flex; display: flex;
border-radius: 2px; border-radius: 10px;
height: 11px; height: 7px;
margin-top: 12px; margin-top: 12px;
span{ span{
&:first-child{ &:first-child{
border-radius: 2px 0px 0px 2px; border-radius: 10px 0px 0px 10px;
} }
&:last-child{ &:last-child{
border-radius: 0px 2px 2px 0px; border-radius: 0px 10px 10px 0px;
} }
} }
} }
@ -244,17 +178,16 @@
height: 8px; height: 8px;
width: 8px; width: 8px;
left: 0px; left: 0px;
top:8px; top:10px
} }
&>span{ &>span{
padding-left: 15px; padding-left: 15px;
position: relative; position: relative;
min-width: 33.5%; min-width: 33.5%;
font-size: 12px;
font-weight: 400;
color: #666;
span{ span{
color: #666;
&:last-child{ &:last-child{
color: #999;
margin-left: 5px; margin-left: 5px;
} }
} }
@ -262,24 +195,18 @@
} }
.listtable{ .listtable{
margin-top: 20px; margin-top: 20px;
border:1px solid #d9d9d9;
border-radius: 4px;
.listtablehead{ .listtablehead{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
padding:12px 20px 11px; padding:7px 20px;
border-radius: 4px 4px 0px 0px; border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23); background-color: #FAFBFC;
background-color: #FAFCFF;
.ellipsistxt{ .ellipsistxt{
&:hover .markdown-body{ margin-top: 6px;
color: #466AFF;
& a{
color: #466AFF;
}
}
margin-top: 2px;
// cursor: pointer;
#ptxt{ #ptxt{
margin-bottom: 0px; margin-bottom: 0px;
word-break: break-all; word-break: break-all;
@ -289,27 +216,6 @@
white-space:-pre-wrap; /* Opera 4-6 */ white-space:-pre-wrap; /* Opera 4-6 */
white-space:-o-pre-wrap; /* Opera 7 */ white-space:-o-pre-wrap; /* Opera 7 */
word-wrap:break-word; word-wrap:break-word;
.markdown-body{
line-height: 10px;
font-size: 14px;
& p {
margin: 1px 0px 0px !important;
font-size: 14px !important;
}
& ol,ul{
padding-bottom: 3px;
& li{
min-height: 18px;
}
}
& table{
line-height: 1;
background: #FAFCFF;
}
&:first-child {
margin-top: -1px !important;
}
}
} }
margin-left: 13px; margin-left: 13px;
line-height:18px; line-height:18px;
@ -317,41 +223,36 @@
width: 0; width: 0;
color: #666; color: #666;
&.hidetxt{ &.hidetxt{
height: 24px; height: 18px;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
padding-right:8px; padding-right:8px;
// &::after{ &::after{
// position: absolute; position: absolute;
// right: 0px; right: 0px;
// bottom: 0px; bottom: 0px;
// content:"..."; content:"...";
// } }
} }
} }
.ellipsis{ .ellipsis{
margin-left: 8px; margin-left: 8px;
cursor: pointer; cursor: pointer;
border-radius: 2px; border-radius: 2px;
height: 16px; background-color: #c1c1c1;
background: rgba(153, 153, 153, 0.2);
border-radius: 2px;
padding:0px 4px; padding:0px 4px;
height: 14px; height: 14px;
line-height: 14px; line-height: 14px;
margin-top: 9px; margin-top: 9px;
i{ i{
font-size: 15px!important; font-size: 15px!important;
color: #333; color: #fff;
height: 14px; height: 14px;
line-height: 14px; line-height: 14px;
} }
} }
} }
.listtablebody{ .listtablebody{
border-radius:0px 0px 4px 4px ;
border: 1px solid #D0D0D0;
border-top: none;
li.listtablepath{ li.listtablepath{
a{color: #40a9ff;} a{color: #40a9ff;}
p{ p{
@ -359,15 +260,12 @@
} }
} }
& > li{ & > li{
height: 38px; height: 42px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
padding:0px 20px 0px 24px; padding:0px 20px 0px 24px;
&:hover{
background-color: #F3F4F6;
}
& > span:first-child{ & > span:first-child{
width: 30%; width: 30%;
overflow: hidden; overflow: hidden;
@ -394,10 +292,8 @@
.drawerBtn{ .drawerBtn{
position: fixed; position: fixed;
left: -13px; left: -13px;
width: 33px; border:1px solid rgb(207,205,223);
background: #FFFFFF; width: 34px;
box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.09);
border: 1px solid #666666;
border-radius: 0px 12px 12px 0px; border-radius: 0px 12px 12px 0px;
height: 70px; height: 70px;
top:50%; top:50%;
@ -405,49 +301,36 @@
cursor: pointer; cursor: pointer;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: flex-end;
justify-content: center; justify-content: center;
padding-left: 7px;
&:hover{ &:hover{
box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.09); box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
} }
span{ span{
writing-mode: vertical-lr; writing-mode: vertical-lr;
color: #333; color: #202429;
width: 25px; width: 25px;
font-size: 14px;
} }
i{ i{
color: #333; color: #24292e;
height: 14px; height: 18px;
line-height: 14px; line-height: 18px;
width: 14px; width: 18px;
margin-left: 2px;
margin-bottom: 3px;
} }
} }
.downMenu{ .downMenu{
width: 329px; width: 330px;
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
background-color: #fff; background-color: #fff;
box-shadow: 0px 1px 8px 1px rgba(212, 212, 212, 0.5); .ant-menu-vertical .ant-menu-item:hover{
padding-bottom: 14px; background-color: #e6f7ff;
.ant-menu-item{
height: 50px;
line-height: 50px;
}
}
.fileMenu{
width: 83px;
li{
padding:6px 0px!important;
text-align: center;
width: 100%;
} }
} }
.catelogue{ .menuslist{
cursor: pointer; max-height: 200px;
background: #FAFBFC; overflow-y: auto;
padding:10px 15px;
border-radius: 4px; border-radius: 4px;
.ant-dropdown-menu-item{ .ant-dropdown-menu-item{
border-radius: 8px; border-radius: 8px;
@ -459,19 +342,22 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
} }
border: 1px solid #D0D0D0; .ant-dropdown-menu-item.active{
background-color: #e6f7ff;
}
}
.catelogue{
border:1px solid rgb(211, 211, 211);
font-size: 15px; font-size: 15px;
font-weight: normal; font-weight: normal;
margin-right: 12px; border-radius: 5px;
margin-right: 10px;
padding:0px 10px; padding:0px 10px;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
color: #666!important; color: #666!important;
display: flex; display: flex;
align-items: center; align-items: center;
&:hover{
background-color: #F3F4F6;
}
span{ span{
margin-top: 1px; margin-top: 1px;
} }
@ -484,48 +370,4 @@
&:hover{ &:hover{
color: #05101a; color: #05101a;
} }
}
.pinfos{
i,a{color: #666;}
&:hover i,&:hover a{
color: #2A61FF!important;
}
}
.graph{
flex:1;
margin:0px 12px;
.ant-typography{
white-space: pre-wrap;
margin-bottom: 0px;
}
}
.ant-anchor-wrapper{
padding-left: 2px!important;
.ant-anchor-ink::before{
background-color: #fff;
}
}
.coderSubPage{
width: 1200px;
margin:0px auto;
}
.griditemAnchor{
margin-left: 0px!important;
padding: 0px!important;
border-bottom: 1px solid #ddd;
.ant-anchor{
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
}
.griditemCate{
color: #333;
font-size: 16px;
display: flex;
align-items: center;
.catelogue{
margin-left: 0px;
}
}
} }

View File

@ -5,7 +5,7 @@ import { AlignCenter } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import '../css/index.scss'; import '../css/index.scss';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import './list.scss'; import './list.css';
import img_parise from '../Images/parise.png'; import img_parise from '../Images/parise.png';
class IndexItem extends Component { class IndexItem extends Component {
@ -28,35 +28,35 @@ class IndexItem extends Component {
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img> <img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
</a> </a>
: :
<Link to={`/${item.author && item.author.login}`} className="show-user-link"> <Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}`:`/users/${item.author.login}`)} className="show-user-link">
<img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img> <img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img>
</Link> </Link>
} }
<div className="p-r-Infos"> <div className="p-r-Infos">
<div className="p-r-name"> <div className="p-r-name">
<AlignCenter> <AlignCenter>
<Link to={`/${item.author.login}/${item.identifier}`} title={`${item.author.name}/${item.name}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 470 }}> <Link to={`/projects/${item.author.login}/${item.identifier}`} title={`${item.author.name}/${item.name}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 470 }}>
{item.author.name}/{item.name} {item.author.name}/{item.name}
</Link> </Link>
{ !item.is_public && <span className="privateTag">私有</span> } { !item.is_public && <span className="privateTag">私有</span> }
{ {
item.forked_from_project_id ? item.forked_from_project_id ?
<Tooltip title="该项目是一个fork仓库" className="ml5"> <span className="ml5">
<i className="iconfont icon-fork font-18 color-orange" /> <i className="iconfont icon-fork font-18 color-orange" />
</Tooltip> </span>
: "" : ""
} }
{ {
item.type && item.type === 2 ? item.type && item.type === 2 ?
<Tooltip title="该项目是一个同步镜像仓库" className="ml5"> <Tooltip title="该项目是一个镜像" className="ml5">
<i className="iconfont icon-banbenku font-18 color-green" /> <i className="iconfont icon-banbenku font-18 color-green" />
</Tooltip>:"" </Tooltip>:""
} }
{ {
item.type && item.type === 1 ? item.type && item.type === 1 ?
<Tooltip title="该项目是一个导入于其他网站的仓库" className="ml5"> <span className="ml5">
<i className="iconfont icon-jingxiang font-18 color-green" /> <i className="iconfont icon-jingxiang font-18 color-green" />
</Tooltip>:"" </span>:""
} }
</AlignCenter> </AlignCenter>
<span className="p-r-tags"> <span className="p-r-tags">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

View File

@ -218,92 +218,74 @@
} }
/* -----------详情------------ */ /* -----------详情------------ */
.detailHeader-wrapper{ .detailHeader-wrapper{
background-color:#FBFCFF; background-color:#FAFBFC;
border-bottom:1px solid #e2e2e2; /* background: url(../Images/forgeBanner.jpg) no-repeat center; */
/* background-size:cover; */
} }
.headerMenu-wrapper{ .headerMenu-wrapper{
font-size: 16px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
cursor: pointer; }
li{ .headerMenu-wrapper li{
text-align: center; position: relative;
padding:0px; text-align: center;
margin-right: 40px; height: 40px;
display: flex; line-height: 28px;
& > a{ margin-right: 40px;
position: relative; }
font-size: 14px; .headerMenu-wrapper li a{
height: 36px; color: #666;
line-height: 24px; }
display: block; .headerMenu-wrapper li a > img{
color: #000!important; margin-right: 8px;
&> span.num{ }
line-height: 24px; .headerMenu-wrapper li a > span.num{
margin-left: 5px; height: 28px;
font-size: 12px; line-height: 29px;
float: right; margin-left: 8px;
color: #666!important; font-size: 12px;
background-color: rgba(153, 153, 153, 0.13);; color: #2878FF;
border-radius: 50%; float: right;
width: 24px; }
height: 24px; .headerMenu-wrapper li.active::after{
} position: absolute;
} bottom:0px;
height:2px;
&.active a::after,&:hover a::after{ background-color: #5091FF;
position: absolute; content:'';
bottom:0px; left: 0px;
height:2px; width:100%;
background-color:rgba(153, 153, 153, 0.2);
content:'';
left: 0px;
width:100%;
}
&.active span{
font-weight: 500;
}
&.active a::after{
background-color: #466AFF;
}
}
} }
.detail_tag_btn{ .detail_tag_btn{
height:32px; height:26px;
line-height: 32px; line-height: 26px;
border-radius:5px; border-radius:5px;
border:1px solid #D0D0D0; border:1px solid #f1f1f1;
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 10px; margin-left: 30px;
padding:0px; padding:0px;
background-color:#FAFBFC; background-color: transparent;
box-shadow: none; box-shadow: none;
.detail_tag_btn_name{
padding:0px 10px;
text-align: center;
height: 30px;
line-height: 30px;
border-radius:5px 0px 0px 5px;
&:hover
{
background-color: #F3F4F6;
}
span{
color: #333!important;
}
}
.detail_tag_btn_count{
width: 42px;
text-align: center;
background: #fff;
border-radius: 0px 4px 4px 0px;
height:100%;
border-left: 1px solid #D0D0D0;
}
} }
.ant-tooltip { .ant-tooltip {
max-width: fit-content!important; max-width: fit-content!important;
} }
.detail_tag_btn_name{
padding:0px 10px;
color: #666!important;
}
.detail_tag_btn_name img{
margin-right: 10px;
}
.detail_tag_btn_count{
padding:0px 10px;
background: #fff;
border-radius: 0px 4px 4px 0px;
font-size: 12px;
height:100%;
}
.files-md{ .files-md{
padding:20px; padding:20px;
} }
@ -354,7 +336,6 @@
.gitAddressClone{ .gitAddressClone{
margin:14px 20px!important;
display: flex; display: flex;
height: 40px; height: 40px;
align-items: center; align-items: center;
@ -426,15 +407,14 @@
border-right: none; border-right: none;
} }
.gitAddressClone > input{ .gitAddressClone > input{
border:none;
outline: none; outline: none;
padding: 0px 8px; padding:0px 8px;
height: 38px; height: 40px;
line-height: 38px; line-height: 40px;
border: none!important; border-radius: 0px;
border-right: 1px solid #eee!important; border: 1px solid #eee;
border-radius: 4px 0px 0px 4px; flex:1;
flex: 1;
max-width: 249px;
} }
.wrap-commit-table .ant-table-small > .ant-table-content > .ant-table-body{ .wrap-commit-table .ant-table-small > .ant-table-content > .ant-table-body{
margin:0px; margin:0px;
@ -519,7 +499,7 @@
} }
.addFile a{ .addFile a{
display: block; display: block;
background-color: rgba(76, 172, 255,0.8); background-color: rgb(76, 172, 255,0.8);
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
height: 32px; height: 32px;
@ -534,7 +514,7 @@
border-left: 1px solid rgba(247, 247, 247, 0.3); border-left: 1px solid rgba(247, 247, 247, 0.3);
} }
.addFile a:active{ .addFile a:active{
background-color: rgba(76, 172, 255,1); background-color: rgb(76, 172, 255,1);
} }
@ -573,11 +553,8 @@
} }
.commonBox{ .commonBox{
border:1px solid #ddd; border:1px solid #ddd;
margin-top: 18px; margin-top: 30px;
border-radius: 4px; border-radius: 4px;
.ant-anchor-wrapper{
overflow: unset!important;
}
} }
.commonBox .commonBox-title{ .commonBox .commonBox-title{
padding:0px 20px; padding:0px 20px;
@ -590,28 +567,14 @@
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
border-radius: 4px 4px 0px 0px; border-radius: 4px 4px 0px 0px;
} }
.readBox{
border:none;
&.commonBox .commonBox-info{
border:1px solid #D0D0D0;
border-top: none;
border-radius: 0px 0px 4px 4px;
padding:20px 38px;
}
}
.commonBox .commonBox-title.boxTitle{ .commonBox .commonBox-title.boxTitle{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
height: 55px;
line-height: 55px;
background: #FAFCFF;
border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23);
} }
.synchronism{ .synchronism{
display: block; display: block;
height: 34px; height: 26px;
line-height: 34px; line-height: 26px;
padding:0px 15px; padding:0px 15px;
color: #fff!important; color: #fff!important;
background-color: #28BD6C; background-color: #28BD6C;
@ -620,19 +583,10 @@
.files_info{ .files_info{
cursor: pointer; cursor: pointer;
} }
.commonBox { .commonBox .commonBox-info{
.commonBox-info{ padding:20px 15px;
padding:20px 15px;
}
}
.commonBox-title-read{
vertical-align: middle;
color: #000;
font-size: 14px;
&:hover {
color: #466AFF;
}
} }
.commonBox-title-read{vertical-align: middle;color: #666;}
@media screen and (max-width: 370px){ @media screen and (max-width: 370px){
.p-r-tags,.p-r-btn{ .p-r-tags,.p-r-btn{
@ -673,7 +627,9 @@
.item:last-child{ .item:last-child{
border-bottom:none; border-bottom:none;
} }
.gitAddressClone{
margin: 0 !important;
}
.item_title small{ .item_title small{
font-weight: 400; font-weight: 400;
margin-left: 10px; margin-left: 10px;
@ -722,84 +678,12 @@ a.color-grey-ccc:hover{
padding:0px 30px; padding:0px 30px;
min-height: 400px; min-height: 400px;
} }
.commitList > div{
.main{ border-bottom: 1px solid #EEEEEE;
margin: 30px auto; padding:16px 0px;
.ant-timeline{ }
margin-top: 28px; .commitList > div:last-child{
.commitList-item{ border-bottom: none;
position: relative;
padding: 20px 20px;
background: #FAFCFF;
border: 1px solid rgba(42, 97, 255, 0.23);
border-radius: 4px;
margin-left: 16px;
& .treecopy{
margin-top: 20px;
}
& .markdown-body table{
background: #FAFCFF;
}
&:after,&:before{
content: "";
position: absolute;
left: -10px;
top: 10px;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 10px solid rgba(42, 97, 255, 0.23);
}
&:after{
left: -8px;
border-right: 10px solid #FAFCFF;
&:hover{
border-right: 10px solid #EEF6FF;
}
}
&:hover{
background: #EEF6FF;
border: 1px solid rgba(42, 97, 255, 0.58);
&:after{
border-right: 10px solid #EEF6FF;
}
&:before{
border-right: 10px solid rgba(42, 97, 255, 0.58);
}
& .markdown-body table{
background: #EEF6FF;
}
}
.treecopy-cont{
padding: 4px 15px;
}
.btn-83{
margin-left: 20px;
}
}
.ant-timeline-item{
padding: 8px 0 20px;
}
.ant-timeline-item-tail{
height: calc(100% - 20px);
border-left: 2px solid #EEEEEE;
top: 12px;
&:after{
content: ' ';
height: 0;
position: absolute;
width: 0;
border: 7px solid transparent;
border-top-color: #EEEEEE;
top: 100%;
left: 50%;
margin-left: -8px;
}
}
.ant-timeline-item-head-custom{
top:20px;
padding: 0 1px;
}
}
} }
@ -848,13 +732,4 @@ a.color-grey-ccc:hover{
text-align: center; text-align: center;
display: flex; display: flex;
justify-content: center; justify-content: center;
}
.depotNum{
color: #666!important;
span:last-child{
color: #333;
}
&:hover span:last-child{
color: #2A61FF;
}
} }

View File

@ -1,103 +0,0 @@
import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '/home/gitlink/forgeplus/public/react/forgeplus-react/src/forge/Component/layout';
import { Link } from 'react-router-dom';
import { Popover , Spin , Button } from 'antd';
import { getImageUrl } from 'educoder';
import '/home/gitlink/forgeplus/public/react/forgeplus-react/src/forge/Component/Component.scss';
// projectDetail && projectDetail.contributors && projectDetail.contributors.total_count >0 &&
// <Badge contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />?
function Badge({badges,owner}){
const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0);
const [ menu , setMenu ] = useState("");
const [ login , setLogin ] = useState(undefined);
const [ badge , setBadge ] = useState(undefined);
useEffect(()=>{
if(badges && badges.total_count>0){
setTotal(badges.total_count);
setList(badges.badge);
}
},[badges])
useEffect(()=>{
setMenusFunc(badge);
},[badge])
function setMenusFunc(data){
if(data){
let ele = (
<AlignCenter>
<Link to={`/${data.login}`}><img src={data.image_url} alt="" className="radius" width="38px" height="38px"/></Link>
<div className="ml10">
<Link to={`/${data.login}`}>{data.name}</Link>
{ data.description && <span className="leftline">{data.description}</span> }
</div>
</AlignCenter>
)
setMenu(ele);
}
}
function setVisibleFunc(flag,l,index){
if(l !== badge){
setBadge(l);
}
var lx = list.concat();
lx.map(i=>i.visible =false);
if(flag){
lx[index].visible = flag;
}
lx.splice();
setList(lx);
}
// {
// "list": [
// {
// "login": "many_stars",
// "image_url": "User",
// "description": "test description"
// },
// {
// "login": "many_stars",
// "image_url": "User",
// "description": "test description"
// }
// ],
// "total_count": 2
// }
return(
<div className="halfs">
<Link to={`/${owner}/badge`} className="font-16 color-ooo hoverA">
<span>徽章</span>
{ badges && badges.total_count > 0 && <span className="infoCount">{badges.total_count}</span>}
</Link>
<div className="attrBadge" onMouseLeave={()=>setVisibleFunc(false)}>
{
total > 0 ?
list.map((item,key)=>{
return(
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
<Link key={key} to={`/${item.login}`}>
<img src={item.image_url} alt="" onMouseOver={()=>setVisibleFunc(true,item,key)}/>
</Link>
</Popover>
)
})
:""
}
</div>
</div>
)
}
//{getImageUrl(`/${item.image_url}`)}
export default Badge;

View File

@ -52,7 +52,7 @@ function Contribute(props){
<AlignCenter> <AlignCenter>
<img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`/${item.image_url}`)} width="50px" height="50px"/> <img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`/${item.image_url}`)} width="50px" height="50px"/>
<div> <div>
<Link to={`/${item.login}`} className="font-16">{item.name}</Link> <Link to={`/users/${item.login}`} className="font-16">{item.name}</Link>
<p className="font-12 color-grey-9">提交{item.contributions}</p> <p className="font-12 color-grey-9">提交{item.contributions}</p>
</div> </div>
</AlignCenter> </AlignCenter>

View File

@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Skeleton , Tooltip} from 'antd'; import { Skeleton , Tooltip} from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { numFormat } from 'educoder';
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){ function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
const [ menuName , setMenuName ] = useState(undefined); const [ menuName , setMenuName ] = useState(undefined);
@ -11,76 +10,66 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
if(pathname && pathname==="source"){ if(pathname && pathname==="source"){
let a = list.filter(item=>item.menu_name === "resources"); let a = list.filter(item=>item.menu_name === "resources");
if(a && a.length === 0){ if(a && a.length === 0){
history.push(`/${owner}/${projectsId}`); history.push(`/projects/${owner}/${projectsId}`);
} }
} }
setMenuName(list); setMenuName(list);
} }
},[list]); },[list]);
return( return(
<div className="f-wrap-between mt25"> <div className="f-wrap-between mt15">
{ {
menuName && projectDetail ? menuName && projectDetail ?
<ul className="headerMenu-wrapper"> <ul className="headerMenu-wrapper">
{ {
Array.isArray(menuName)&& menuName.map((item,key)=>{ menuName.map((item,key)=>{
return( return(
<React.Fragment key={item.menu_name}> <React.Fragment>
{ {
item.menu_name === "home" && item.menu_name === "home" &&
<li className={pathname==="about" ? "active" : ""}> <li className={pathname==="about" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/about`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
<i className={"iconfont icon-zhuye-fill color-grey-3 mr5 font-14"}></i> <i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
<span>主页</span> <span>主页</span>
</Link> </Link>
</li> </li>
} }
{ {
item.menu_name === "code" && item.menu_name === "code" &&
<li className={(pathname==="" || urlFlag) ? "active" : ""}> <li className={(pathname==="" || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
<i className={"iconfont icon-daimakuicon1 color-grey-3 mr5 font-14"}></i> <i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
<span>代码库</span> <span>代码库</span>
</Link> </Link>
</li> </li>
} }
{ {
item.menu_name === "issues" && item.menu_name === "issues" &&
<li className={pathname==="issues" ? "active" : ""}> <li className={pathname==="issues" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/issues`, state }}> <Tooltip title="易修是Issue的中文名即问题列表" placement="bottom">
<Tooltip title="易修是Issue的中文名即问题列表" placement="bottom"> <Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<i className={"iconfont icon-yixiuicon1 color-grey-3 mr5 font-14"}></i> <i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
<span>易修(Issue)</span> <span>易修</span>
</Tooltip> {projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
{projectDetail && projectDetail.issues_count ? <span className="num">{numFormat(projectDetail.issues_count)}</span> : ""}
</Link> </Link>
</Tooltip>
</li> </li>
} }
{ {
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ? item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
<li className={pathname==="pulls" ? "active" : ""}> <li className={pathname==="pulls" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/pulls`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
<i className={"iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14"}></i> <i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
<span>合并请求</span> <span>合并请求</span>
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{numFormat(projectDetail.pull_requests_count)}</span> : ""} {projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
</Link> </Link>
</li>:"" </li>:""
} }
{
item.menu_name === "wiki" &&
<li className={pathname === "wiki" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/wiki`, state }}>
<i className={"iconfont icon-a-wikiicon1 color-grey-3 mr5 font-14"}></i>
<span>Wiki</span>
</Link>
</li>
}
{ {
item.menu_name === "devops" && platform ? item.menu_name === "devops" && platform ?
<li className={pathname==="devops" ? "active" : ""}> <li className={pathname==="devops" ? "active" : ""}>
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */} <Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}>
<Link to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}> <i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>工作流(beta版)
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""} {projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link> </Link>
</li> </li>
@ -89,37 +78,37 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
{/* { {/* {
item.menu_name === "resources" && item.menu_name === "resources" &&
<li className={pathname==="source" ? "active" : ""}> <li className={pathname==="source" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/source`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/source`, state }}>
<i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i> <i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i>
<span>资源库</span> <span>资源库</span>
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""} {projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
</Link> </Link>
</li> </li>
} */} } */}
{ {
item.menu_name === "versions" && item.menu_name === "versions" &&
<li className={pathname==="milestones" ? "active" : ""}> <li className={pathname==="milestones" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/milestones`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
<i className={pathname==="milestones" ? "iconfont icon-lichengbeiicon color-grey-3 mr5 font-14":"iconfont icon-lichengbeiicon color-grey-6 font-14 mr5"}></i> <i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
<span>里程碑</span> <span>里程碑</span>
{projectDetail && projectDetail.versions_count ? <span className="num">{numFormat(projectDetail.versions_count)}</span> :""} {projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
</Link> </Link>
</li> </li>
} }
{ {
item.menu_name === "activity" && item.menu_name === "activity" &&
<li className={pathname==="activity" ? "active" : ""}> <li className={pathname==="activity" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/activity`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
<i className={pathname==="activity" ? "iconfont icon-dongtaiicon color-grey-3 mr5 font-14":"iconfont icon-dongtaiicon color-grey-6 font-14 mr5"}></i> <i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
<span>动态</span> <span>动态</span>
</Link> </Link>
</li> </li>
} }
{ {
item.menu_name === "settings" && item.menu_name === "setting" &&
<li className={pathname === "settings" ? "active" : ""}> <li className={pathname === "setting" ? "active" : ""}>
<Link to={`/${owner}/${projectsId}/settings`}> <Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url && url.indexOf("/settings") > 0 ? "iconfont icon-cangkushezhiicon color-grey-3 mr5 font-14":"iconfont icon-cangkushezhiicon color-grey-6 font-14 mr5"}></i> <i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
<span>仓库设置</span> <span>仓库设置</span>
</Link> </Link>
</li> </li>

View File

@ -1,15 +1,26 @@
import React from 'react'; import React from 'react';
import { Tooltip , message } from 'antd';
import './sub.scss'; import './sub.scss';
import CopyTool from '../../Component/CopyTool';
function Invite({code,className}) { function Invite({code,className}) {
function jsCopy(id) {
const copyEle = document.querySelector(id); //
const range = document.createRange(); // range
window.getSelection().removeAllRanges(); //selection
range.selectNode(copyEle); //
window.getSelection().addRange(range); //
document.execCommand("Copy"); // copy
message.success('复制成功');
}
return( return(
<div className={className}> <div className={className}>
<span className="font-16 color-ooo">邀请码</span> <span className="font-16 color-grey-6">邀请码</span>
<div> <div>
<input value={code} id="devitecode" style={{width:"62px",border:"none",cursor:"default"}} readOnly/> <span id="devitecode">{code}</span>
<CopyTool timeOut={true} beforeText={<p className="edu-txt-center">可以通过邀请码邀请成员加入项目<br/>点击复制邀请码</p>} className="ml8 font-16" inputId="devitecode"/> <Tooltip title={<p className="edu-txt-center">可以通过邀请码邀请成员加入项目<br/>点击复制邀请码</p>} placement={"bottom"}>
<i className="iconfont icon-fuzhi2 font-16 color-blue ml8" onClick={()=>jsCopy("#devitecode")}></i>
</Tooltip>
</div> </div>
</div> </div>
) )

View File

@ -1,57 +0,0 @@
import React , { useState } from 'react';
import { Anchor , Input } from 'antd';
import './sub.scss';
import { useEffect } from 'react';
const { Link } = Anchor;
function ReadmeCatelogue({ menuList , hash }) {
const [ goHref , setGoHref ] = useState("");
const [ value , setValue ] = useState("");
const [ menu , setMenu] = useState(menuList);
function onChange(link){
setGoHref(link);
};
function changeValue(e) {
setValue(e.target.value);
if(e.target.value){
let m = menuList.filter(i=>i.text.toLowerCase().indexOf(e.target.value.toLowerCase())>-1);
setMenu(m);
}else{
setMenu(menuList);
}
}
return(
<div>
<div className="searchBox">
<Input
placeholder={"请输入关键字"}
value={value}
onChange={changeValue}
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}/>
</div>
{
menu && menu.length>0?
<div className="anchorBox">
<Anchor affix={false} onChange={onChange}>
{
menu.map((item,key)=>{
return(
<div style={{paddingLeft:`${item.level *10}px`}} className={goHref===item.href?"items active":"items"}>
<Link href={`#${item.text}`} title={item.text} />
</div>
)
})
}
</Anchor>
</div>
:""
}
</div>
)
}
export default ReadmeCatelogue;

View File

@ -1,13 +0,0 @@
import React from 'react';
import { Link } from 'react-router-dom';
import'./sub.scss'
function SubMenu({tab,owner,projectsId}) {
return(
<ul className="subMenu">
<Link to={`/${owner}/${projectsId}/tags`} className={tab==="tags"?"active":""}>标签</Link>
<Link to={`/${owner}/${projectsId}/releases`} className={tab==="releases"?"active":""}>发行版</Link>
</ul>
)
}
export default SubMenu;

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