Compare commits

...

40 Commits

Author SHA1 Message Date
baladiwei 7fd790fe7d Merge pull request '@我功能' (#261) from durian/forgeplus-react:feature_notification_v2 into feature_notification_v2 2021-11-12 14:21:39 +08:00
谢思 c48e3584c3 删除之前atwo.js的引入 2021-11-12 14:17:06 +08:00
谢思 d0ca09e780 Merge branch 'feature_notification_v2' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification_v2 2021-11-12 14:08:56 +08:00
baladiwei ed3bf55f90 Merge pull request 'merge old version' (#260) from feature_noti_v2 into feature_notification_v2 2021-11-12 14:07:07 +08:00
谢思 7ff29fec70 未及时更新评论内容 2021-11-12 13:50:35 +08:00
谢思 a94d02bb8a atwo markdown渲染 2021-11-11 11:31:42 +08:00
谢思 cc2dd35ff4 编辑合并请求最后一行@弹框被遮挡 2021-11-10 20:45:23 +08:00
谢思 f003a99779 @我功能。 2021-11-10 16:47:22 +08:00
谢思 b1ead191a6 Merge branch 'pre_develop' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification_v2 2021-11-10 10:28:23 +08:00
谢思 55a6f93fe3 atwho 2021-11-08 16:04:19 +08:00
谢思 ac4488a907 atwho 2021-11-08 15:14:04 +08:00
谢思 2078a044b6 at我列表 2021-11-01 09:31:08 +08:00
jasder d5b4c5425f Merge pull request 'wip' (#235) from pre_develop_dev into pre_develop 2021-10-28 17:48:03 +08:00
jasder 56946f94e8 更改域名相关信息 2021-10-28 17:29:35 +08:00
caishi 61ee3fe36f 注册页面相关信息修改 2021-10-28 17:25:50 +08:00
jasder 7b77c46915 Merge pull request '导入仓库链接和项目issue优化更改' (#228) from hc1913847458/forgeplus-react:testdev into pre_develop_dev 2021-10-25 17:33:48 +08:00
hucong 746f552a21 issue 2021-10-25 16:37:50 +08:00
hucong 7872d5ecab 导入链接优化 2021-10-25 15:56:06 +08:00
hucong 60da6bd110 导入链接优化 2021-10-25 15:46:57 +08:00
hucong aeff357660 项目页icon更改 2021-10-25 11:09:41 +08:00
hucong 0e6cb3954a 项目页icon更改 2021-10-25 11:09:13 +08:00
hucong ae12618c0c 导入链接显示优化 2021-10-25 10:45:40 +08:00
谢思 1c46617144 Merge branch 'pre_develop' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification_v2 2021-10-23 19:52:58 +08:00
谢思 ec133a6880 添加todo 2021-10-23 19:50:17 +08:00
谢思 bcdb631c20 删除引入的js文件 2021-10-23 19:43:58 +08:00
谢思 8021d96cd8 atwho列表 2021-10-23 19:39:54 +08:00
谢思 3498390974 at 2021-10-21 14:12:15 +08:00
谢思 4f3e385f78 at谁列表(缺弹框的上下,enter键监听) 2021-10-21 10:51:40 +08:00
谢思 18b289b84c @who(缺优化) 2021-10-21 09:41:17 +08:00
谢思 e3f49db5c0 at谁列表 2021-10-18 14:19:32 +08:00
谢思 4add266047 at谁列表 2021-10-15 11:36:51 +08:00
谢思 4a6012bfa9 at谁列表 2021-10-14 15:04:17 +08:00
谢思 7fe88aa4d9 at列表 2021-10-14 09:11:37 +08:00
谢思 bc6ef583fb atwho 2021-10-13 16:01:38 +08:00
谢思 b268b540d8 @我列表 2021-10-13 14:53:13 +08:00
谢思 7e69c64c9c @who列表 2021-10-13 11:52:54 +08:00
谢思 85ef26f70e @who 2021-10-13 10:07:38 +08:00
谢思 8c7865d2c1 Merge branch 'pre_develop' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification_v2 2021-10-13 09:54:04 +08:00
谢思 999a15761d md@谁列表 2021-10-12 14:24:18 +08:00
谢思 5c2330512e @我:在markdown编辑器中输入@我弹出列表需要引入的js 2021-10-11 13:48:50 +08:00
20 changed files with 493 additions and 107 deletions

View File

@ -224,7 +224,7 @@ function NoticeContent({ visible, showNotification, resetUserInfo, current_user:
<Badge color="#FA2020" /> <Badge color="#FA2020" />
</span> </span>
<div className="noticeCont-text"> <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="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: item.content }}></span>
<span className="timeSpan">{item.time_ago}</span> <span className="timeSpan">{item.time_ago}</span>
</div> </div>
</div> </div>

View File

@ -508,11 +508,6 @@ class Detail extends Component {
this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info) this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info)
: "" : ""
} }
{
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
<span className="color-grey-9">导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
: ""
}
</div> </div>
</div> </div>
<div> <div>

View File

@ -52,12 +52,6 @@ class IndexItem extends Component {
<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 ?
<Tooltip title="该项目是一个导入于其他网站的仓库" className="ml5">
<i className="iconfont icon-jingxiang font-18 color-green" />
</Tooltip>:""
}
</AlignCenter> </AlignCenter>
<span className="p-r-tags"> <span className="p-r-tags">
{ {

View File

@ -18,7 +18,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
useEffect(()=>{ useEffect(()=>{
document.addEventListener('click',()=>{setIsOpen(false)}) document.addEventListener('click',()=>{setIsOpen(false)})
}) },[])
function showDown(flag,index,isBin){ function showDown(flag,index,isBin){
if(!isBin){ if(!isBin){

View File

@ -54,7 +54,7 @@ class UpdateMerge extends Component {
const { data, isSpin, pull, merge } = this.state; const { data, isSpin, pull, merge } = this.state;
return ( return (
<div> <div>
<div className="main"> <div className="main updateMerge">
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
{" "} {" "}
{data ? ( {data ? (

View File

@ -222,4 +222,8 @@ form .ant-cascader-picker, form .ant-select {
.overlihide li{ .overlihide li{
max-width: 450px; max-width: 450px;
}
/* 距离底部加大 @列表被遮挡 */
.updateMerge{
margin: 30px auto 60px;
} }

View File

@ -25,6 +25,7 @@ class MergeForm extends Component {
issue_tags: undefined, issue_tags: undefined,
issue_versions: undefined, issue_versions: undefined,
issue_priories: undefined, issue_priories: undefined,
atWhoLoginList:undefined
}; };
} }
@ -146,7 +147,7 @@ class MergeForm extends Component {
} else { } else {
values.issue_tag_ids = []; values.issue_tag_ids = [];
} }
const { desc } = this.state; const { desc , atWhoLoginList } = this.state;
if (merge_type === "new") { if (merge_type === "new") {
let url = `/${owner}/${projectsId}/pulls.json`; let url = `/${owner}/${projectsId}/pulls.json`;
axios.post(url, { axios.post(url, {
@ -158,7 +159,8 @@ class MergeForm extends Component {
fork_project_id: data && data.fork_project_id, fork_project_id: data && data.fork_project_id,
merge_user_login: data && data.merge_user_login, merge_user_login: data && data.merge_user_login,
files_count, files_count,
commits_count commits_count,
receivers_login:atWhoLoginList,
}) })
.then((result) => { .then((result) => {
if (result) { if (result) {
@ -189,6 +191,7 @@ class MergeForm extends Component {
body: desc, body: desc,
head: pull, head: pull,
base: merge, base: merge,
receivers_login:atWhoLoginList,
}) })
.then((result) => { .then((result) => {
if (result) { if (result) {
@ -225,6 +228,13 @@ class MergeForm extends Component {
}); });
}; };
//合并请求中at谁列表存储login
changeAtWhoLoginList = (loginList) =>{
this.setState({
atWhoLoginList:loginList,
});
};
render() { render() {
const { merge_type } = this.props; const { merge_type } = this.props;
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
@ -273,6 +283,10 @@ class MergeForm extends Component {
mdID={"merge-new-description"} mdID={"merge-new-description"}
initValue={desc} initValue={desc}
onChange={this.onContentChange} onChange={this.onContentChange}
isCanAtme = {true}
changeAtWhoLoginList = {this.changeAtWhoLoginList}
owner = {owner}
projectsId = {projectsId}
></MDEditor> ></MDEditor>
<p className="clearfix mt20"> <p className="clearfix mt20">
<Button <Button

View File

@ -35,7 +35,8 @@ class order_form extends Component {
get_attachments: undefined, get_attachments: undefined,
show_token: false, show_token: false,
cannot_edit: false, cannot_edit: false,
issue_current_user: true issue_current_user: true,
atWhoLoginList:undefined
}; };
} }
componentDidUpdate=(prevPros)=>{ componentDidUpdate=(prevPros)=>{
@ -152,7 +153,7 @@ class order_form extends Component {
if (values.issue_tag_ids.length > 0) { if (values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [values.issue_tag_ids]; values.issue_tag_ids = [values.issue_tag_ids];
} }
const { description, start_date, due_date, issue_type } = this.state; const { description, start_date, due_date, issue_type , atWhoLoginList } = this.state;
if (form_type !== "edit") { if (form_type !== "edit") {
const url = `/${owner}/${projectsId}/issues.json`; const url = `/${owner}/${projectsId}/issues.json`;
axios.post(url, { axios.post(url, {
@ -162,6 +163,7 @@ class order_form extends Component {
start_date: start_date, start_date: start_date,
due_date: due_date, due_date: due_date,
issue_type: issue_type, issue_type: issue_type,
receivers_login:atWhoLoginList,
}).then((result) => { }).then((result) => {
if (result && result.data.id) { if (result && result.data.id) {
this.props.showNotification("任务创建成功!"); this.props.showNotification("任务创建成功!");
@ -188,6 +190,7 @@ class order_form extends Component {
due_date: due_date, due_date: due_date,
issue_type: issue_type, issue_type: issue_type,
...values, ...values,
receivers_login:atWhoLoginList,
}).then((result) => { }).then((result) => {
if (result) { if (result) {
this.props.history.push(`/${owner}/${projectsId}/issues/${orderId}`); this.props.history.push(`/${owner}/${projectsId}/issues/${orderId}`);
@ -221,6 +224,14 @@ class order_form extends Component {
description: value, description: value,
}); });
}; };
//issue中at谁列表存储login
changeAtWhoLoginList = (loginList) =>{
this.setState({
atWhoLoginList:loginList,
});
};
// 修改开始时间 // 修改开始时间
changeBeginTime = (start_date, value) => { changeBeginTime = (start_date, value) => {
this.setState({ this.setState({
@ -329,6 +340,10 @@ class order_form extends Component {
mdID={"order-new-description"} mdID={"order-new-description"}
initValue={description} initValue={description}
onChange={this.onContentChange} onChange={this.onContentChange}
isCanAtme = {true}
changeAtWhoLoginList = {this.changeAtWhoLoginList}
owner = {owner}
projectsId = {projectsId}
></MDEditor> ></MDEditor>
</div> </div>
{get_attachments && get_attachments.length > 0 ? ( {get_attachments && get_attachments.length > 0 ? (

View File

@ -17,7 +17,7 @@ function MyNotice(props) {
const [selectedNum, setSelectedNum] = useState(0);//@ const [selectedNum, setSelectedNum] = useState(0);//@
const [isBatchDelete, setIsBatchDelete] = useState(false);//@ const [isBatchDelete, setIsBatchDelete] = useState(false);//@
const [batchDeleteCheckedAll, setBatchDeleteCheckAll] = useState(false);//@-- const [batchDeleteCheckedAll, setBatchDeleteCheckAll] = useState(false);//@--
const [messageType, setMessageType] = useState(undefined);
const [noticeUnreadCount, setNoticeUnreadCount] = useState();// const [noticeUnreadCount, setNoticeUnreadCount] = useState();//
// const [letterUnreadCount, setLetterUnreadCount] = useState(0);// // const [letterUnreadCount, setLetterUnreadCount] = useState(0);//
const [atUnreadCount, setAtUnreadCount] = useState();//@ const [atUnreadCount, setAtUnreadCount] = useState();//@
@ -65,6 +65,7 @@ function MyNotice(props) {
setAtUnreadCount(response.data.unread_atme); setAtUnreadCount(response.data.unread_atme);
setMessageList(response.data.messages); setMessageList(response.data.messages);
setMessTotalCount(response.data.total_count); setMessTotalCount(response.data.total_count);
setMessageType(response.data.type);
} }
}); });
} }
@ -203,7 +204,46 @@ function MyNotice(props) {
</div> </div>
</div>} </div>}
{messageList && messageList.map(item => { {/* 系统消息 */}
{messageType === "notification" && messageList && messageList.map(item =>{
return (
<div className="mynotice-content vertical-center-style" key={item.id}>
<div className="mynotice-cont stretch-style">
{item.status === 1 ? <Badge color="#FA2020" /> : <span className="system-notice-blank"></span>}
<i className={"iconfont "+noticeSourceType[item.source]}></i>
<span className={`sysNotice-length ${item.notification_url?'highlightSpan':''}`} onClick={() => {turnToMess(item)}} dangerouslySetInnerHTML={{__html: item.content}}></span>
</div>
<div className="mynotice-cont vertical-center-style float-left-little">
<span className={item.status === 1?"timeSpan":""}>{item.time_ago}</span>
{item.status === 1 && <span className="invisable-read" onClick={()=>readNotice([item.id])}>标记为已读</span>}
</div>
</div>
)
})}
{/* @我消息 */}
{messageType === "atme" && messageList && messageList.map(item =>{
return (
<div className={`mynotice-content vertical-center-style ${isBatchDelete?'batchDel':''}`} key={item.id}>
<div className="mynotice-cont vertical-center-style">
<Checkbox value={item.id} className={isBatchDelete ? 'visible-checkbox' : 'invisible-checkbox'} onChange={onChange} checked={item.checkedBatch}></Checkbox>
{item.sender && <img src={`https://testforgeplus.trustie.net//${item.sender.image_url}`} className="currentImg" onClick={()=>{window.open(`/${item.sender && item.sender.login}`);}}/>}
<div className={`atme-notice-text stretch-style ${item.notification_url && 'highlightSpan'}`} onClick={() => {turnToMess(item)}}>
{item.status === 1 ? <Badge color="#FA2020"/> : <span className="system-notice-blank"></span>}
{item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: item.content}}></span>}
</div>
</div>
<div className="mynotice-cont vertical-center-style">
<span className={!isBatchDelete && item.status === 1?"timeSpan":""}>{item.time_ago}</span>
{!isBatchDelete && item.status === 1 && <span className="invisable-read" onClick={()=>readNotice([item.id])}>标记为已读</span>}&nbsp;&nbsp;&nbsp;
{!isBatchDelete && <span className="invisable-read float-left-little" onClick={()=>deleteNotice([item.id])}>删除</span>}
</div>
</div>
)
})}
{false && messageList && messageList.map(item => {
console.log('item',item);
// //
if (noticeType === "0") { if (noticeType === "0") {
// //
@ -229,7 +269,7 @@ function MyNotice(props) {
{item.sender && <img src={`https://testforgeplus.trustie.net//${item.sender.image_url}`} className="currentImg" onClick={()=>{window.open(`/${item.sender && item.sender.login}`);}}/>} {item.sender && <img src={`https://testforgeplus.trustie.net//${item.sender.image_url}`} className="currentImg" onClick={()=>{window.open(`/${item.sender && item.sender.login}`);}}/>}
<div className={`atme-notice-text stretch-style ${item.notification_url && 'highlightSpan'}`} onClick={() => {turnToMess(item)}}> <div className={`atme-notice-text stretch-style ${item.notification_url && 'highlightSpan'}`} onClick={() => {turnToMess(item)}}>
{item.status === 1 ? <Badge color="#FA2020"/> : <span className="system-notice-blank"></span>} {item.status === 1 ? <Badge color="#FA2020"/> : <span className="system-notice-blank"></span>}
{item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: "<b class = 'atme-notice-name'>" + item.sender.name+ "</b> "+ item.content +" 中@我"}}></span>} {item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: "<b class = 'atme-notice-name'>" + item.sender.name+ "</b> "+ item.content}}></span>}
</div> </div>
</div> </div>
<div className="mynotice-cont vertical-center-style"> <div className="mynotice-cont vertical-center-style">

View File

@ -267,6 +267,11 @@ class Setting extends Component {
}, },
], ],
})(<Input placeholder="请输入项目名称" />)} })(<Input placeholder="请输入项目名称" />)}
{
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
<span className="color-grey-9">该项目导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
: ""
}
</Form.Item> </Form.Item>
<div className="df" style={{ alignItems: "center" }}> <div className="df" style={{ alignItems: "center" }}>
<span className="mr20 mb15 font-16">可见性</span> <span className="mr20 mb15 font-16">可见性</span>

View File

@ -10,14 +10,10 @@ function ListItem({item,key,OIdentifier}) {
<Link to={`/${OIdentifier}/${item.identifier}`} className="name">{item.name}</Link> <Link to={`/${OIdentifier}/${item.identifier}`} className="name">{item.name}</Link>
{ item.forked_from_project_id && <i className="iconfont icon-fork font-18 color-orange ml8" /> } { item.forked_from_project_id && <i className="iconfont icon-fork font-18 color-orange ml8" /> }
{ {
item.type && item.type !== 0 ? item.type && item.type === 2 ?
item.type === 2 ?
<Tooltip title="该项目是一个镜像" className="ml8"> <Tooltip title="该项目是一个镜像" className="ml8">
<i className="iconfont icon-banbenku font-18 color-green" /> <i className="iconfont icon-banbenku font-18 color-green" />
</Tooltip>: </Tooltip>:""
<span className="ml8">
<i className="iconfont icon-jingxiang font-18 color-green" />
</span>:""
} }
</span> </span>
<ListCount fork={item.forked_count} parise={item.praises_count}/> <ListCount fork={item.forked_count} parise={item.praises_count}/>

View File

@ -27,7 +27,7 @@ class ForkUsers extends Component {
}); });
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/members.json`; const url = `/${owner}/${projectsId}/forks.json`;
axios axios
.get(url, { .get(url, {
params: { params: {

View File

@ -30,6 +30,7 @@ class comments extends Component {
reply_id: undefined, reply_id: undefined,
reply_content: undefined, reply_content: undefined,
new_journal_id: undefined, new_journal_id: undefined,
atWhoLoginList:undefined
}; };
} }
@ -51,6 +52,7 @@ class comments extends Component {
}); });
return; return;
} }
this.props.form.validateFieldsAndScroll((err, values) => { this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
const { const {
@ -60,10 +62,12 @@ class comments extends Component {
orderId, orderId,
reply_id, reply_id,
is_reply, is_reply,
atWhoLoginList,
} = this.state; } = this.state;
const url = `/issues/${orderId}/journals.json`;
const url = `/issues/${orderId}/journals.json`;
axios axios
.post(url, { .post(url, {
...values, ...values,
@ -71,6 +75,7 @@ class comments extends Component {
issue_id: orderId, issue_id: orderId,
attachment_ids: fileList, attachment_ids: fileList,
parent_id: reply_id, parent_id: reply_id,
receivers_login:atWhoLoginList,
}) })
.then((result) => { .then((result) => {
if (result && result.data.status === 0) { if (result && result.data.status === 0) {
@ -248,18 +253,29 @@ class comments extends Component {
onContentChange = (value) => { onContentChange = (value) => {
if (value) { if (value) {
this.setState({ this.setState({
content: value,
quillFlag: false, quillFlag: false,
}); });
} }
this.setState({
content: value,
});
}; };
replyContentChange = (value) => { replyContentChange = (value) => {
if (value) { if (value) {
this.setState({ this.setState({
reply_content: value,
quillFlag: false, quillFlag: false,
}); });
} }
this.setState({
reply_content: value,
});
};
//评论中at谁列表存储login
changeAtWhoLoginList = (loginList) =>{
this.setState({
atWhoLoginList:loginList,
});
}; };
onRef = (ref) => { onRef = (ref) => {
@ -308,6 +324,7 @@ class comments extends Component {
new_journal_id, new_journal_id,
} = this.state; } = this.state;
const { current_user, only_show_content } = this.props; const { current_user, only_show_content } = this.props;
const { projectsId ,owner } = this.props.match.params;
const new_comment = (is_reply, item_id) => { const new_comment = (is_reply, item_id) => {
return ( return (
@ -339,6 +356,10 @@ class comments extends Component {
onChange={ onChange={
is_reply ? this.replyContentChange : this.onContentChange is_reply ? this.replyContentChange : this.onContentChange
} }
isCanAtme = {true}
changeAtWhoLoginList = {this.changeAtWhoLoginList}
owner = {owner}
projectsId = {projectsId}
></MDEditor> ></MDEditor>
<p className="quillFlag"> <p className="quillFlag">
{quillFlag && <span className="">请输入评论内容</span>} {quillFlag && <span className="">请输入评论内容</span>}

View File

@ -153,21 +153,21 @@ class EducoderLogin extends Component {
justifyContent: "center", justifyContent: "center",
width: "100%", width: "100%",
}}> }}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div> <div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>: </div>:
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.main_site===null|| this.props.mygetHelmetapi.main_site===undefined? <div style={{ this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.main_site===null|| this.props.mygetHelmetapi.main_site===undefined? <div style={{
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
width: "100%", width: "100%",
}}> }}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div> <div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>:this.props.mygetHelmetapi.main_site===true? </div>:this.props.mygetHelmetapi.main_site===true?
<div style={{ <div style={{
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
width: "100%", width: "100%",
}}> }}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div> <div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div> </div>
:"" :""
} }

View File

@ -142,12 +142,12 @@ class Trialapplication extends Component {
if (this.state.Phonenumberisnotcobool === false) { if (this.state.Phonenumberisnotcobool === false) {
if (this.state.login.length === 0) { if (this.state.login.length === 0) {
this.setState({ this.setState({
Phonenumberisnotco: "请输入正确的手机号或邮箱", Phonenumberisnotco: "请输入正确的邮箱账号",
}) })
return return
} else { } else {
this.setState({ this.setState({
Phonenumberisnotco: "请输入正确的手机号或邮箱", Phonenumberisnotco: "请输入正确的邮箱账号",
}) })
} }
return; return;

View File

@ -158,12 +158,12 @@ class Trialapplicationysl extends Component {
if (this.state.Phonenumberisnotcobool === false) { if (this.state.Phonenumberisnotcobool === false) {
if (this.state.login.length === 0) { if (this.state.login.length === 0) {
this.setState({ this.setState({
Phonenumberisnotco: "请输入正确的手机号或邮箱", Phonenumberisnotco: "请输入正确的邮箱账号",
}) })
return return
} else { } else {
this.setState({ this.setState({
Phonenumberisnotco: "请输入正确的手机号或邮箱", Phonenumberisnotco: "请输入正确的邮箱账号",
}) })
} }
return; return;

View File

@ -4,4 +4,39 @@
.Permanentban{ .Permanentban{
color:#5091FF !important; color:#5091FF !important;
border-color: #5091FF !important; border-color: #5091FF !important;
}
/*md编辑器中输入@弹出可选人列表样式*/
.at_who_list{
position: absolute;
z-index: 100;
width: 180px;
max-height: 160px;
background: #FFFFFF;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
overflow-y: scroll;
cursor: pointer;
}
.at_who{
height: 40px;
display: flex;
flex-direction: row;
align-items: center;
border-bottom: 1px solid rgba(212, 212, 212, 0.5);
padding: 0 4px;
}
.at_who.active{
background: #F3F4F6;
}
.at_who img{
width:30px;
height:30px;
border-radius:50%;
margin-right: 10px;
}
.at_who span{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }

View File

@ -1,11 +1,12 @@
import React, { Fragment, useEffect, useRef, useState } from 'react'; import React, { Fragment, useEffect, useRef, useState } from 'react';
import { getUploadActionUrl, getUrl } from 'educoder'; import { getUploadActionUrl, getUrl } from 'educoder';
import ResizeObserver from 'resize-observer-polyfill'; import ResizeObserver from 'resize-observer-polyfill';
import { getImageUrl } from 'educoder';
import axios from 'axios';
import '../../courses/css/Courses.css'; import '../../courses/css/Courses.css';
import './css/TPMchallengesnew.css'; import './css/TPMchallengesnew.css';
import 'codemirror/lib/codemirror.css'; import 'codemirror/lib/codemirror.css';
import './css/newquestion.css';
const $ = window.$ const $ = window.$
const mdIcons = ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "inline-latex", "latex", '|', "image", "table", '|', "line-break", "watch", "clear"]; const mdIcons = ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "inline-latex", "latex", '|', "image", "table", '|', "line-break", "watch", "clear"];
@ -39,7 +40,6 @@ function md_rec_data(k, mdu, id) {
} }
window.md_rec_data = md_rec_data; window.md_rec_data = md_rec_data;
function md_elocalStorage(editor, mdu, id) { function md_elocalStorage(editor, mdu, id) {
let oc = window.sessionStorage.getItem('content' + mdu) let oc = window.sessionStorage.getItem('content' + mdu)
if (oc !== null && oc !== editor.getValue()) { if (oc !== null && oc !== editor.getValue()) {
@ -74,16 +74,38 @@ function md_elocalStorage(editor, mdu, id) {
return tid return tid
} }
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , changeAtWhoLoginList, owner, projectsId }) => {
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true , forMember = true }) => {
const editorEl = useRef(); const editorEl = useRef();
const resizeBarEl = useRef(); const resizeBarEl = useRef();
const [editorInstance, setEditorInstance] = useState(); const [editorInstance, setEditorInstance] = useState();
const [atWhoVisible, setAtWhoVisible] = useState(false);
const [atWhoLoginListState, setAtWhoLoginListState] = useState([]);
//调用member.json接口获取到的用户列表
const [users, setUsers] = useState([]);
//可以@的全部用户
const [allUsers, setAllUsers] = useState([]);
const atWhoLoginList = useRef([]);
const atWhoVisibleRef = useRef(false);
const containerId = `mdEditor_${mdID}`; const containerId = `mdEditor_${mdID}`;
const editorBodyId = `mdEditors_${mdID}`; const editorBodyId = `mdEditors_${mdID}`;
const tipId = `e_tips_mdEditor_${mdID}`; const tipId = `e_tips_mdEditor_${mdID}`;
useEffect(()=>{
//请求members接口获取全部可@列表
isCanAtme && axios.get(`/${owner}/${projectsId}/members.json`).then(response=>{
if(response.data.total_count !== 0){
setAllUsers(response.data.users);
setUsers(response.data.users);
}
})
//点击其他地方关闭弹框
document.addEventListener('click',()=>{
atWhoVisibleRef.current = false;
setAtWhoVisible(false);
})
},[])
function onLayout() { function onLayout() {
let ro; let ro;
if (editorEl.current) { if (editorEl.current) {
@ -101,6 +123,96 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
return ro; return ro;
} }
function selectAtWho(username){
atWhoVisibleRef.current = false;
setAtWhoVisible(false);
const cm = editorInstance.cm;
//获取鼠标所在行的行数和ch
const cursor = cm.doc.getCursor();
const line = cursor.line;//行
const ch = cursor.ch;//列
const startIndex = cm.getRange({line,ch:0},{line,ch}).lastIndexOf("@");
let selectUserLogin = undefined;
users.map((item)=>{
item.username === username && (selectUserLogin = item.login);
})
//替换内容
cm.replaceRange("[@"+username+"]"+`(/${selectUserLogin}) `,{line,ch:startIndex},{line,ch});
//鼠标聚焦
cm.focus();
//将此user的login存储到atWhoLoginList集合中
const list = new Set(atWhoLoginList.current);
list.add(selectUserLogin);
atWhoLoginList.current = Array.from(list);
setAtWhoLoginListState(Array.from(list));
}
function onMouseOver(key){
document.getElementsByClassName("at_who active")[0] && (document.getElementsByClassName("at_who active")[0].className="at_who");
document.getElementsByClassName("at_who")[key] && (document.getElementsByClassName("at_who")[key].className="at_who active");
}
//markdown编辑器中输入的键盘监听事件
function mdKeyDown(e){
if (e.shiftKey && e.code === "Digit2") {
// 输入@键后在对应的位置显示可选的项目成员
atWhoVisibleRef.current = true;
setAtWhoVisible(true);
//获取光标位置
const cssStyle = document.getElementsByClassName("CodeMirror cm-s-default CodeMirror-wrap")[0].firstChild.style;
//设置弹框位置
const newTop = placeholder === "添加评论..." ? 159: placeholder === "请输入合并请求的描述..." ? 172:62;
const newLeft = placeholder === "添加评论..." ? 80: 20;
document.getElementById("at_who_list").style.top = parseInt(cssStyle.getPropertyValue("top").replace("px","")) + newTop +"px";
document.getElementById("at_who_list").style.left = parseInt(cssStyle.getPropertyValue("left").replace("px",""))+newLeft+"px";
}
//处理本来@了某人 -> 删掉 -> 撤回 的情况
if(e.ctrlKey && e.code === "KeyZ" && allUsers.length != 0){
const codemirror = editorInstance.cm;
let value = codemirror.getValue();
//处理初始内容就自带@谁的情况
if(initValue){
const del = [];
allUsers.map(item=>{
if(initValue.indexOf(item.username)!=-1 && initValue.charAt(initValue.indexOf(item.username)-1) === "@" && initValue.indexOf(`@${item.username}`)===value.indexOf(`@${item.username}`)){
//初始内容中有符合@+名字的格式并且当前内容未删除初始内容
del[del.length] = `[@${item.username}](/${item.login})`;
}
})
del.length!=0 && del.map(str=>{
value = value.replace(str,"");
})
}
//判断value是否包含@符号
value.indexOf("@") != -1 && allUsers.map(item =>{
if(value.indexOf(item.username)!=-1 && value.charAt(value.indexOf(item.username)-1) ==="@"){
//将此user的login存储到atWhoLoginList集合中
const list = new Set(atWhoLoginList.current);
list.add(item.login);
atWhoLoginList.current = Array.from(list);
setAtWhoLoginListState(Array.from(list));
}
})
}
}
useEffect(()=>{
changeAtWhoLoginList && changeAtWhoLoginList(atWhoLoginListState);
},[atWhoLoginListState])
const atWhoList = (
<div className="at_who_list" id="at_who_list" >
{users && users.map((item,key)=>{
return(
<div key={key} className={`at_who ${key===0 && `active`}`} onClick={()=>{selectAtWho(item.username)}} onMouseOver={()=>{onMouseOver(key)}}>
{item.image_url && <img src={getImageUrl(`/${item.image_url}`)}></img>}
<span>{item.username}</span>
</div>
)
})}
</div>
)
useEffect(() => { useEffect(() => {
if (editorInstance) { if (editorInstance) {
return return
@ -183,6 +295,69 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
const cmEl = editorInstance && editorInstance.cm const cmEl = editorInstance && editorInstance.cm
useEffect(()=>{
if(atWhoVisibleRef.current){
// 添加上下键、enter键监听事件
cmEl.addKeyMap({
'Up':()=>{
const atWhoListDiv = document.getElementById("at_who_list");
const atWhoDivs = document.getElementsByClassName("at_who");
let index;
for(let i = 0; i<atWhoDivs.length;i++){
atWhoDivs[i].className === "at_who active" && (index = i);
}
if(index>0){
index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
atWhoDivs[index].className = "at_who";
atWhoDivs[index-1].className = "at_who active";
}
},
'Down':()=>{
const atWhoListDiv = document.getElementById("at_who_list");
const atWhoDivs = document.getElementsByClassName("at_who");
let index;
for(let i = 0; i<atWhoDivs.length;i++){
atWhoDivs[i].className === "at_who active" && (index = i);
}
if(index<atWhoDivs.length-1){
index >=3 && (atWhoListDiv.scrollTop +=40)
atWhoDivs[index].className = "at_who";
atWhoDivs[index+1].className = "at_who active";
}
},
'Enter':()=>{
//找到classname为at_who active的div执行click事件
if(document.getElementsByClassName("at_who active")[0]){
document.getElementsByClassName("at_who active")[0].click()
}else{
const cm = editorInstance.cm;
const cursor = cm.doc.getCursor();
const line = cursor.line;//行
const ch = cursor.ch;//列
//添加换行
cm.replaceRange("\n",{line,ch},{line,ch});
setAtWhoVisible(false);
atWhoVisibleRef.current = false;
}
}
})
} else {
//移除上下、enter键监听
cmEl && cmEl.removeKeyMap();
}
},[atWhoVisible])
useEffect(()=>{
//当users数组发生变化时改变框的位置
if(atWhoVisibleRef.current && users){
//获取光标位置
const cssStyle = document.getElementsByClassName("CodeMirror cm-s-default CodeMirror-wrap")[0].firstChild.style;
//设置弹框位置
const newLeft = placeholder === "添加评论..."? 80: 10;
document.getElementById("at_who_list").style.left = (parseInt(cssStyle.getPropertyValue("left").replace("px",""))+newLeft)+"px";
}
},[users])
useEffect(() => { useEffect(() => {
if (cmEl) { if (cmEl) {
let tid = null let tid = null
@ -198,19 +373,138 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
if (!noStorage) { if (!noStorage) {
tid = md_elocalStorage(editorInstance, `MDEditor__${containerId}`, containerId) tid = md_elocalStorage(editorInstance, `MDEditor__${containerId}`, containerId)
} }
if (onChange) { //isCanAtme:只有issue和合并请求以及评论部分可以@他人操作
editorInstance.cm.on('change', (cm) => { //绑定@事件
// if(forMember){ isCanAtme && editorInstance.cm.on("focus", () => {
// document.onkeydown = (e) => { document.addEventListener("keydown", mdKeyDown);
// if (e.key === "@") { });
// // 输入@键后在对应的位置显示可选的项目成员 isCanAtme && editorInstance.cm.on("blur", () => {
document.removeEventListener("keydown",mdKeyDown);
// } });
// }; editorInstance.cm.on("change", (cm) => {
// } //调用父组件的onchange方法将输入内容传入父级组件
onChange(cm.getValue()) onChange && onChange(cm.getValue());
}) if(atWhoVisibleRef.current){
} //搜索用户(弹框之后用户输入用户名信息)
const cur = cm.doc.getCursor();
const line = cur.line;
const ch = cur.ch;
let rangeCont = cmEl.getRange({line,ch:0},{line,ch});
//处理已经弹出列表框,但用户删除@符号
if(rangeCont.indexOf("@")===-1){
setAtWhoVisible(false);
atWhoVisibleRef.current = false;
}else{
rangeCont = rangeCont.substring(rangeCont.lastIndexOf("@")+1);
rangeCont ? axios.get(`/${owner}/${projectsId}/members.json`,{
params: {
search: rangeCont,
},
}).then(response=>{
if(response && response.data && response.data.total_count !== 0){
setUsers(response.data.users);
}else{
setUsers(undefined);
}
}):setUsers(allUsers)
}
}
//当内容发生改变并且有已@列表时
if(atWhoLoginList.current.length != 0){
const codemirror = editorInstance.cm;
//startValue触发change方法时的内容value处理了初始内容带@用户的情况
let startValue = codemirror.getValue();
let value = codemirror.getValue();
//处理初始内容就自带@谁的情况
if(initValue){
const del = [];
allUsers.map(item=>{
if(initValue.indexOf(item.username)!=-1 && initValue.charAt(initValue.indexOf(item.username)-1) === "@" && initValue.indexOf(`@${item.username}`)===value.indexOf(`@${item.username}`)){
//初始内容中有符合@+名字的格式并且当前内容未删除初始内容
del[del.length] = `[@${item.username}](/${item.login})`;
}
})
del.length!=0 && del.map(str=>{
value = value.replace(str,"");
})
}
//以username为主键login为value的map集合
let atWhoMap = new Map();
Array.from(atWhoLoginList.current).map(item=>{
allUsers.map(i=>{
if(i.login === item){
atWhoMap.set(i.username,i.login);
}
})
});
const cursor = codemirror.doc.getCursor();
const line = cursor.line;
const ch = cursor.ch;
//处理全部内容中不包含“@”的情况
if(value.indexOf("@") === -1){
//markdown嵌套的链接删掉
// Array.from(atWhoMap.keys()).map(username=>{
// startValue = startValue.replaceAll(`[${username}](/${atWhoMap.get(username)}) `,username);
// })
//替换全部内容
// codemirror.setValue(startValue);
//全部内容已经有要@的列表,但是没有@符号 -> 清空@集合
atWhoLoginList.current = [];
setAtWhoLoginListState([]);
}
//截取第一个字符到光标的内容
const curAfterCont = codemirror.getRange({line,ch:0},{line,ch});
const content = codemirror.getLine(line);
//处理光标所在行 有“@”的情况
if(content && content.indexOf("@") !== -1){
Array.from(atWhoMap.keys()).map(username=>{
//判断content是不是以列表中的某个username结尾
const userCont = `[@${username}](/${atWhoMap.get(username)})`;
//删除空格->选中@用户区域
if(curAfterCont.endsWith(userCont)){
codemirror.setSelection({line,ch:curAfterCont.lastIndexOf("@")-1},{line,ch});
}
//处理已经有@列表但是value中不包含完整[@用户名](/login)的情况
if(value.indexOf(userCont)===-1){
// //markdown嵌套的链接删掉,删[]、()的情况不用处理markdown会自动认为不是链接
// //找到[和)的index将区域内容替换成[]包裹的内容
// //光标之后的内容
// const curLeterCont = codemirror.getRange({line,ch},{line,ch:content.length});
// console.log('光标之后的内容curLeterCont',curLeterCont);
// //删除用户名 -> ]在curLeterCont中
// //删除login -> ]在curAfterCont中
// const a = curAfterCont.lastIndexOf('[');
// const b = curLeterCont.indexOf(')')
// const c = curLeterCont.indexOf(']') === -1 ? curAfterCont.lastIndexOf(']') : curLeterCont.indexOf(']')+curAfterCont.length;
// console.log('[',a,')',b,']',c);
// const newCont = codemirror.getRange({line,ch:a+1},{line,ch:c});
// console.log('newCont',newCont);
// codemirror.replaceRange(newCont,{line,ch:a-1},{line,ch:b+curAfterCont.length+1})
//符合情况->踢掉这个人 不给他发消息
const list = new Set(atWhoLoginList.current);
list.delete(atWhoMap.get(username));
atWhoLoginList.current = Array.from(list);
setAtWhoLoginListState(Array.from(list));
}
})
}else{
//处理所在行没有“@”的情况
Array.from(atWhoMap.keys()).map(username=>{
const userCont = `[@${username}](/${atWhoMap.get(username)})`;
if(value.indexOf(userCont)===-1){
//符合情况->踢掉这个人 不给他发消息
const list = new Set(atWhoLoginList.current);
list.delete(atWhoMap.get(username));
atWhoLoginList.current = Array.from(list);
setAtWhoLoginListState(Array.from(list));
}
})
}
}
});
ro = onLayout() ro = onLayout()
return () => { return () => {
if (!noStorage) { if (!noStorage) {
@ -271,7 +565,8 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
return ( return (
<Fragment> <Fragment>
<div ref={editorEl} className={`df ${className} ${imageExpand && 'editormd-image-click-expand'} `} > {atWhoVisible && atWhoList}
<div ref={editorEl} className={`df ${className} ${imageExpand && 'editormd-image-click-expand'} `}>
<div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''}`} id={containerId} > <div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''}`} id={containerId} >
<textarea style={{ display: 'none' }} id={editorBodyId} name="content"></textarea> <textarea style={{ display: 'none' }} id={editorBodyId} name="content"></textarea>
<div className="CodeMirror cm-s-defualt"></div> <div className="CodeMirror cm-s-defualt"></div>

View File

@ -699,7 +699,7 @@ class LoginRegisterComponent extends Component {
{/*onBlur={(e) => this.inputOnBlur(e)}*/} {/*onBlur={(e) => this.inputOnBlur(e)}*/}
<Input style={loginInputsyl} type="text" autoComplete="off" onClick={this.changeTypey} <Input style={loginInputsyl} type="text" autoComplete="off" onClick={this.changeTypey}
className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"} className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
placeholder="输入注册手机号或邮箱" value={this.state.login} placeholder="输入注册的邮箱账号" value={this.state.login}
// onBlur={(e) => this.inputOnBlurzhuche(e)} // onBlur={(e) => this.inputOnBlurzhuche(e)}
onChange={this.loginInputonChange} style={{marginTop: '10px', height: "38px"}}></Input> onChange={this.loginInputonChange} style={{marginTop: '10px', height: "38px"}}></Input>
{ {

View File

@ -7,6 +7,7 @@ import axios from 'axios';
import CheckInputysl1 from './CheckInputysl'; import CheckInputysl1 from './CheckInputysl';
import CheckInputysl2 from './CheckInputysl'; import CheckInputysl2 from './CheckInputysl';
import Notcompletedysl from './Notcompletedysl'; import Notcompletedysl from './Notcompletedysl';
import Educoder from '../login/educoder.png';
import './common.css' import './common.css'
import './commontwo.css' import './commontwo.css'
const { TabPane } = Tabs; const { TabPane } = Tabs;
@ -1039,7 +1040,7 @@ class LoginRegisterComponent extends Component {
} }
</style> </style>
<Input placeholder="请输入登录手机号码或邮箱" value={this.state.login} <Input placeholder="请输入邮箱账号" value={this.state.login}
onChange={this.loginInputonChange} onChange={this.loginInputonChange}
name="username" name="username"
className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"} className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
@ -1085,28 +1086,14 @@ class LoginRegisterComponent extends Component {
<Button className="login_btn font-16" type="primary" style={{height:"46px"}} onClick={() => this.postLogin()} <Button className="login_btn font-16" type="primary" style={{height:"46px"}} onClick={() => this.postLogin()}
size={"large"}>登录</Button> size={"large"}>登录</Button>
{this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?this.state.isphone===true?<p className="clearfix mb10 textcenter"> <p className="clearfix mb10 textcenter">
<span className={"startlogin"}> 快速登录 </span>
<span className={"startlogin"}> 快速登录 </span> <div className={"mt10"}>
<div className={"mt10"}> <a href="https://data.educoder.net/oauth2?call_url=/oauth/authorize?client_id=d060ea87615f6f731880857bccc73f2620b0421b6780532cdf0df33583dbab4d&redirect_uri=https%3A%2F%2Fforgeplus.trustie.net%2Fapi%2Fauth%2Feducoder%2Fcallback&response_type=code">
<a onClick={()=>this.openweixinlogin()}> <img src={Educoder} alt="educoder登录" width="46px"/>
<img src={require('./img/WeChat.png')} alt="微信登录"/> </a>
</a> </div>
<a onClick={()=>this.openqqlogin()} className={"ml10"}> </p>
<img src={require('./img/qq.png')} alt="qq登录"/>
</a>
</div>
</p>:<p className="clearfix mb10 textcenter">
<span className={"startlogin"}> 快速登录 </span>
<div className={"mt10"}>
{/*<a onClick={()=>this.openweixinlogin()}>*/}
{/*<img src={require('./WeChat.png')} alt="微信登录"/>*/}
{/*</a>*/}
<a onClick={()=>this.openphoneqqlogin()}>
<img src={require('./img/qq.png')} alt="qq登录"/>
</a>
</div>
</p>:""}
</div> </div>
} }
@ -1115,7 +1102,7 @@ class LoginRegisterComponent extends Component {
{ {
weixinlogin===false&&parseInt(tab[0])==1 && weixinlogin===false&&parseInt(tab[0])==1 &&
<div style={{width: '340px'}}> <div style={{width: '340px'}}>
<Input placeholder="请使用手机号/邮箱账号进行注册" <Input placeholder="请使用邮箱账号进行注册"
className={Phonenumberisnotcos && Phonenumberisnotcos !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"} className={Phonenumberisnotcos && Phonenumberisnotcos !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
value={this.state.logins} value={this.state.logins}
type="text" autoComplete="off" type="text" autoComplete="off"
@ -1255,34 +1242,19 @@ class LoginRegisterComponent extends Component {
color: '#676767', color: '#676767',
}}>我已阅读并同意 }}>我已阅读并同意
<span> <span>
<a href={'https://forge.educoder.net/help?index=4'} target="_blank" className={"color-blue"}>服务协议条款</a> <a href={'https://gitlink.org.cn/forums/5029/detail'} target="_blank" className={"color-blue"}>服务协议条款</a>
</span></span></Checkbox>:""} </span></span></Checkbox>:""}
<Button className=" font-16 mb20" type="primary" style={this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?{height:"46px", width: "100%",marginTop:"26px"}:{height:"46px", width: "100%"}} onClick={() => this.postregistered()} <Button className=" font-16 mb20" type="primary" style={this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?{height:"46px", width: "100%",marginTop:"26px"}:{height:"46px", width: "100%"}} onClick={() => this.postregistered()}
size={"large"}>{this.props.weixinlogin?"注册并绑定":"注册"}</Button> size={"large"}>{this.props.weixinlogin?"注册并绑定":"注册"}</Button>
{this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?this.state.isphone===true?<p className="clearfix mb10 textcenter"> <p className="clearfix mb10 textcenter">
<span className={"startlogin"}> 快速登录 </span>
<span className={"startlogin"}> 快速登录 </span> <div className={"mt10"}>
<div className={"mt10"}> <a href="https://data.educoder.net/oauth2?call_url=/oauth/authorize?client_id=d060ea87615f6f731880857bccc73f2620b0421b6780532cdf0df33583dbab4d&redirect_uri=https%3A%2F%2Fforgeplus.trustie.net%2Fapi%2Fauth%2Feducoder%2Fcallback&response_type=code">
<a onClick={()=>this.openweixinlogin()}> <img src={Educoder} alt="educoder登录" width="46px"/>
<img src={require('./img/WeChat.png')} alt="微信登录"/> </a>
</a> </div>
<a onClick={()=>this.openqqlogin()} className={"ml10"}> </p>
<img src={require('./img/qq.png')} alt="qq登录"/>
</a>
</div>
</p>:<p className="clearfix mb10 textcenter">
<span className={"startlogin"}> 快速登录 </span>
<div className={"mt10"}>
{/*<a onClick={()=>this.openweixinlogin()}>*/}
{/*<img src={require('./WeChat.png')} alt="微信登录"/>*/}
{/*</a>*/}
<a onClick={()=>this.openphoneqqlogin()}>
<img src={require('./img/qq.png')} alt="qq登录"/>
</a>
</div>
</p>:""
}
</div> </div>
} }