diff --git a/src/forge/Component/Contributors.jsx b/src/forge/Component/Contributors.jsx index f6dade6a..294fdf03 100644 --- a/src/forge/Component/Contributors.jsx +++ b/src/forge/Component/Contributors.jsx @@ -61,6 +61,11 @@ function Contributors({owner,projectsId,currentLogin}){ return str && str.substr(0,str.length - 1); } + function getBlockchain(userLogin){ + const user = list.filter(item =>{ return item.login === userLogin}); + return user[0] && user[0].contribution_perc; + } + function setMenusFunc(data){ if(data){ let ele = ( @@ -94,6 +99,10 @@ function Contributors({owner,projectsId,currentLogin}){ {data.following_count} 关注数 + {getBlockchain(data.login) && + {getBlockchain(data.login)} + 贡献度 + }
{ diff --git a/src/forge/Issues/Component/comments/list.jsx b/src/forge/Issues/Component/comments/list.jsx index 1bd94875..416deadf 100644 --- a/src/forge/Issues/Component/comments/list.jsx +++ b/src/forge/Issues/Component/comments/list.jsx @@ -187,8 +187,8 @@ function IssueCommentList(props){
{i.user.name} - 回复 - {i.reply_user.name} + {i.reply_user && 回复} + {i.reply_user && i.reply_user.name} {timeAgo(i.created_at)}
{login &&
diff --git a/src/forge/Issues/Component/comments/list.scss b/src/forge/Issues/Component/comments/list.scss index 3ae4c9d5..69fd1cbf 100644 --- a/src/forge/Issues/Component/comments/list.scss +++ b/src/forge/Issues/Component/comments/list.scss @@ -85,7 +85,7 @@ justify-content: space-between; } .commentRenderHtml.markdown-body p{ - font-size: 13px !important; + font-size: 14px !important; } .commentReply{ padding: 15px 0 0 20px; diff --git a/src/forge/Issues/Pages/details.jsx b/src/forge/Issues/Pages/details.jsx index 0bcf7890..df49e5d6 100644 --- a/src/forge/Issues/Pages/details.jsx +++ b/src/forge/Issues/Pages/details.jsx @@ -85,6 +85,7 @@ function Details(props){ const url = `/v1/${owner}/${projectsId}/issues/${index}`; axios.get(url).then(result=>{ if(result && result.data){ + console.log('result', result); let data = result.data; setDetails(data); diff --git a/src/forge/Main/sub/Contribute.jsx b/src/forge/Main/sub/Contribute.jsx index ce14e0ca..1db9f7e5 100644 --- a/src/forge/Main/sub/Contribute.jsx +++ b/src/forge/Main/sub/Contribute.jsx @@ -8,14 +8,25 @@ import { getImageUrl } from 'educoder'; import { Link } from 'react-router-dom'; function Contribute(props){ + console.log('props', props); const [ list , setList ] = useState(undefined); const [ page , setPage ] = useState(1); const [ total , setTotal ] = useState(0); const [ isSpin , setIsSpin ] = useState(true); + const {project} = props; const owner = props.match.params.owner; const projectsId = props.match.params.projectsId; const LIMIT = 20; + + useEffect(()=>{ + if(project){ + // 更改网页标题 + const {name, author} = project; + document.title = `贡献者列表-${author.name}/${name}`; + } + }, [project]) + useEffect(()=>{ if(owner && projectsId){ getData(); @@ -49,11 +60,11 @@ function Contribute(props){ { list.map((item,key)=>{ return( - +
{item.name} -

提交{item.contributions}次

+

提交{item.contributions}次{item.contribution_perc ? ` I 贡献占比${item.contribution_perc}` : ''}

) diff --git a/src/forge/New/Index.js b/src/forge/New/Index.js index 1794d8e4..c307a8be 100644 --- a/src/forge/New/Index.js +++ b/src/forge/New/Index.js @@ -51,6 +51,9 @@ class Index extends Component { languageFlag:false, ignoreFlag:false, licenseFlag:false, + + // 区块链确权 + tokenConTri: false } } componentDidMount = () => { @@ -200,14 +203,13 @@ class Index extends Component { isSpin: true }) const { projectsType } = this.props.match.params; - const { - project_language_id, project_category_id, license_id, ignore_id , owners_id , - ignoreFlag,licenseFlag,categoreFlag,languageFlag - } = this.state; + const { project_language_id, project_category_id, license_id, ignore_id, owners_id, ignoreFlag, licenseFlag, categoreFlag, languageFlag, tokenConTri} = this.state; const decoderPass = Base64.encode(values.password); const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json"; // 新建项目的时候,暂存数据,如果失败,返回的时候可以重新赋值 sessionStorage.newProjectValue=JSON.stringify({...values,project_language_id,project_category_id,license_id,ignore_id}); + // 贡献值激励确权机制 + const {blockchain_init} = values; axios.post(url, { ...values, auth_password:decoderPass, @@ -215,7 +217,10 @@ class Index extends Component { project_category_id:categoreFlag ? project_category_id : undefined, license_id:licenseFlag ? license_id : undefined, ignore_id:ignoreFlag ? ignore_id : undefined, - user_id:owners_id + user_id:owners_id, + blockchain: tokenConTri, + blockchain_token_all: 10000, + blockchain_init_token: blockchain_init && blockchain_init/100 }).then((result) => { if (result && result.data.id) { projectsType && projectsType !== "mirror" && this.props.showNotification(`项目创建成功!`); @@ -343,6 +348,7 @@ class Index extends Component { const { getFieldDecorator } = this.props.form; // 项目类型:deposit-托管项目,mirror-镜像项目 const { projectsType } = this.props.match.params; + const {current_user:{open_blockchain}} = this.props; const { CategoryList, @@ -365,7 +371,8 @@ class Index extends Component { ignoreFlag, licenseFlag, languageFlag, - categoreFlag + categoreFlag, + tokenConTri } = this.state; return (
@@ -630,6 +637,32 @@ class Index extends Component { )} } + + {/* 确权 仅在新建项目时 */} + {open_blockchain && projectsType === "deposit" &&
+

确权

+
{this.setState({tokenConTri:e.target.checked})}}>加入贡献值激励确权机制
+ + {getFieldDecorator('blockchain_init', { + rules: [{ + required: tokenConTri, message: '初始token值为一个不超过10000的正整数' + }, + { validator: (rule,val,callback) =>{ + if(val>10000){ + callback('初始token值最大值10000'); + }else{ + callback(); + } + }}], + })( + + )} + +
} +
注: 为必填项,否则为选填
diff --git a/src/forge/users/Index.jsx b/src/forge/users/Index.jsx index d4d0ff6c..8ed8b1e4 100644 --- a/src/forge/users/Index.jsx +++ b/src/forge/users/Index.jsx @@ -24,7 +24,7 @@ export default withRouter( secondRouter = props.location.pathname.split('/')[2]; } - let userRouterArr = ['statistics', 'projects', 'notice', 'devops', 'organizes', 'info', 'following', 'followers', 'password' , "general"]; + let userRouterArr = ['statistics', 'projects', 'notice', 'devops', 'organizes', 'info', 'following', 'followers', 'password' , "general", "blockchain"]; return ( diff --git a/src/forge/users/Index.scss b/src/forge/users/Index.scss index 242ef640..bfd6518a 100644 --- a/src/forge/users/Index.scss +++ b/src/forge/users/Index.scss @@ -278,7 +278,7 @@ ul.ant-menu.menuStyle{ .infosRightMenu{ .ant-menu-item{ padding:0px; - margin:0px 30px 0px 0px !important; + margin:0px 17px 0px 0px !important; font-size: 17px; height: 32px; line-height: 0px; diff --git a/src/forge/users/Infos.js b/src/forge/users/Infos.js index f44c9fa4..803c9745 100644 --- a/src/forge/users/Infos.js +++ b/src/forge/users/Infos.js @@ -63,6 +63,11 @@ const Personal = Loadable({ loading: Loading, }) +// 贡献确权 +const Contribution = Loadable({ + loader: () => import('./contribution/index'), + loading: Loading, +}) class Infos extends Component { constructor(props) { @@ -108,6 +113,8 @@ class Infos extends Component { this.setState({menuKey:undefined,route_type:"following"}); }else if(pathname === `/${username}/followers`){ this.setState({menuKey:undefined,route_type:"followers"}); + }else if(pathname === `/${username}/blockchain`){ + this.setState({menuKey:'7',route_type:undefined}); }else{ this.setState({menuKey:"6",route_type:undefined}); } @@ -394,6 +401,10 @@ class Infos extends Component { { user && user.user_org_count && user.user_org_count > 0 ? ({user.user_org_count}):""} + {/* 当前用户+配置了贡献确权 */} + {current_user && user && user.login === current_user.login && current_user.open_blockchain && + 贡献确权 + } } {user && ( @@ -440,6 +451,12 @@ class Infos extends Component { return ; }} > + { + return ; + }} + > {/* { diff --git a/src/forge/users/contribution/index.jsx b/src/forge/users/contribution/index.jsx new file mode 100644 index 00000000..3fd80e11 --- /dev/null +++ b/src/forge/users/contribution/index.jsx @@ -0,0 +1,147 @@ + +import React , { useEffect , useState } from 'react'; +import { Button, Dropdown, Input, Menu , message, Pagination } from 'antd'; +import Search from '../../Component/Search'; +import Item from '../Team-item'; +import Nodata from '../../Nodata'; +import axios from 'axios'; +import CheckProfile from '../../Component/ProfileModal/Profile'; +import './index.scss'; +import SearchUser from '../../Component/SearchUser'; +import { FlexAJ } from '../../Component/layout'; + +// 个人中心-贡献确权 +function Contribution(props){ + // 接口暂不支持分页 + const limit = 15; + const [page, setPage] = useState(1); + const [total, setTotal] = useState(undefined); + // 转账列表 + const [reload, setReload] = useState(undefined); + const [list, setList] = useState(undefined); + // 选项 1 转账 0 记录 + const [ type, setType] = useState(1); + // 目标转账用户id/login + const [userLogin, setUserLogin] = useState({}); + const [error1, setError1] = useState(undefined); + // 转账数值 + const [tokenCount, setTokenCount] = useState({}); + const [error2, setError2] = useState(undefined); + // 操作仓库id + const [proId, setProId] = useState(undefined); + const { checkIfLogin , showLoginDialog , current_user:{user_id, login}, current_user } = props; + console.log('current_user', current_user); + const {user} = props; + + useEffect(()=>{ + // token转账列表 + axios.get(`/users/blockchain/balance.json`,{params: {user_id}}).then(res=>{ + if(res && res.data){ + setList(res.data.projects); + setTotal(res.data.total_count); + } + }) + }, [reload]) + + useEffect(()=>{ + if(user){ + // 更改网页标题 + const {username, login} = user; + document.title = `贡献确权-${username}/${login}`; + } + },[user]) + + // 目标转账用户 + function getUser(id, login){ + const userLoginObject = Object.assign(userLogin); + userLoginObject[id] = login; + setUserLogin(userLoginObject); + } + + // token转账值 + function setToken(id, token){ + const tokenCountObject = Object.assign(tokenCount); + tokenCountObject[id] = token; + setTokenCount(tokenCountObject); + } + + // 确认转账 + function confirmTransfer(id, identifier, max){ + setError1(undefined); + setError2(undefined); + setProId(id); + const userLoginById = userLogin[id]; + const tokenCountById = tokenCount[id]; + if(!userLoginById || !tokenCountById){ + !userLoginById && setError1('请确定目标转账用户'); + if(!tokenCountById){ + setError2('请输入token数额'); + } + }else if(!/^[1-9]+[0-9]*]*$/.test(tokenCountById) || tokenCountById>max){ + setError2('转账token数额必须为不超过token总数的正整数'); + }else{ + console.log('userLogin', userLoginById, 'tokenCount', tokenCountById); + axios.post(`/users/blockchain/transfer`, { + owner_login: login, + project_identifier: identifier, + user_id, + transfer_amount: tokenCountById, + transfer_login: userLoginById, + payer_id: user_id, + project_id: id + }).then(res=>{ + console.log('res', res); + if(res && res.data && res.data.status === 2){ + setReload(Math.random()); + message.success('转账成功'); + } + }) + } + } + + return(
+ {/* 转账/记录切换 */} + {/* */} + {/* token转账 */} + {type ?
+ {list && list.length > 0 &&
+
项目名称
+
token总量
+
目标转账用户
+
转账token数额
+
操作
+
} + {list && !list.length && } + {list && list.map(item=>{return
+
{item.name}
+
{item.balance}
+
+ {getUser(item.id, login)}} width={"100%"} placeholder="搜索转账目标用户"/> + {proId === item.id && error1 &&
{error1}
} +
+
+ {setToken(item.id, e.target.value)}} placeholder='请输入token数额'/> + {proId === item.id && error2 &&
{error2}
} +
+
+
})} +
:
+ + 蒋宇航GilLink/确实开源给你转账了1000个tiken + 6小时前 + + + 蒋宇航GilLink/确实开源给你转账了1000个tiken + 6小时前 + +
} + {/* {total > limit &&
+ setPage(page)}/> +
} */} +
+ ) +} +export default Contribution; \ No newline at end of file diff --git a/src/forge/users/contribution/index.scss b/src/forge/users/contribution/index.scss new file mode 100644 index 00000000..ba3ee58a --- /dev/null +++ b/src/forge/users/contribution/index.scss @@ -0,0 +1,79 @@ +.contHead{ + &>.itemCont{ + display: inline-block; + width:83px; + height:32px; + background-color:rgba(250, 251, 252, 0); + border:1px solid #d0d0d0; + border-radius:0px 4px 4px 0px; + text-align: center; + color: #333; + &:first-of-type{ + border-radius:4px 0px 0px 4px; + border-right: none; + } + &:last-of-type{ + border-left: none; + } + &.active{ + border-color: $primary-color; + background-color: $primary-color; + color: white; + } + } +} +.contribution{ + .flexCenterCont{ + display: flex; + justify-content: space-between; + } + .contributionTable{ + background-color:rgba(250, 252, 255, 0.89); + border-radius:4px 4px 0px 0px; + padding: 20px 20px 40px 20px; + } + .tableHeadTri{ + color:#898d9d; + } + .transferAccount{ + color:#40424a; + padding: 15px 0; + border-bottom: 1px solid #eee; + } + .tableColumn3, .tableColumn4{ + width: 200px; + } + .tableColumn1{ + width: 130px; + } + .tableColumn5{ + width: 120px; + text-align: center; + } + .tableColumn2{ + flex: 0.5; + } + .confirmTransfer{ + border-color: $primary-color; + color: $primary-color; + } + .errorTipTri{ + width: 400px; + color: red; + } +} +.record.contributionTable{ + padding: 0px 20px; + .contributionRecordItem{ + padding: 15px 0; + } + .contributionRecordItem+.contributionRecordItem{ + border-top: 1px solid #eee; + } + .themeSpan{ + color: $primary-color; + } +} +.paginationTri{ + text-align: center; +} \ No newline at end of file