Merge branch 'gitlink_server' of http://106.75.45.236:3000/Gitlink/forgeplus-react into feature_GLCC

This commit is contained in:
何童崇 2022-05-20 14:26:56 +08:00
commit d088e1a2e1
32 changed files with 1010 additions and 19 deletions

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2340181 */
src: url('iconfont.woff2?t=1652870557319') format('woff2'),
url('iconfont.woff?t=1652870557319') format('woff'),
url('iconfont.ttf?t=1652870557319') format('truetype');
src: url('iconfont.woff2?t=1652927945088') format('woff2'),
url('iconfont.woff?t=1652927945088') format('woff'),
url('iconfont.ttf?t=1652927945088') format('truetype');
}
.iconfont {

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,6 +7,7 @@
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
<meta name="theme-color" content="#000000">
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">

View File

@ -25,7 +25,7 @@ if (isDev) {
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'student'
}
window._debugType = debugType;
export function initAxiosInterceptors(props) {

View File

@ -11,7 +11,7 @@ function SystemNotice({showNotice,system_notification,history,login,hideSystemNo
useEffect(()=>{
if(system_notification && !system_notification.is_read && showNotice && login){
if((system_notification && !system_notification.is_read) && showNotice && login){
setVisible(true);
}
},[system_notification,login])
@ -22,11 +22,12 @@ function SystemNotice({showNotice,system_notification,history,login,hideSystemNo
axios.post(url,{
system_notification_id:system_notification.id
}).then(result=>{
if(result){
setVisible(false);
hideSystemNotice();
}
}).catch(error=>{})
setVisible(false);
hideSystemNotice();
}).catch(error=>{
setVisible(false);
hideSystemNotice();
})
}else{
setVisible(false);
hideSystemNotice();

View File

@ -129,6 +129,10 @@ const Source = Loadable({
loader: () => import('../Source/Index'),
loading: Loading,
})
const Server = Loadable({
loader: () => import('../Server/Index'),
loading: Loading,
})
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
@ -168,6 +172,8 @@ function checkPathname(projectsId, owner, pathname) {
name = "source"
} else if (url.indexOf(`/wiki`) > -1) {
name = "wiki"
} else if (url.indexOf(`/server`) > -1) {
name = "server"
}
}
return name;
@ -651,6 +657,12 @@ class Detail extends Component {
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 服务 */}
<Route path="/:owner/:projectsId/server"
render={
() => (<Server {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 资源 */}
<Route path="/:owner/:projectsId/source"
render={

View File

@ -228,14 +228,14 @@
li{
text-align: center;
padding:0px;
margin-right: 40px;
margin-right: 35px;
display: flex;
& > a{
position: relative;
font-size: 14px;
height: 36px;
line-height: 24px;
display: block;
display: flex;
color: #000!important;
&> span.num{
line-height: 24px;

View File

@ -8,11 +8,13 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
useEffect(()=>{
if(list){
// banner
if(pathname && pathname==="source"){
let a = list.filter(item=>item.menu_name === "resources");
if(a && a.length === 0){
history.push(`/${owner}/${projectsId}`);
}
let a = list.filter(item=>item.menu_name === "resources");
if((pathname && pathname==="source") && (a && a.length === 0)){
history.push(`/${owner}/${projectsId}`);
}
let b = list.filter(item=>item.menu_name === "server");
if((pathname && pathname.indexOf("server") > 0) && (b && b.length === 0)){
history.push(`/${owner}/${projectsId}`);
}
setMenuName(list);
}
@ -106,6 +108,15 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
</Link>
</li>
}
{
item.menu_name === "services" &&
<li className={pathname === "server" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/server`, state }}>
<i className={"iconfont icon-fuwuicon color-grey-3 mr5 font-15"} style={{marginTop:"1px"}}></i>
<span>服务</span>
</Link>
</li>
}
{
item.menu_name === "activity" &&
<li className={pathname==="activity" ? "active" : ""}>

View File

@ -0,0 +1,34 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import "./index.scss";
import Loadable from 'react-loadable';
import Loading from '../../Loading';
const List = Loadable({
loader: () => import('./List'),
loading: Loading,
})
const Data = Loadable({
loader: () => import('./data'),
loading: Loading,
})
function ServerIndex(props){
return(
<div className="panels">
<Switch {...props}>
<Route path="/:owner/:projectsId/server/:id"
render={
() => (<Data {...props}/>)
}
></Route>
<Route path="/:owner/:projectsId/server"
render={
() => (<List {...props}/>)
}
></Route>
</Switch>
</div>
)
}
export default ServerIndex;

48
src/forge/Server/List.jsx Normal file
View File

@ -0,0 +1,48 @@
import React,{useState , useEffect} from 'react';
import AgreementModal from './agreementModal';
function Main(props){
const [ visible , setVisible ] = useState(false);
const { owner , projectsId } = props.match.params;
const [ has_trace_user , setHas_trace_user ] = useState(false);
const { current_user , resetUserInfo } = props;
useEffect(()=>{
if(current_user){
setHas_trace_user(current_user.has_trace_user);
}
},[current_user])
function onOk(){
setVisible(false);
resetUserInfo && resetUserInfo();
props.history.push(`/${owner}/${projectsId}/server/1`);
}
function openDetail(){
if(!has_trace_user){
setVisible(true);
}else{
props.history.push(`/${owner}/${projectsId}/server/1`);
}
}
return(
<div>
<AgreementModal visible={visible} onCancel={()=>setVisible(false)} onOk={onOk}/>
<ul className="serverlist">
<li>
<span className="servername">
<img src={require('./img/logo.png')} alt=""/>
<a onClick={openDetail}>重晴鸟代码溯源系统</a>
</span>
<p className="task-hide-2 serverdesc">支持软件源代码的溯源分析自主度评估开源漏洞检测开源许可证合规性分析等</p>
<span className="serverbtn">
<a onClick={openDetail} className="btnhover">查看详情</a>
</span>
</li>
</ul>
</div>
)
}
export default Main;

View File

@ -0,0 +1,65 @@
import React, { useState } from 'react';
import { Modal , Checkbox } from 'antd';
import axios from 'axios';
function AgreementModal({ visible , onCancel , onOk}){
const [ agree , setAgree ] = useState(false);
function changeAgree(e){
setAgree(e.target.checked);
}
//
function unAgree(){
setAgree(false);
onCancel();
}
//
function agreeFunc(){
const url = `/traces/trace_users.json`;
axios.post(url).then(result=>{
if(result){
agree && onOk();
setAgree(false);
}
}).catch(error=>{})
}
return(
<Modal
visible={visible}
title="用户协议及声明条款"
onCancel={onCancel}
onOk={onOk}
className="agreementModal"
width="700px"
footer={
<div className="agreeBtn">
<a onClick={unAgree}>不同意</a>
<a className={agree ? "agree btnhover" : 'notagree'} onClick={ agreeFunc}>同意协议</a>
</div>
}
>
<div className="agreementCon">
<div className="agreementDesc">
<p>在使用本系统前请您务必仔细阅读下列条款 本系统的资料信息及其他内容均由国家超级计算无锡中心中国科学院计算技术研究所清华大学和北京大学提供任何人进入本系统阅读本系统所载任何内容从本系统下载任何资料或使用本系统提供的任何资料即表示同意遵守这些条款如果您不同意遵守这些条款请勿继续使用本系统提供方有权对这些条款不时进行更新前述更新之后的条款将在本系统进行公布并自公布之日起生效</p>
<p className="blod">版权声明</p>
<p>本系统所提供任何内容包括但不限于数据文字图表或图象其所有权著作权及其他权利均由提供方享有前述权利受中华人民共和国的法律法规规章规范性法律文件及相关国际条约的保护对前述权利的任何侵犯行为均有可能导致民事行政或刑事责任一切后果均由侵权行为人承担未经提供方事先书面许可您不得以任何方式复制修改传播出版转载或展示本系统的任何内容</p>
<p>本系统采用但非本系统原创的所有内容其版权归版权所有人所有转载的部分内容源自其他系统因无法和版权权利人联系如果您是前述内容的版权权利人请与我们联系并提供证明材料和详实说明我们将及时加注版权信息如果您提出异议我们将立即撤除任何涉及版权问题的内容对于独家授权本系统提供的任何内容如您需要转载应当事先得到本系统和版权所有人的同意</p>
<p className="blod">引用本系统内容</p>
<p>1. 在遵守国家法律以及本协议的情况下您可以出于非商业目的浏览下载本系统的内容如出于商业目的使用拷贝下载存储通过硬盘拷贝或电子抓取系统发送转换演示传播出版本系统的任何内容或创造与前述内容有关的演绎作品或衍生产品则必须事先经过提供方的书面许可并在使用时注明来源和版权标记</p>
<p>2. 如果您需要使用本系统包含的由任何其他主体提供的内容请直接与版权权利人联系</p>
<p className="blod">免责条款</p>
<p>对本系统的内容我们已尽最大努力审核但对于内容的正确性完整性及时性有效性稳定性可用性不侵犯他人权利等方面不提供任何形式无论明示或默示的保证我们不保证服务器的稳定性任何由于黑客入侵或攻击计算机病毒侵入或发作因政府管制而造成的暂时性关闭等影响网络正常经营的不可抗力而造成的资料泄露丢失被盗用或被篡改等本系统均得免责我们不保证您在任何时候均可浏览阅读使用本系统不保证本系统的内容不存在打印复制及其他输入方面的错误提供方有权随时更改本系统任何内容 在任何情况下对于无法进入本系统或无法使用本系统内容而导致的任何直接的间接的附带的给第三人造成的损失(包括但不限于利润损失信息数据丢失财产毁坏损失)提供方均不承担任何责任 本系统提供的站外链接仅为用户提供方便但链接的系统不属于本系统的控制范围或管理范畴故提供方对链接系统所传送或登载的任何形式的内容不承担任何责任 任何用户在本系统发表的商业信息个人信息留言以及其他信息均不代表本系统以及提供方的立场且与本系统与提供方无关相关责任由作者完全承担本系统有权对上述商业信息个人信息留言以及其他信息随时进行删除</p>
<p>本系统支持用户在使用本系统系统过程中的合法经营行为但因用户的作为或不作为所造成的后果概由用户自行承担</p>
<p className="blod">隐私保护声明</p>
<p>本系统承诺按照相关法律的规定本系统的隐私政策保护本系统收集的用户个人信息我们建议您认真阅读本隐私保护声明</p>
<p className="blod">适用法律与争议解决</p>
<p>因本公告或使用本系统所发生的争议适用中华人民共和国法律因本公告或使用本系统发生争议应当协商解决协商不成的由本公司所在地人民法院受理解决</p>
<p className="blod">终止协议或退出服务</p>
<p>如果您希望不再使用本系统提供的服务或者您不同意上述条款及更新内容您可以选择终止协议或者退出服务具体请联系客服人员</p>
</div>
<Checkbox checked={agree} onChange={changeAgree}>我已阅读并同意用户协议及声明条款</Checkbox>
</div>
</Modal>
)
}
export default AgreementModal;

184
src/forge/Server/data.jsx Normal file
View File

@ -0,0 +1,184 @@
import React, { useEffect, useState } from 'react';
import DataEmpty from './dataEmpty';
import DetectionModal from './detectionModal';
import { Table , Spin, message } from 'antd';
import axios from 'axios';
function Data(props){
const [ detectionVisible , setDetectionVisible ] = useState(false);
const [ dataSource , setDataSource ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ spining , setSpining ] = useState(true);
const [ relayCount , setRelayCount ] = useState(5);
const [ repeatId , setRepeatId ] = useState(undefined);
const [ repeatBranch , setRepeatBranch ] = useState(undefined);
const { owner , projectsId } = props.match.params;
const { current_user , isManager } = props;
const limit = 15;
function onDetectionOk(){
props.showNotification("扫描成功!");
setDetectionVisible(false);
setSpining(true);
Init();
}
function Init(){
const url = `/traces/${owner}/${projectsId}/task_results.json`;
axios.get(url,{
params:{
page,limit
}
}).then(result=>{
if(result){
setDataSource(result.data.data);
setRelayCount(result.data.left_tasks_count);
setSpining(false);
}
}).catch(error=>{})
}
useEffect(()=>{
setSpining(true);
Init();
},[])
//
function repeatCheck(project_id,branch){
if(relayCount <= 0){
message.error("无可用检测次数");
return;
}
setRepeatId(project_id);
setRepeatBranch(branch);
setDetectionVisible(true);
}
function createCheck(){
if(relayCount <= 0){
message.error("无可用检测次数");
return;
}
setRepeatBranch(undefined);
setRepeatId(undefined);
setDetectionVisible(true);
}
function handleDownExcel(task_id){
setSpining(true);
const url = `/api/traces/${owner}/${projectsId}/task_pdf.json?task_id=${task_id}`;
// window.open(`/api/traces/${owner}/${projectsId}/task_pdf.json?task_id=${task_id}`);
const x = new XMLHttpRequest();
x.open('GET', url, true)
x.responseType = 'blob';
x.onload = (e) => {
// DOMStringURL URL document URL File Blob
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = url;
a.download = "report.pdf";
a.click();
setSpining(false);
}
x.send();
console.log("spining");
}
return(
<div>
<DetectionModal
visible={detectionVisible}
onCancel={()=>setDetectionVisible(false)}
onOk={onDetectionOk}
owner={owner}
projectsId={projectsId}
relayCount={relayCount}
repeatId={repeatId}
repeatBranch={repeatBranch}
/>
<div className="servertitle">
<span className="systitle">重晴鸟代码溯源系统</span>
{ isManager && <a className="btnhover" onClick={createCheck}>新建分析</a> }
</div>
<Spin spinning={spining}>
<div style={{minHeight:"400px"}}>
{
dataSource && dataSource.length >0 &&
<div>
<ul className="dataUl">
<li className="dataUlhead">
<span>序号</span>
<span>分支名称</span>
<span>检测状态</span>
<span>检测时间</span>
{ isManager && <span>操作</span> }
</li>
{
dataSource.map((e,key)=>{
return(
<div key={key}>
<li className="dataUlbody">
<span>{key + 1 }</span>
<span title={e.branch_tag}>{e.branch_tag}</span>
<span>
{
e.detect_status === "fail" ?
<span className="failure">失败</span>
: e.detect_status==="detecting" ?
<div className="running">
<span className="percentline" style={{width:`${e.detect_process}%`}}></span>
<span className="percentNum" style={{left:`${e.detect_process+5}%`}}>{e.detect_process}%</span>
</div>
:
<span className="success">成功</span>
}
</span>
<span>{e.detect_startdate}</span>
{
isManager &&
<span>
<div className="operationBtns">
{
e.detect_status ==="detecting" ?
<span>重新扫描</span>
:
<a onClick={()=>repeatCheck(e.project_id,e.branch_tag)}>重新扫描</a>
}
{/* {
(e.detect_status ==="fail" || e.detect_status ==="detecting") ?
<span>查看<i className="iconfont icon-sanjiaoxing-down"></i></span>
:
<a>查看<i className="iconfont icon-sanjiaoxing-down"></i></a>
} */}
{
(e.detect_status ==="fail" || e.detect_status ==="detecting") ?
<span>下载报告</span>
:
<a onClick={()=>handleDownExcel(e.task_id)}>下载报告</a>
}
</div>
</span>
}
</li>
{false && <iframe src="www.baidu.com" id={`htmlIframe_${key}`} frameBorder="0" name={`htmlIframe_${key}`} style={{ background: '#fff', height: '100%', width: '100%' }}></iframe>}
</div>
)
})
}
</ul>
</div>
}
{
(dataSource === null || (dataSource && dataSource.length === 0)) &&
<DataEmpty />
}
</div>
</Spin>
</div>
)
}
export default Data;

View File

@ -0,0 +1,18 @@
import React from 'react';
import { Divider} from 'antd';
function DataEmpty(props){
return(
<div className="dataEmpty">
<div className="dataemptyCon">
<img src={require('./img/nullicon.png')} width="68px" alt=""/>
<span className="nullTitle">暂无数据</span>
<p className="nullDesc">重睛鸟代码溯源及安全审查系统是一款完全自主面向主流语言的代码审查大数据平台主要功能包含软件源代码的溯源分析自主度评估开源漏洞检测开源许可证合规性分析支持分析结果多层次可视化展示等可用于提高软件代码的可控性与安全性</p>
<Divider />
<p className="nullSubDesc">对每个仓库可进行代码检测总次数仅为 <span style={{color:"rgba(70, 106, 255, 1)",fontSize:"20px"}}>5</span> </p>
</div>
</div>
)
}
export default DataEmpty;

View File

@ -0,0 +1,162 @@
import React, { useState , forwardRef, useEffect } from 'react';
import { Modal , Form , Select } from 'antd';
import axios from 'axios';
function DetectionModal({form , visible , onCancel , onOk , projectsId, owner , relayCount , repeatId , repeatBranch }){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const [ check , setCheck ] = useState(false);
const [ branch , setBranch ] = useState("");
const [ branchList , setBranchList ] = useState([]);
const source = axios.CancelToken.source();
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
useEffect(()=>{
if(visible && owner && projectsId){
const url = `/${owner}/${projectsId}/branches.json`;
axios.get(url).then(result=>{
if(result){
setBranchList(result.data);
}
}).catch(error=>{})
}
},[owner,projectsId,visible])
//
function onCancelFunc(){
source.cancel();
if(check) {
setCheck(false);
} else{
onCancel();
}
}
//
function onOkFunc(){
validateFields((error,values)=>{
if(!error){
setCheck(true);
setBranch(values.branch);
if(repeatId){
//
const url = `/traces/${owner}/${projectsId}/reload_task.json`;
axios.get(url,{
params:{
project_id:repeatId,
branch_name:repeatBranch
}
},{
CancelToken:source.token
}).then(result=>{
if(result){
onOk();
}
setCheck(false);
}).catch(error=>{})
}else{
//
const url = `/traces/${owner}/${projectsId}/tasks.json`;
axios.post(url,{
branch_name:values.branch
},{
CancelToken:source.token
}).then(result=>{
if(result){
onOk();
}
setCheck(false);
}).catch(error=>{})
}
}
})
}
return(
<Modal
visible={visible}
title=""
onCancel={onCancel}
className="agreementModal"
width="635px"
footer={
<div className="agreeBtn">
<a onClick={onCancelFunc}>取消</a>
{ !check && relayCount !== 0 && <a className={"agree btnhover"} onClick={onOkFunc}>开始检测</a> }
</div>
}
>
<div>
<div className="detectionAnimation">
<ul className={check ? "animationUl action" : "animationUl" }>
<li><img src={require('./img/1.png')} width="166px" alt=""/></li>
<li><img src={require('./img/2.png')} width="136px" alt=""/></li>
<li><img src={require('./img/3.png')} width="96px" alt=""/></li>
<li><img src={require('./img/4.png')} width="96px" alt=""/></li>
<li><img src={require('./img/5.png')} width="15px" alt=""/></li>
<li><img src={require('./img/6.png')} width="25px" alt=""/></li>
<li><img src={require('./img/7.png')} width="1px" alt=""/></li>
</ul>
{
check ?
<p className="lastTimes">正在开启检测请等待...</p>
:
<p className="lastTimes">剩余扫描次数<span>{relayCount}</span></p>
}
</div>
<div className="formDiv">
<Form {...layout}>
{
!check && !repeatBranch &&
<Form.Item label="检测分支" colon={false} labelAlign={"left"}>
{getFieldDecorator("branch",{
rules:[{required:true,message:"请选择要检测的分支"}]
})(
<Select placeholder="请选择仓库分支" showSearch style={{width:"360px"}}>
{
branchList && branchList.length >0 ?
branchList.map((i,k)=>{
return(
<Select.Option value={i.name}>{i.name}</Select.Option>
)
})
:
<Select.Option value={""}>暂无分支</Select.Option>
}
</Select>
)}
</Form.Item>
}
<div className="checkInfos">
{
((check && branch) || repeatBranch) &&
<div>
<span>检测分支</span>
<p className="task-hide" title={branch || repeatBranch}>{branch || repeatBranch}</p>
</div>
}
<div>
<span>检测类型</span>
<p>快速-组件级</p>
</div>
<div>
<span>检测参数</span>
<div style={{flex:1}}>
<p>解析层级2</p>
<p>最小解析文件行数10</p>
<p>许可证检测类型开源软件</p>
<span className="color-grey-6">文件相似阈值</span>
<ul>
<li>行数20</li>
<li>相似比例50%</li>
</ul>
</div>
</div>
</div>
</Form>
</div>
</div>
</Modal>
)
}
export default Form.create()(forwardRef(DetectionModal));

BIN
src/forge/Server/img/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
src/forge/Server/img/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
src/forge/Server/img/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/forge/Server/img/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
src/forge/Server/img/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

BIN
src/forge/Server/img/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

BIN
src/forge/Server/img/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

BIN
src/forge/Server/img/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

454
src/forge/Server/index.scss Normal file
View File

@ -0,0 +1,454 @@
.panels{
width: 1200px;
margin:20px auto;
}
.btnhover{
background-color: #466aff;
color: #fff!important;
&:hover{
background-color: rgba(26, 71, 255, 1)!important;
color: #fff!important;
}
}
.servertitle{
display: flex;
align-items: center;
background-color:#fafcff;
border:1px solid rgba(42, 97, 255, 0.23);
border-radius:3px 3px 0px 0px;
justify-content: space-between;
padding:12px 16px;
.systitle{
font-weight:500;
color:#333333;
font-size:16px;
}
a{
width:88px;
height:36px;
line-height: 36px;
background-color:#466aff;
border-radius:5px;
text-align: center;
}
}
.dataEmpty{
margin-top: 25px;
background-color:#fafcff;
border-radius:4px 4px 0px 0px;
min-height: 418px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.dataemptyCon{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 665px;
text-align: center;
.nullTitle{
font-size: 22px;
height: 30px;
line-height: 30px;
margin:15px 0px 28px!important;
color: #333;
}
.nullDesc{
color:#666666;
font-size:14px;
line-height:28px;
}
.ant-divider{
min-width: 500px;
width: 500px;
border-top:1px solid rgba(90, 117, 193, 0.23);
margin:18px 0px!important;
height: 0px;
}
.nullSubDesc{
color:#333333;
font-size:16px;
}
}
}
.agreementModal{
.ant-modal-header{
padding:0px ;
height: 56px;
background:url('./img/modaltitle.png') 100% 100% ;
color: #fff;
.ant-modal-title{
color: #fff;
height: 56px;
line-height: 56px!important;
color: #fff;
}
}
.ant-modal-close{
top:0px!important;
color: #fff;
}
.ant-modal-body{
padding:0px;
}
.agreementCon{
height: 400px;
overflow-y: auto;
padding:20px;
p{
line-height: 26px;
font-size: 15px;
color: #333;
margin-bottom: 8px!important;
&.blod{
font-weight:500;
color: #000;
}
}
}
.agreeBtn{
display: flex;
align-items: center;
height: 67px;
justify-content: center;
a{
display: block;
height:36px;
line-height: 34px;
margin:0px 20px;
background-color:#ffffff;
border:1px solid;
border-color:#d0d0d0;
border-radius:4px;
width: 120px;
text-align: center;
color:#666666;
font-size:15px;
&.notagree{
background-color:rgba(177, 192, 255, 1);
border-color:rgba(177, 192, 255, 1);
color: #fff!important;
cursor: default;
}
&.agree{
background-color:#466aff;
border-color:rgba(177, 192, 255, 1);
color: #fff!important;
}
}
}
}
.detectionAnimation{
height: 240px;
width: 100%;
background-image: url('./img/detectionBG.png');
background-size: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.animationUl{
width: 166px;
height: 166px;
position: relative;
&.action li{
-webkit-animation: App-logo-spin infinite 5s linear;
animation: App-logo-spin infinite 5s linear;
}
li{
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
&:last-child{
align-items: flex-end;
height: 96px;
bottom: 36px;
}
}
}
@keyframes App-logo-spin {
from{
transform:rotate(0deg);
}
to {
transform:rotate(360deg);
}
}
.lastTimes{
color: #fff;
margin-top: 6px;
height: 30px;
line-height: 30px;
display: flex;
span{
font-size: 20px;
margin-left: 8px;
}
}
}
.dataTable,.dataUl{
.ant-table-thead > tr > th{
background-color: #fff;
div{
color: rgba(51, 51, 51, 1);
font-size: 16px;
}
}
.ant-table-tbody > tr:hover > td{
background-color: rgba(248, 250, 255, 1)!important;
}
.failure{
display: block;
height:32px;
line-height:32px;
background-color:rgba(230, 0, 6, 0.1);
border:1px solid;
border-color:#fcb6c2;
border-radius:4px;
color: rgba(255, 12, 12, 1);
width:58px;
text-align: center;
}
.success{
display: block;
height:32px;
line-height:32px;
background-color:rgba(83, 255, 163, 0.1);
border:1px solid;
border-color:rgba(0, 184, 67, 1);
border-radius:4px;
color: rgba(0, 156, 68, 1);
width:58px;
text-align: center;
}
.running{
position: relative;
width: 137px;
height: 22px;
background-color: rgba(75, 75, 75, 0.1);
border-radius:26px;
span.percentline{
position: absolute;
left: 0px;
top:0px;
height: 100%;
background-color: rgba(80, 156, 255, 1);
border-radius:26px;
text-align: center;
line-height: 24px;
color: rgba(51, 51, 51, 1);
}
}
.percentNum{
position: absolute;
height: 24px;
line-height: 24px;
}
.operationBtns{
display: flex;
align-items: center;
justify-content: center;
a,span{
margin:0px 14px;
position: relative;
color: rgba(70, 106, 255, 1);
display: flex;
align-items: center;
height: 26px;
}
span{
color: rgba(197, 204, 225, 1)!important;
cursor: default;
}
a > i,span>i{
width: 13px;
}
a::before,span::before{
position: absolute;
content: "";
width: 1px;
height: 12px;
top:7px;
background-color: rgba(213, 213, 213, 1);
left: -14px;
}
a:first-child::before,span:first-child::before{
display: none;
}
}
}
.dataUl{
&>div{
border-bottom: 1px solid #eee;
}
li{
display: flex;
flex-wrap: wrap;
height: 66px;
align-items: center;
color:#333333;
&>span{
padding:0px 10px;
text-align: left;
}
&>span:first-child{
width: 7%;
text-align: center;
}
&>span:nth-child(2){
width: 30%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&>span:nth-child(3){
flex:1;
}
&>span:nth-child(4){
width: 16%;
}
&>span:last-child{
width: 30%;
text-align: center;
}
&.dataUlhead{
font-size:16px;
}
&.dataUlbody{
font-size: 14px;
&:hover{
background-color:#f8faff
}
}
}
}
.formDiv{
width: 430px;
margin:0px auto;
padding:20px 0px;
.has-error .ant-form-explain{
position: absolute;
bottom: -15px;
}
.ant-form-item-label{
width: 70px;
height: 32px;
line-height: 32px;
margin-top: 4px;
label{
color:#20294a;
font-size:15px;
}
}
.ant-row.ant-form-item{
margin-bottom: 12px!important;
}
.ant-form-item-required::before{
display: none;
}
.checkInfos{
&>div{
display: flex;
&>span{
display: block;
width: 70px;
line-height: 32px;
text-align: left;
color:#20294a;
font-size:15px;
}
ul{
display: flex;
margin-top: 15px;
li:first-child{
margin-right: 30px;
}
}
p,ul>li{
height: 32px;
line-height: 32px;
padding:0px 12px;
background-color:#f5f7ff;
border-radius:4px;
color:#666666;
margin-bottom: 15px!important;
flex:1
}
}
}
}
.serverlist{
display: flex;
flex-wrap: wrap;
min-height: 500px;
align-content: flex-start;
li{
width: 368px;
margin-right: 36px;
height: 198px;
background-image:url('./img/bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
margin-bottom: 20px!important;
padding:30px 40px 0px 40px;
position: relative;
&:nth-child(3n+1){
margin-left: -10px;
}
&:nth-child(3n){
margin-right: -10px;
}
.servername{
display: flex;
align-items: center;
margin-bottom: 12px;
img{
margin-right: 8px;
width: 42px;
}
a{
font-weight:500;
color:#466aff;
font-size:17px;
}
}
&:hover{
.serverbtn{
opacity: 1;
}
}
.serverdesc{
-webkit-line-clamp: 3;
line-height: 25px;
color:#525662;
font-size:15px;
}
.serverbtn{
position: absolute;
height: 56px;
background-color: transparent;
bottom: 10px;
left: 10px;
right: 10px;
display: flex;
justify-content: center;
padding: 10px;
opacity: 0;
transition: 0.3s;
a{
display: block;
width: 224px;
height: 36px;
line-height: 36px;
text-align: center;
border-radius: 4px;
}
}
}
}

View File

@ -18,6 +18,7 @@ const menu = [
// {name:"资源库",index:"resources"},
{name:"里程碑",index:"versions"},
{name:"维基 (Wiki)",index:"wiki"},
{name:"服务",index:"services"},
{name:"动态",index:"activity"},
]
class Setting extends Component {

View File

@ -102,7 +102,7 @@ class Infos extends Component {
}else if(pathname === `/${username}/followers`){
this.setState({menuKey:undefined,route_type:"followers"});
}else{
this.setState({menuKey:undefined,route_type:undefined});
this.setState({menuKey:"6",route_type:undefined});
}
}
@ -249,7 +249,6 @@ class Infos extends Component {
const { current_user } = this.props;
const { username } = this.props.match.params;
const { user, isSpin, route_type , undo_events , menuKey , avatarVisible } = this.state;
return (
<div className="newMain clearfix">
{

View File

@ -226,6 +226,7 @@ export function TPMIndexHOC(WrappedComponent) {
this.setState({
showNotice:false
})
this.getAppdatausr();
}
showCompeleteDialog=()=>{