diff --git a/public/css/iconfont.css b/public/css/iconfont.css index 9cface5a..037ef59d 100644 --- a/public/css/iconfont.css +++ b/public/css/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2340181 */ - src: url('iconfont.woff2?t=1682403222759') format('woff2'), - url('iconfont.woff?t=1682403222759') format('woff'), - url('iconfont.ttf?t=1682403222759') format('truetype'); + src: url('iconfont.woff2?t=1686823554834') format('woff2'), + url('iconfont.woff?t=1686823554834') format('woff'), + url('iconfont.ttf?t=1686823554834') format('truetype'); } .iconfont { @@ -13,6 +13,22 @@ -moz-osx-font-smoothing: grayscale; } +.icon-a-zu2044:before { + content: "\e96d"; +} + +.icon-cuo:before { + content: "\e96c"; +} + +.icon-dui:before { + content: "\e96b"; +} + +.icon-zanting:before { + content: "\e96a"; +} + .icon-cangkuyuyanicon:before { content: "\e962"; } diff --git a/public/css/iconfont.js b/public/css/iconfont.js index 26c9209e..2baa04e0 100644 --- a/public/css/iconfont.js +++ b/public/css/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_2340181='',function(c){var a=(a=document.getElementsByTagName("script"))[a.length-1],l=a.getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var h,i,o,z,t,p=function(a,l){l.parentNode.insertBefore(a,l)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}h=function(){var a,l=document.createElement("div");l.innerHTML=c._iconfont_svg_string_2340181,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?p(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),h()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(o=h,z=c.document,t=!1,m(),z.onreadystatechange=function(){"complete"==z.readyState&&(z.onreadystatechange=null,v())})}function v(){t||(t=!0,o())}function m(){try{z.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}v()}}(window); \ No newline at end of file +window._iconfont_svg_string_2340181='',function(c){var a=(a=document.getElementsByTagName("script"))[a.length-1],l=a.getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var h,i,o,z,t,p=function(a,l){l.parentNode.insertBefore(a,l)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}h=function(){var a,l=document.createElement("div");l.innerHTML=c._iconfont_svg_string_2340181,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?p(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),h()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(o=h,z=c.document,t=!1,m(),z.onreadystatechange=function(){"complete"==z.readyState&&(z.onreadystatechange=null,v())})}function v(){t||(t=!0,o())}function m(){try{z.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}v()}}(window); \ No newline at end of file diff --git a/public/css/iconfont.json b/public/css/iconfont.json index c21fd868..bcaf91ce 100644 --- a/public/css/iconfont.json +++ b/public/css/iconfont.json @@ -5,6 +5,34 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "36020261", + "name": "组 2044", + "font_class": "a-zu2044", + "unicode": "e96d", + "unicode_decimal": 59757 + }, + { + "icon_id": "5287658", + "name": "错", + "font_class": "cuo", + "unicode": "e96c", + "unicode_decimal": 59756 + }, + { + "icon_id": "8802648", + "name": "对", + "font_class": "dui", + "unicode": "e96b", + "unicode_decimal": 59755 + }, + { + "icon_id": "887857", + "name": "暂停", + "font_class": "zanting", + "unicode": "e96a", + "unicode_decimal": 59754 + }, { "icon_id": "34965902", "name": "仓库语言icon", diff --git a/public/css/iconfont.ttf b/public/css/iconfont.ttf index 3a879e10..7e2bf2df 100644 Binary files a/public/css/iconfont.ttf and b/public/css/iconfont.ttf differ diff --git a/public/css/iconfont.woff b/public/css/iconfont.woff index ec894a8c..b39f4893 100644 Binary files a/public/css/iconfont.woff and b/public/css/iconfont.woff differ diff --git a/public/css/iconfont.woff2 b/public/css/iconfont.woff2 index 3d4905ee..0cc082d5 100644 Binary files a/public/css/iconfont.woff2 and b/public/css/iconfont.woff2 differ diff --git a/src/AppConfig.js b/src/AppConfig.js index cf7fe8b6..9c5fbfd4 100644 --- a/src/AppConfig.js +++ b/src/AppConfig.js @@ -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) { diff --git a/src/forge/Component/Setnav.jsx b/src/forge/Component/Setnav.jsx index 97012159..0a918bd5 100644 --- a/src/forge/Component/Setnav.jsx +++ b/src/forge/Component/Setnav.jsx @@ -11,10 +11,12 @@ export default(({ header , nav })=>{ nav && nav.list && nav.list.length>0 ? nav.list.map((item,key)=>{ return( -
  • + !item.hide &&
  • - {item.name} + {item.icon && } + {item.img && } + {item.name}

  • diff --git a/src/forge/Information/Pages/newsDetail.jsx b/src/forge/Information/Pages/newsDetail.jsx index eba75c5f..ce20aae9 100644 --- a/src/forge/Information/Pages/newsDetail.jsx +++ b/src/forge/Information/Pages/newsDetail.jsx @@ -46,7 +46,7 @@ function NewsDetail(props){

    {detail.name}

    diff --git a/src/forge/Information/index.jsx b/src/forge/Information/index.jsx index c7da2c5c..33de4f59 100644 --- a/src/forge/Information/index.jsx +++ b/src/forge/Information/index.jsx @@ -92,8 +92,8 @@ function Index(props){ function getAdminUrl(id){ getCheckZoneRole(id).then(response=>{ - if(response && response.data.code === 200){ - setAdminUrl(response.data); + if(response && response.data.data){ + setAdminUrl(response.data.data); }else{ setAdminUrl(undefined); } diff --git a/src/forge/Information/index.scss b/src/forge/Information/index.scss index 71f343b2..60d4d1e1 100644 --- a/src/forge/Information/index.scss +++ b/src/forge/Information/index.scss @@ -1022,12 +1022,6 @@ margin: 25px 25px 25px 0; border-radius: 12px; } - .informations_detail.markdown-body{ - &>p{ - line-height: 32px; - margin-bottom: 8px!important; - } - } } .zone_parter{ background-color: #fff; @@ -1195,4 +1189,10 @@ } } } +} +.informations_detail.markdown-body{ + &>p{ + line-height: 32px; + margin-bottom: 8px!important; + } } \ No newline at end of file diff --git a/src/forge/Main/CoderDepot.jsx b/src/forge/Main/CoderDepot.jsx index 91bc4ef2..39ec3726 100644 --- a/src/forge/Main/CoderDepot.jsx +++ b/src/forge/Main/CoderDepot.jsx @@ -63,9 +63,9 @@ function CoderDepot(props){ branchName = returnbar(branchName); const details = props.projectDetail; let pathname = props.history.location.pathname; - const { platform } = props ; + const { platform , mirror_status } = props ; //distribution:判断此用户是否可以创建发行版 - const distribution = details && details.type !== 2 && ( details.permission && details.permission !== "Reporter"); + const distribution = details && details.type ===0 && ( details.permission && details.permission !== "Reporter"); const { bannerList } = props; useEffect(()=>{ if(bannerList && bannerList.length>0){ @@ -93,7 +93,7 @@ function CoderDepot(props){ useEffect(()=>{ - if(details){ + if(details && mirror_status===0){ setProjectDetail(details); setTopics(details.topics); setDesc(details.description); @@ -102,7 +102,7 @@ function CoderDepot(props){ setDefaultBranch(details.default_branch); setInviteCode(details.invite_code); } - },[details]) + },[details,mirror_status]) useEffect(()=>{ // 设置网页标题 @@ -126,7 +126,7 @@ function CoderDepot(props){ },[treeValue]) useEffect(()=>{ - if (projectsId && owner && defaultBranch){ + if (projectsId && owner && defaultBranch && mirror_status===0){ let b = turnbar(branchName) ; if(pathname.indexOf(`/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) { let url = pathname.split(`/tree/${b}/`)[1]; @@ -139,10 +139,10 @@ function CoderDepot(props){ setType("dir"); } } - },[projectsId,owner,pathname,defaultBranch]) + },[projectsId,owner,pathname,defaultBranch,mirror_status]) useEffect(()=>{ - if(platform){ + if(platform && mirror_status===0){ setReadOnly(props.history.location.search.indexOf('edit') !== -1); axios.get(`/${owner}/${projectsId}/releases.json`).then((result)=>{ if(result && result.data){ @@ -154,7 +154,7 @@ function CoderDepot(props){ } }) } - },[platform]) + },[platform,mirror_status]) // 获取readme信息 function getReadmeInfo(path, ref) { @@ -386,14 +386,14 @@ function CoderDepot(props){ const { current_user , checkIfLogin , showLoginDialog } = props; const baseOper = current_user && current_user.login && issuesFlag; - const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type !== 2 && pullsFlag && props.platform; - const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin)); + const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type ===0 && pullsFlag && props.platform; + const fileOperate = type === "dir" && projectDetail && projectDetail.type ===0 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin)); return( - setOpenModal(false)} onOk={okUpdate}/> + {mirror_status ===0 && setOpenModal(false)} onOk={okUpdate}/> } { - (dirInfo || fileInfo) && + ((dirInfo || fileInfo) && mirror_status===0 ) &&
    { - props && props.platform ? + props && (props.platform && mirror_status ===0) ? } {/* 贡献者 */} - + {mirror_status ===0 && } {/* 语言 */} - + { mirror_status ===0 && } } diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index 8f4e4188..75cdf887 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -192,7 +192,7 @@ class Detail extends Component { // 非本平台项目 platform: false, - mirror_status:1 + mirror_status:2 } } @@ -240,7 +240,6 @@ class Detail extends Component { open_devops: result.data.open_devops, platform: result.data.platform && result.data.platform !== 'educoder' }) - if (result.data.type !== 0 && result.data.mirror_status === 1) { console.log("--------start channel --------"); // 是镜像项目,且未完成迁移 @@ -260,16 +259,18 @@ class Detail extends Component { mirror_status:1 }) } else if (result.data.mirror_status === 2) { - this.deleteProjectBack(); this.setState({ - mirror_status:2 + mirror_status:2, + firstSync: false }) + this.deleteProjectBack(); } else { this.getBanner(); this.getDetail(); this.setState({ firstSync: false, - secondSync: false + secondSync: false, + mirror_status:0 }) } } @@ -860,7 +861,7 @@ class Detail extends Component { > (mirror_status!==2 ? :) + (props) => } > diff --git a/src/forge/New/Index.js b/src/forge/New/Index.js index 8ade2df0..6502016a 100644 --- a/src/forge/New/Index.js +++ b/src/forge/New/Index.js @@ -53,7 +53,10 @@ class Index extends Component { licenseFlag:false, // 区块链确权 - tokenConTri: false + tokenConTri: false, + + gitHubUrl:false, + checkToken:undefined } } componentDidMount = () => { @@ -203,7 +206,9 @@ 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, tokenConTri} = this.state; + const { project_language_id, project_category_id, license_id + , ignore_id, owners_id, ignoreFlag, licenseFlag, + categoreFlag, languageFlag, tokenConTri,gitHubUrl} = this.state; const decoderPass = Base64.encode(values.password); const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json"; // 新建项目的时候,暂存数据,如果失败,返回的时候可以重新赋值 @@ -220,7 +225,8 @@ class Index extends Component { user_id:owners_id, blockchain: tokenConTri, blockchain_token_all: 10000, - blockchain_init_token: parseInt(blockchain_init) + blockchain_init_token: parseInt(blockchain_init), + auth_token:gitHubUrl ? values.auth_token : undefined }).then((result) => { if (result && result.data.id) { projectsType && projectsType !== "mirror" && this.props.showNotification(`项目创建成功!`); @@ -235,6 +241,7 @@ class Index extends Component { }) }) } else { + window.scrollTo(0,0); this.setState({ isSpin: false }) @@ -301,6 +308,9 @@ class Index extends Component { repository_name:first }) } + this.setState({gitHubUrl:value.indexOf("https://github.com")>-1 ? true : false}) + }else{ + this.setState({gitHubUrl:false,checkToken:undefined}) } } @@ -344,6 +354,29 @@ class Index extends Component { } } + + blurFunc=(e)=>{ + let value = e.target.value; + if(value){ + const { clone_addr } = this.props.form.getFieldsValue(); + if(clone_addr){ + const u = `/projects/verify_auth_token.json`; + axios.post(u,{ + auth_token:value, + clone_addr + }).then(response=>{ + if(response && response.data){ + this.setState({ + checkToken:response.data.data + }) + } + }).catch(error=>{}) + } + }else{ + this.setState({checkToken:undefined}) + } + } + render() { const { getFieldDecorator } = this.props.form; // 项目类型:deposit-托管项目,mirror-镜像项目 @@ -372,7 +405,9 @@ class Index extends Component { licenseFlag, languageFlag, categoreFlag, - tokenConTri + tokenConTri, + gitHubUrl, + checkToken } = this.state; return (
    @@ -381,7 +416,6 @@ class Index extends Component {
    - { projectsType && projectsType === "mirror" && @@ -398,7 +432,7 @@ class Index extends Component { )} -

    示例:https://github.com/Stability-AI/StableStudio.git

    +

    示例:https://github.com/Stability-AI/StableStudio.git

    } { @@ -406,10 +440,32 @@ class Index extends Component {

    需要授权验证 - 如果导入项目为私有仓库,则必须填写相应平台正确的用户名和密码 + + 如果导入项目为私有仓库,{gitHubUrl ? `则需输入目标平台用户token进行授权,`:"则必须填写相应平台正确的用户名和密码"} + {gitHubUrl && 如何获取token?} +

    { - mirrorCheck && + mirrorCheck && gitHubUrl && +
    + Token + + + {getFieldDecorator('auth_token')( + + )} + + + { checkToken === false && } + { checkToken === true && } + +
    + } + { + mirrorCheck && !gitHubUrl &&
    用户名 @@ -447,19 +503,26 @@ class Index extends Component { {getFieldDecorator('user_id', { rules: [{ required: true, message: '请选择拥有者' - },{ - validator:(rule, value, callback) => this.checkId(rule, value, callback, OwnerList, '拥有者') }], })( - this.ChangePlatform(value, e, 'owners', OwnerList)} className="plateAutoComplete" - onBlur={(value) => this.blurCategory(value, OwnerList, "owners")} + optionFilterProp="children" + filterOption={(input, option) => + option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 + } > - {owners_list} - + {OwnerList && OwnerList.length > 0 && + OwnerList.map((i,k)=>{ + return( + + ) + }) + } + )} / @@ -681,4 +744,6 @@ class Index extends Component { } } const WrappedIndexForm = Form.create({ name: 'NewWorkForm' })(Index); -export default WrappedIndexForm; \ No newline at end of file +export default WrappedIndexForm; + + diff --git a/src/forge/New/new.scss b/src/forge/New/new.scss index 15aca70b..8432cecd 100644 --- a/src/forge/New/new.scss +++ b/src/forge/New/new.scss @@ -11,6 +11,12 @@ font-size: 1.6em; border-bottom: 1px solid #f0f0f0 } +.token_box{ + align-items: center; +} +.token_box .ant-form-explain{ + position: absolute; +} .newPanel_content{ padding:2rem; } @@ -25,7 +31,7 @@ min-width: 280px; } .newPanel_content .ant-select-selection{ - height: 37px; + height: 35px; } .newPanel_content .ant-select-selection__rendered,.newPanel_content input{ height: 35px; diff --git a/src/forge/Newfile/m_editor.js b/src/forge/Newfile/m_editor.js index 125d7c36..ae2ad19b 100644 --- a/src/forge/Newfile/m_editor.js +++ b/src/forge/Newfile/m_editor.js @@ -34,7 +34,6 @@ class m_editor extends Component { render() { const { editorValue, changeValue } = this.state; - console.log("editorValue:",editorValue) const { readOnly, editorType,onEmpty,filename,empty, currentBranch, descName, checkName, detail, match: { params },filepath,ideTheme } = this.props; const editor_options = { lineNumbers: "on", diff --git a/src/forge/SecuritySetting/Index.jsx b/src/forge/SecuritySetting/Index.jsx index c2019695..beb45b42 100644 --- a/src/forge/SecuritySetting/Index.jsx +++ b/src/forge/SecuritySetting/Index.jsx @@ -25,7 +25,10 @@ const NoticeManager = Loadable({ loader: () => import("./notice/manager/Index"), loading: Loading, }); - +const CLAList = Loadable({ + loader: () => import("./cla/Index"), + loading: Loading, +}); const SSHNew = Loadable({ loader: () => import("./sub/New"), loading: Loading, @@ -116,6 +119,7 @@ function Index(props){
    • 安全设置
    • -1 ?"active":""}>SSH密钥
    • +
    • -1 ?"active":""}>我的CLA
    • Bot开发
    • @@ -138,6 +142,12 @@ function Index(props){ )} > + ( + + )} + > ( diff --git a/src/forge/SecuritySetting/cla/DeleteBox.jsx b/src/forge/SecuritySetting/cla/DeleteBox.jsx new file mode 100644 index 00000000..d6ae9903 --- /dev/null +++ b/src/forge/SecuritySetting/cla/DeleteBox.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { AlignCenter } from '../../Component/layout'; +import Modals from '../../Component/PublicModal/Index'; +import { Button } from 'antd'; + +function DeleteBox({visible , onCancel,onSuccess,pr_need}){ + return( + + + +
    + } + > +
    + + 确定解除协议吗? + { pr_need &&

    您解除协议后,提交的合并请求对项目成员将不再可见(已存在的开启的合并请求也将被隐藏)

    } +
    + + ) +} +export default DeleteBox; \ No newline at end of file diff --git a/src/forge/SecuritySetting/cla/Index.jsx b/src/forge/SecuritySetting/cla/Index.jsx new file mode 100644 index 00000000..7a98fa6c --- /dev/null +++ b/src/forge/SecuritySetting/cla/Index.jsx @@ -0,0 +1,87 @@ +import React,{useEffect,useState} from 'react'; +import './index.scss'; +import logo from '../img/icon.svg'; +import { Link } from 'react-router-dom'; +import { Button , Spin } from 'antd'; +import Nodata from '../../Nodata'; +import DeleteBox from './DeleteBox'; +import axios from 'axios'; + +function Index(props){ + const { current_user } = props; + const[ lists, setLists] = useState(undefined); + const[ isSpin, setIsSpin] = useState(false); + const [ visible , setVisible ] = useState(false); + const [ cancelKey , setCancelKey ] = useState(undefined); + const [ pr_need , setPr_need ] = useState(true); + useEffect(()=>{ + document.title = "我的CLA"; + },[]) + + useEffect(()=>{ + if(current_user && current_user.user_id){ + setIsSpin(true); + getClaLists(); + } + },[current_user]) + + function getClaLists(){ + const url = `/users/${current_user.user_id}/clas.json`; + axios.get(url).then(response=>{ + if(response && response.data){ + setLists(response.data.user_clas); + setIsSpin(false); + } + }).catch(error=>{}) + } + + function onSuccess(){ + if(cancelKey && (current_user && current_user.user_id)){ + const url = `/users/${current_user && current_user.user_id}/clas/${cancelKey}.json`; + axios.delete(url).then(response=>{ + if(response){ + setVisible(false); + props.showNotification("协议解除成功!"); + getClaLists(); + } + }).catch(error=>{}) + } + } + return( +
    + {setVisible(false);setCancelKey(undefined)}} onSuccess={onSuccess}/> +
    我签署的CLA(开源贡献者协议)
    + { + lists && lists.length>0 && +
      + { + lists.map((i,k)=>{ + return( +
    • + +
      + {i.cla && i.cla.name} + {i.state && 签署状态{i.state === "signed" ? "生效中" : "已解除"} } + 签署邮箱{i.email} + 签署时间{i.created_at} +

      + + { i.state === "signed" && } +

      +
      +
    • + ) + }) + } +
    + } + { + lists && lists.length === 0 && + } + { + !lists &&
    + } +
    + ) +} +export default Index; \ No newline at end of file diff --git a/src/forge/SecuritySetting/cla/index.scss b/src/forge/SecuritySetting/cla/index.scss new file mode 100644 index 00000000..a6f66a78 --- /dev/null +++ b/src/forge/SecuritySetting/cla/index.scss @@ -0,0 +1,75 @@ +.default_head{ + height: 65px; + line-height: 64px; + border-bottom: 1px solid rgba(224, 230, 245, 1); + color:#151d40; + font-size:17px; + padding-bottom:20px; +} +.cla_lists{ + display: flex; + flex-wrap: wrap; + li{ + width: 478px; + margin-right: 26px; + border:1px solid; + border-color:rgba(153, 153, 153, 0.3); + border-radius:6px; + padding:30px 26px; + box-sizing: border-box; + display: flex; + align-items: flex-start; + margin-top: 25px; + &>img{ + width: 65px; + margin-right: 20px; + } + &>div{ + flex:1; + width: 0; + display: flex; + flex-direction: column; + &>span{ + color:rgba(76, 88, 118, 1); + height: 20px; + line-height: 20px; + margin-bottom: 10px!important; + } + .agree_status{ + >span{ + margin-left: 20px; + position: relative; + color:#8a94a2 ; + &::before{ + position: absolute; + height: 6px; + width: 6px; + border-radius: 50%; + left: -11px; + content: ""; + background-color: #8a94a2; + top:50%; + margin-top: -3px; + } + &.green_tip{ + color: #009b28; + } + &.green_tip::before{ + background-color: #009b28; + } + } + } + .agree_name{ + color:#151d40; + font-size:16px; + margin-bottom: 10px; + display: block; + height: 22px; + line-height: 22px; + } + } + &:nth-child(2n){ + margin-right: 0px; + } + } +} \ No newline at end of file diff --git a/src/forge/SecuritySetting/img/cla-logo.png b/src/forge/SecuritySetting/img/cla-logo.png new file mode 100644 index 00000000..d9a35de0 Binary files /dev/null and b/src/forge/SecuritySetting/img/cla-logo.png differ diff --git a/src/forge/SecuritySetting/img/icon.svg b/src/forge/SecuritySetting/img/icon.svg new file mode 100644 index 00000000..121d52f4 --- /dev/null +++ b/src/forge/SecuritySetting/img/icon.svg @@ -0,0 +1,13 @@ + + + + + + + + CLA + + + + + diff --git a/src/forge/Team/Index.jsx b/src/forge/Team/Index.jsx index 6d9ade0a..81266ca6 100644 --- a/src/forge/Team/Index.jsx +++ b/src/forge/Team/Index.jsx @@ -14,6 +14,10 @@ const GroupNew = Loadable({ loader: () => import("./Group/GroupNew"), loading: Loading, }); +const CLAinfos = Loadable({ + loader: () => import("./Setting/cla/CLAinfos"), + loading: Loading, +}); const New = Loadable({ loader: () => import("./New"), loading: Loading, @@ -40,6 +44,13 @@ export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC( return (
    + {/* 协议详情+签署协议 */} + ( + + )} + > {/* 新建组织 */} }} > - {/* 组织详情(包含组织设置) */} { if(result && result.data){ showNotification("组织创建成功!"); @@ -121,7 +121,7 @@ export default Form.create()( [], ,false )} - {helper( + {/* {helper( '可见性', "visibility", [{ required: true, message: "请选择可见性" }], @@ -130,7 +130,7 @@ export default Form.create()( 受限(仅对登录用户可见) 私有(仅对组织成员可见) - )} + )} */}

    选择头像

    diff --git a/src/forge/Team/RightBox.jsx b/src/forge/Team/RightBox.jsx index 4e75fe66..6a05d621 100644 --- a/src/forge/Team/RightBox.jsx +++ b/src/forge/Team/RightBox.jsx @@ -27,6 +27,10 @@ const ListName = styled.div`{ margin-bottom:8px; height:18px; line-height:18px; + width:210px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; }`; const ColorListName = styled.div`{ color:rgba(31, 35, 41, 1); @@ -34,6 +38,10 @@ const ColorListName = styled.div`{ margin-bottom:8px; height:18px; line-height:18px; + width:230px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; }` const Img = styled.img`{ border-radius:50%; diff --git a/src/forge/Team/Setting/TeamSettingCommon.jsx b/src/forge/Team/Setting/TeamSettingCommon.jsx index 6cd64962..d1ff67c0 100644 --- a/src/forge/Team/Setting/TeamSettingCommon.jsx +++ b/src/forge/Team/Setting/TeamSettingCommon.jsx @@ -58,7 +58,7 @@ export default Form.create()( if(!error){ const url = `/organizations/${organizeDetail.id}.json`; axios.patch(url,{ - ...values,image:imageFlag ? image : undefined + ...values,image:imageFlag ? image : undefined,visibility:"common" }).then(result=>{ if(result && result.data){ showNotification("组织信息更新成功!"); @@ -122,7 +122,7 @@ export default Form.create()( }) } return( -
    +
    基本设置 setPrivacyVisible(false)}> @@ -172,7 +172,7 @@ export default Form.create()( [], )} - {helper( + {/* {helper( '可见性:', "visibility", [], @@ -181,7 +181,7 @@ export default Form.create()( 受限(仅对登录用户可见) 私有(仅对组织成员可见) - )} + )} */} {helper( '权限:', "repo_admin_change_team_access", diff --git a/src/forge/Team/Setting/TeamSettingGroup.jsx b/src/forge/Team/Setting/TeamSettingGroup.jsx index 8ebdb4af..15a9ff24 100644 --- a/src/forge/Team/Setting/TeamSettingGroup.jsx +++ b/src/forge/Team/Setting/TeamSettingGroup.jsx @@ -5,7 +5,7 @@ import GroupItems from '../TeamGroupItems'; const limit = 8; function TeamSettingGroup({organizeDetail,history,current_user}){ return( - + 组织团队管理 diff --git a/src/forge/Team/Setting/TeamSettingIndex.jsx b/src/forge/Team/Setting/TeamSettingIndex.jsx index b5f4f368..91db1156 100644 --- a/src/forge/Team/Setting/TeamSettingIndex.jsx +++ b/src/forge/Team/Setting/TeamSettingIndex.jsx @@ -2,10 +2,12 @@ import React , { useEffect , useState } from 'react'; import { Box , Long , Short , Gap } from '../../Component/layout'; import Title from '../../Component/Title'; import Setnav from '../../Component/Setnav'; +import './teamSetting.scss'; import { Route, Switch } from "react-router-dom"; import Loadable from "react-loadable"; import Loading from "../../../Loading"; +import claIcon from '../images/cla-icon.png'; const Group = Loadable({ @@ -28,11 +30,18 @@ const Hooks = Loadable({ loader: () => import("./TeamSettingHooks"), loading: Loading, }); +const CLA = Loadable({ + loader: () => import("./cla/TeamSettingCLA"), + loading: Loading, +}); +const CLANew = Loadable({ + loader: () => import("./cla/TeamSettingCLAEdit"), + loading: Loading, +}); export default (( props )=>{ const pathname = props.location.pathname; const OIdentifier = props.match.params.OIdentifier; const {organizeDetail} = props; - useEffect(()=>{ if(organizeDetail){ const {nickname} = organizeDetail; @@ -48,7 +57,9 @@ export default (( props )=>{ a = 1; }else if(pathname === `/${OIdentifier}/setting/group`){ a = 3; - }else if(pathname === `/${OIdentifier}/setting/hooks`){ + // }else if(pathname === `/${OIdentifier}/setting/hooks`){ + // a = 4; + }else if(pathname.indexOf(`/${OIdentifier}/setting/agreement`)>-1){ a = 4; } return a; @@ -60,6 +71,7 @@ export default (( props )=>{ {name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/${OIdentifier}/setting/member`}, {name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/${OIdentifier}/setting/group`}, // {name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:`/${OIdentifier}/setting/hooks`} + {name:'CLA管理',img:claIcon,href:`/${OIdentifier}/setting/agreement`,hide:organizeDetail && !organizeDetail.enabling_cla} ], active } @@ -70,8 +82,29 @@ export default (( props )=>{ -
    +
    + {organizeDetail && organizeDetail.enabling_cla && + ( + + )} + > + } + {organizeDetail && organizeDetail.enabling_cla && ( + + )} + >} + {organizeDetail && organizeDetail.enabling_cla && ( + + )} + > + } ( diff --git a/src/forge/Team/Setting/TeamSettingMember.jsx b/src/forge/Team/Setting/TeamSettingMember.jsx index 9124390f..1b83b7b4 100644 --- a/src/forge/Team/Setting/TeamSettingMember.jsx +++ b/src/forge/Team/Setting/TeamSettingMember.jsx @@ -111,7 +111,7 @@ export default (({organizeDetail,history,match})=>{ }).catch(error=>{}) } return( - + <span>组织成员管理</span> {/* <AlignCenter> diff --git a/src/forge/Team/Setting/TeamSettingPage.jsx b/src/forge/Team/Setting/TeamSettingPage.jsx index b2600d16..9246a1a9 100644 --- a/src/forge/Team/Setting/TeamSettingPage.jsx +++ b/src/forge/Team/Setting/TeamSettingPage.jsx @@ -51,7 +51,7 @@ export default Form.create()(forwardRef((props)=>{ }) } return( - <div> + <div style={{border:"1px solid #eee"}}> <Title> <span>组织首页管理</span> diff --git a/src/forge/Team/Setting/cla/CLAinfos.jsx b/src/forge/Team/Setting/cla/CLAinfos.jsx new file mode 100644 index 00000000..3896f0cf --- /dev/null +++ b/src/forge/Team/Setting/cla/CLAinfos.jsx @@ -0,0 +1,114 @@ +import React,{ forwardRef, useState , useEffect } from 'react'; +import '../teamSetting.scss'; +import RenderHtml from '../../../../components/render-html'; +import { Button , Form , Input , Spin } from 'antd'; +import { getImageUrl } from 'educoder'; +import axios from 'axios'; + + +function CLAinfos(props){ + const { form , current_user , showLoginDialog } = props; + const { getFieldDecorator , validateFields , setFieldsValue , getFieldsValue} = form; + + const OIdentifier = props.match.params.OIdentifier; + const claid = props.match.params.claid; + + const [ details, setDetails ] = useState(undefined); + + useEffect(()=>{ + if(current_user && current_user.email){ + setFieldsValue({ + email:current_user.email + }) + } + },[current_user,details]) + + useEffect(()=>{ + if(current_user &&!current_user.login){ + props.history.push(`/login?go_page=/${OIdentifier}/cla/${claid}`); + } + },[current_user]) + + useEffect(()=>{ + if(claid){ + getDetails(); + } + },[claid]) + + function getDetails(){ + const url = `/organizations/${OIdentifier}/clas/${claid}.json`; + axios.get(url).then(response=>{ + if(response && response.data){ + setDetails(response.data); + document.title = `${response.data.name}`; + } + }).catch(error=>{}) + } + + function agreeFunc(){ + validateFields((error,values)=>{ + if(!error){ + const url = `/users/${current_user && current_user.user_id}/clas.json`; + axios.post(url,{ + ...values, + cla_id:details && details.id, + email:(current_user && current_user.email) || values.email + }).then(response=>{ + if(response && response.data){ + props.showNotification('协议签署成功!'); + window.scrollTo(0,0); + getDetails(); + } + }).catch(error=>{}) + } + }) + } + + return( + details ? +
    +
    +
    + +
    +

    {details.name}

    +

    {details.organization && details.organization.nickname}

    + {details.is_sign && details.cla_sign_email &&

    签署邮箱{details.cla_sign_email}

    } +
    +
    +
    +
    + {details.is_sign &&
    您已签署协议,可在“个人设置 > 我的 CLA”中查看和管理本协议
    } +
    +

    协议内容

    + +
    + { + !details.is_sign && !details.is_member && + +
    + + {getFieldDecorator("real_name",{ + rules:[{ required: true, message: "请输入您的真实姓名" }] + })( + + )} + + + {getFieldDecorator("email",{ + rules:[{ required: true, message: "请输入签署邮箱" }] + })( + + )} + +
    + + + } +
    +
    + : +
    + ) +} +export default Form.create()(forwardRef(CLAinfos)) \ No newline at end of file diff --git a/src/forge/Team/Setting/cla/TeamSettingCLA.jsx b/src/forge/Team/Setting/cla/TeamSettingCLA.jsx new file mode 100644 index 00000000..a207f0c8 --- /dev/null +++ b/src/forge/Team/Setting/cla/TeamSettingCLA.jsx @@ -0,0 +1,63 @@ +import React,{ useState , useEffect } from 'react'; +import Title from '../../../Component/Title'; +import defaultimg from '../../images/cla-icon-big.png'; +import Logo from '../../images/icon.svg'; +import { Button, Spin } from 'antd'; +import axios from 'axios'; + +function TeamSettingCLA(props){ + const OIdentifier = props.match.params.OIdentifier; + const [ list , setList ] = useState(undefined); + const [ isSpin , setisSpin ] = useState(false); + + useEffect(()=>{ + if(OIdentifier){ + setisSpin(true); + getList(); + } + },[OIdentifier]) + + function getList(){ + const url = `/organizations/${OIdentifier}/clas.json`; + axios.get(url).then(response=>{ + if(response){ + let l = {...response.data}; + setList(l); + setisSpin(false); + } + }).catch(error=>{}) + } + + return( +
    + CLA管理 + { + (list && list.id) && +
      +
    • + +
      +

      {list.name}

      + 签署人数{list.count || 0} +
      + + +
      +
      +
    • +
    + } + { + (list && !list.id) && +
    + +

    CLA( Contributor License Agreement)指开源贡献者许可协议。您可以为本组织配置CLA,当非组织用户作为贡献者在组织仓库提交合并请求之前,需要签署CLA后才可正常提交合并请求

    + +
    + } + { list === undefined &&
    } + +
    + ) +} +export default TeamSettingCLA; \ No newline at end of file diff --git a/src/forge/Team/Setting/cla/TeamSettingCLAEdit.jsx b/src/forge/Team/Setting/cla/TeamSettingCLAEdit.jsx new file mode 100644 index 00000000..a7d95659 --- /dev/null +++ b/src/forge/Team/Setting/cla/TeamSettingCLAEdit.jsx @@ -0,0 +1,133 @@ +import React ,{ forwardRef , useState , useEffect } from 'react'; +import Title from '../../../Component/Title'; +import MdEditor from "../../../../modules/tpm/challengesnew/tpm-md-editor"; +import { Button, Form , Input , Switch } from 'antd'; +import { turnbar , returnbar } from 'educoder'; +import { Link } from 'react-router-dom'; +import axios from 'axios'; + +export default Form.create()( +forwardRef((props)=>{ + const { form , match , showNotification , history , location } = props; + const { getFieldDecorator , validateFields , setFieldsValue , getFieldsValue} = form; + const [ switchBtn , setSwitchBtn ] = useState(false); + const [ details , setDetails] = useState(undefined); + const OIdentifier = match.params.OIdentifier; + const claid = match.params.claid; + const keyBefore = window.location.origin+`/${OIdentifier}/cla/`; + + useEffect(()=>{ + if(claid){ + getDetails(); + } + },[claid]) + + function getDetails(){ + const url = `/organizations/${OIdentifier}/clas/${claid}.json`; + axios.get(url).then(response=>{ + if(response && response.data){ + setFieldsValue({ + ...response.data + }) + setSwitchBtn(response.data.pr_need); + setDetails(response.data); + } + }).catch(error=>{}) + } + + + // 新建保存 + function saveClaFunc(){ + validateFields((error,values)=>{ + if(!error){ + const params = { + pr_need:switchBtn, + ...values, + key:turnbar(values.key) + } + if(claid){ + const url = `/organizations/${OIdentifier}/clas/${claid}.json`; + axios.put(url,{ + ...params + }).then(response=>{ + if(response && response.data){ + window.scrollTo(0,0); + showNotification("协议更新成功!"); + history.push(`/${OIdentifier}/setting/agreement`); + } + }).catch(error=>{}) + }else{ + const url = `/organizations/${OIdentifier}/clas.json`; + axios.post(url,{ + ...params + }).then(response=>{ + if(response && response.data && response.data.id){ + window.scrollTo(0,0); + showNotification("协议创建成功!"); + history.push(`/${OIdentifier}/setting/agreement`); + } + }).catch(error=>{}) + } + } + }) + } + + function checkKeyReg(rule, value, callback){ + let reg = /^[a-zA-Z0-9][a-zA-Z0-9_]*[a-zA-Z0-9]+$/g + if(value && !reg.test(value)){ + callback("协议标识长度2-30,只能以数字、字母开头结尾,可包含下划线"); + } + callback(); + } + + return( +
    + { + claid ? + <span><Link to={`/${OIdentifier}/setting/agreement`} className="color-blue mr3">CLA管理</Link>><span className="ml2">编辑协议</span></span> + : 创建CLA + } + +
    + + {getFieldDecorator("name",{ + rules:[{ required: true, message: "请输入协议名称" }] + })( + + )} + + + {getFieldDecorator("key",{ + rules:[ + { required: true, message: "请输入协议标识" }, + { validator: checkKeyReg } + ] + })( + + )} + + + {getFieldDecorator("content",{ + rules:[{ required: true, message: "请输入协议内容" }] + })( + + )} + +

    合并请求准入设置:

    + + setSwitchBtn(e)}/> + 要求 Pull Request 中所有提交者必须签署 CLA 方可合并 + + + {/* { claid && } */} +
    +
    + ) +} +)) diff --git a/src/forge/Team/Setting/teamSetting.scss b/src/forge/Team/Setting/teamSetting.scss new file mode 100644 index 00000000..6f5a21bc --- /dev/null +++ b/src/forge/Team/Setting/teamSetting.scss @@ -0,0 +1,132 @@ +.cla_default_box{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 320px; + .cla_default_desc{ + width: 80%; + color:#666666; + font-size:15px; + line-height:30px; + text-align:center; + margin:20px 0px!important; + } +} +.cla_list_box{ + display: flex; + flex-wrap: wrap; + padding-top: 25px; + li{ + margin-right: 24px; + border:1px solid; + border-color:rgba(153, 153, 153, 0.3); + border-radius:6px; + width: 446px; + display: flex; + padding:30px 26px; + box-sizing: border-box; + justify-content: flex-start; + align-items: flex-start; + margin-bottom: 25px; + &:nth-child(2n){ + margin-right: 0px; + } + .cla_list_infos{ + flex:1; + width: 0; + .cla_name{ + color:#151d40; + font-size:16px; + padding-bottom:20px; + height: 22px; + line-height: 22px; + word-break: break-all; + margin-bottom: 14px!important; + } + .cla_personCount{ + color:#4c5876; + display: block; + margin-bottom: 15px!important; + span{ + margin-left: 10px; + } + } + } + } +} +.cla_allinfos{ + .cla_infos_header{ + background-color:rgba(70, 106, 255, 0.05); + padding:30px 0px; + &>div{ + display: flex; + align-items: center; + margin:0px auto; + width: 1200px; + &>img{ + height: 94px; + margin-right: 32px; + border-radius: 4px; + } + .cla_i{ + flex: 1; + width: 0; + .cla_i_name{ + font-weight:700; + color:#333333; + font-size:24px; + height: 33px; + line-height: 33px; + margin-bottom: 0px!important; + } + .cla_o_name,.cla_i_email{ + color:#4c5b76; + font-size:15px; + height: 20px; + line-height: 20px; + margin-top: 18px; + } + .cla_i_email{ + margin-top: 12px; + } + } + } + } + .wirtes_tips{ + margin:25px 0px; + span{ + padding:9px 18px; + font-size:15px; + border:1px solid; + border-radius:6px; + border-color:#009b28; + color: #009b28; + } + } + .cla_c{ + width: 100%; + background-color:rgba(245, 245, 245, 0.5); + border-radius: 2px; + padding:25px; + margin:16px auto; + .cla_c_title{ + font-weight:700; + color:#202d40; + font-size:15px; + padding-bottom:20px; + height: 22px; + line-height: 22px; + margin-bottom: 15px!important; + } + } + .form_div{ + display: flex; + &>div{ + flex:1 + } + &>div:first-child{ + margin-right: 40px; + } + } +} \ No newline at end of file diff --git a/src/forge/Team/Sub/Detail.jsx b/src/forge/Team/Sub/Detail.jsx index a7c57e79..eedce64b 100644 --- a/src/forge/Team/Sub/Detail.jsx +++ b/src/forge/Team/Sub/Detail.jsx @@ -6,7 +6,6 @@ import { setSeoMeta } from "educoder"; import Cards from '../../Component/Cards'; import axios from 'axios'; import '../Index.scss'; - const GroupDetails = Loadable({ loader: () => import("../Group/GroupDetails"), loading: Loading, @@ -40,6 +39,9 @@ function Detail(props){ if(pathname){ if(pathname.indexOf(`/${OIdentifier}/setting`)>-1){ setFlag(false); + if(detail && !detail.is_admin ){ + props.history.push("/nopage"); + } }else{ setFlag(true); } @@ -49,7 +51,7 @@ function Detail(props){ setButtonflagFlag(false); } } - },[pathname]) + },[pathname,detail]) useEffect(()=>{ if(OIdentifier){ @@ -111,7 +113,7 @@ function Detail(props){ } /> } - + {/* 组织团队-详情 */} }} > - { - return - }} - > + + { + return + }} + > + { diff --git a/src/forge/Team/images/cla-icon-big.png b/src/forge/Team/images/cla-icon-big.png new file mode 100644 index 00000000..c6e1ff0a Binary files /dev/null and b/src/forge/Team/images/cla-icon-big.png differ diff --git a/src/forge/Team/images/cla-icon.png b/src/forge/Team/images/cla-icon.png new file mode 100644 index 00000000..a04d1099 Binary files /dev/null and b/src/forge/Team/images/cla-icon.png differ diff --git a/src/forge/Team/images/cla-logo.png b/src/forge/Team/images/cla-logo.png new file mode 100644 index 00000000..d9a35de0 Binary files /dev/null and b/src/forge/Team/images/cla-logo.png differ diff --git a/src/forge/Team/images/cla.png b/src/forge/Team/images/cla.png new file mode 100644 index 00000000..1bb05815 Binary files /dev/null and b/src/forge/Team/images/cla.png differ diff --git a/src/forge/Team/images/icon.svg b/src/forge/Team/images/icon.svg new file mode 100644 index 00000000..121d52f4 --- /dev/null +++ b/src/forge/Team/images/icon.svg @@ -0,0 +1,13 @@ + + + + + + + + CLA + + + + + diff --git a/src/forge/css/index.scss b/src/forge/css/index.scss index 7066e01f..d1729294 100644 --- a/src/forge/css/index.scss +++ b/src/forge/css/index.scss @@ -260,7 +260,6 @@ form{ margin-bottom: 12px; border-radius:2px; background-color: #fff; - padding: 20px 0; border:1px solid rgba(79, 108, 188, 0.21); &>li{ font-size: 15px; diff --git a/src/glcc/api.js b/src/glcc/api.js index f15c7a95..5d930499 100644 --- a/src/glcc/api.js +++ b/src/glcc/api.js @@ -222,4 +222,13 @@ export function deleteApplyInfo(data) { method: 'post', data }); -} \ No newline at end of file +} + +// 判断课题是否有学生报名 +export async function findStudentTaskByTaskId(params) { + return await fetch({ + url: '/api/applyInformation/findStudentTaskByTaskId', + method: 'get', + params: params, + }); +} diff --git a/src/glcc/apply/editInfo.jsx b/src/glcc/apply/editInfo.jsx index b9198b41..b9b836e4 100644 --- a/src/glcc/apply/editInfo.jsx +++ b/src/glcc/apply/editInfo.jsx @@ -1,7 +1,7 @@ import React , { useCallback, useEffect , useState } from 'react'; import { Button, Form, Input, Select, Upload, message, Popconfirm } from 'antd'; import {getUploadActionUrl} from 'educoder'; -import {applyGlcc, updateApplyGlcc} from '../api'; +import {applyGlcc, findStudentTaskByTaskId, updateApplyGlcc} from '../api'; import TextArea from 'antd/lib/input/TextArea'; import { main_site_url } from '../fetch'; import TaskApply from './taskApply'; @@ -13,7 +13,7 @@ function EditRepoApplyInfo(props) { const {form, applyInfo, current_user, round, cateList, setReload, isAddRepo, setIsAddRepo, setIsEdit, setEditRepoCount} = props; const phonereg = /(^|\s*\+?0?0?86|\D)(1\d{2})[-\s]{0,3}(\d{4})[-\s]{0,3}(\d{4})(?=\D|$)/ const emailreg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ - const {getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll } = form; + const {getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll, getFieldValue } = form; const [imageUrl, setImageUrl] = useState(undefined); // 提交按钮loading效果 const [loading, setLoading] = useState(false); @@ -27,7 +27,7 @@ function EditRepoApplyInfo(props) { const taskCountArr = [] registrationTaskList.map((item, index)=>{ taskCountArr.push(index+1); - const{taskName, taskUrl, taskDifficulty, taskReward, tutorName, tutorMail, taskDesc, tutorPhone} = item; + const{taskName, taskUrl, taskDifficulty, taskReward, tutorName, tutorMail, taskDesc, tutorPhone, id} = item; taskInfo[`taskName${index+1}`] = taskName; taskInfo[`taskUrl${index+1}`] = taskUrl; taskInfo[`taskDifficulty${index+1}`] = taskDifficulty; @@ -36,6 +36,7 @@ function EditRepoApplyInfo(props) { taskInfo[`tutorMail${index+1}`] = tutorMail; taskInfo[`taskDesc${index+1}`] = taskDesc; taskInfo[`tutorPhone${index+1}`] = tutorPhone; + taskInfo[`taskId${index+1}`] = id; }) setTaskCount(taskCountArr); setTimeout(() => { @@ -76,6 +77,7 @@ function EditRepoApplyInfo(props) { const registrationTaskList = [] taskCount && taskCount.map(item=>{ registrationTaskList.push({ + id: values[`taskId${item}`], taskName: values[`taskName${item}`], taskUrl: values[`taskUrl${item}`], taskDifficulty: values[`taskDifficulty${item}`], @@ -157,14 +159,19 @@ function EditRepoApplyInfo(props) { // 添加课题输入框 function addTaskApplyForm(){ - setTaskCount(taskCount.concat([taskCount.length+1])); + setTaskCount(taskCount.concat([taskCount[taskCount.length-1]+1])); } // 删除课题报名 - function deleteTaskApply(index){ - const arr = [...taskCount]; - arr.splice(index-1, 1) - setTaskCount(arr); + async function deleteTaskApply(index){ + const delTaskId = getFieldValue(`taskId${index}`); + const res = delTaskId ? await findStudentTaskByTaskId({ taskId: delTaskId }) : "newTask"; + if((res && res.data && res.data.length)){ + message.error("已有学生报名,不允许删除"); + }else{ + const arr = taskCount.filter(item=>item!== index); + setTaskCount(arr); + } } // 取消编辑点击函数 @@ -267,7 +274,7 @@ function EditRepoApplyInfo(props) {
    课题信息({index+1}/5)
    {index>0 && } - +
    })} {taskCount && taskCount.length<5 &&
    diff --git a/src/glcc/apply/taskApply.jsx b/src/glcc/apply/taskApply.jsx index a263f9bd..86ed6c5f 100644 --- a/src/glcc/apply/taskApply.jsx +++ b/src/glcc/apply/taskApply.jsx @@ -4,7 +4,7 @@ import TextArea from 'antd/lib/input/TextArea'; const Option = Select.Option; // 课题信息编辑 function TaskApply(props) { - const {helper, disabled, taskKey, phonereg, emailreg} = props; + const {helper, disabled, taskKey, phonereg, emailreg, getFieldDecorator} = props; // 低、中、高 const difficultyList = [ {id: 1, name: "低"}, @@ -26,6 +26,9 @@ function TaskApply(props) { return(
    + {helper('课题名称', '', `taskName${taskKey}`,