forked from Gitlink/forgeplus-react
Merge remote-tracking branch 'upstream/gitlink_server' into gitlink_server
This commit is contained in:
commit
7b1dc69f82
|
|
@ -19,7 +19,7 @@ export function getImageUrl(path) {
|
|||
return `${path}`;
|
||||
}
|
||||
|
||||
export function IsPC(){
|
||||
export function isPhone(){
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone",
|
||||
"SymbianOS", "Windows Phone",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export {
|
|||
getImageUrl as getImageUrl,getImageUrlAbsolute as getImageUrlAbsolute,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, getZoneUrl as getZoneUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
|
||||
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
|
||||
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl,
|
||||
turnbar,returnbar,setSeoMeta as setSeoMeta , IsPC as IsPC, addMeta as addMeta
|
||||
turnbar,returnbar,setSeoMeta as setSeoMeta , isPhone as isPhone, addMeta as addMeta
|
||||
} from './UrlTool';
|
||||
|
||||
export { setmiyah as setmiyah } from './Component';
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ li.ant-menu-item{
|
|||
border:1px solid #eee;
|
||||
.img{
|
||||
margin-right: 20px;
|
||||
width: 190px;
|
||||
max-width: 190px;
|
||||
height: 90px;
|
||||
border:1px solid rgba(238,238,238,1);
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Popconfirm, Radio, Input, message, Tooltip, Spin, Pagination } from 'antd';
|
||||
import axios from 'axios';
|
||||
import { getImageUrl, timeAgo } from 'educoder';
|
||||
import { getImageUrl, timeAgo, isPhone } from 'educoder';
|
||||
import RenderHtml from '../../../../components/render-html';
|
||||
import Attachment from '../../../Upload/attachment';
|
||||
import EditComment from './editComment';
|
||||
|
|
@ -109,7 +109,7 @@ function IssueCommentList(props){
|
|||
}
|
||||
|
||||
return(
|
||||
<div className="commentListBox">
|
||||
(isPhone() && journalsCount === 0) ? '' : <div className="commentListBox info_text mt30">
|
||||
{/* 评论 */}
|
||||
<div className={`${!login && journalsCount > 0 && 'pb15'}`}>
|
||||
<div className='typeActionBox mb20'>
|
||||
|
|
@ -118,7 +118,7 @@ function IssueCommentList(props){
|
|||
</div>
|
||||
</div>
|
||||
{/* 评论快速入口-仅有评论且登录时展示 */}
|
||||
{login && category !== 'operate' && journalsCount > 0 && <div className={`pb30 ${journalsCount > 0 && 'pt15'}`}><div className='gotoComment'>点击<a className='ml5' href='#addComments'>添加评论</a></div></div>}
|
||||
{login && category !== 'operate' && journalsCount > 0 && !isPhone() && <div className={`pb30 ${journalsCount > 0 && 'pt15'}`}><div className='gotoComment'>点击<a className='ml5' href='#addComments'>添加评论</a></div></div>}
|
||||
{/* 评论/操作日志 展示列表 */}
|
||||
<Spin spinning={spin}>
|
||||
<div className={`issueCommentsBox ${category === 'comment' && !spin && 'justComment'}`}>
|
||||
|
|
@ -135,7 +135,7 @@ function IssueCommentList(props){
|
|||
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
|
||||
<span className='ml15 timeAgo font-14'>{timeAgo(item.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{login && !isPhone() && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
|
||||
{(admin || isManager || login === item.user.login || username === author) && <Popconfirm
|
||||
placement="bottom"
|
||||
|
|
@ -172,7 +172,7 @@ function IssueCommentList(props){
|
|||
<span>{i.reply_user && i.reply_user.name}</span>
|
||||
<span className='ml15 timeAgo font-14'>{timeAgo(i.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{login && !isPhone() && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
|
||||
{(admin || isManager || login === i.user.login || (i.reply_user && login === i.reply_user.login) || username === author) && <Popconfirm
|
||||
placement="bottom"
|
||||
|
|
@ -207,7 +207,7 @@ function IssueCommentList(props){
|
|||
<Pagination simple current={page} pageSize={limit} total={totalCount} onChange={(page)=>setPage(page)}/>
|
||||
</div>}
|
||||
{/* 添加评论 */}
|
||||
{category !== 'operate' && <div className="pb30" style={{marginTop: journalsCount ? '-5px' : '30px'}}>
|
||||
{category !== 'operate' && !isPhone() && <div className="pb30" style={{marginTop: journalsCount ? '-5px' : '30px'}}>
|
||||
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addComments" id='addComments'>
|
||||
<img src={getImageUrl(image_url)} alt="" />
|
||||
<div style={{flex:1}}>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { httpUrl } from '../fetch';
|
|||
import guideArrow from '../img/guideArrow.png';
|
||||
import { Link } from 'react-router-dom';
|
||||
import shijian from '../img/shijian.png';
|
||||
import { getHomePageList , gethomePageDocList , getAllList } from '../api';
|
||||
import { getHomePageList , gethomePageDocList , getAllList, getPartnerList } from '../api';
|
||||
import axios from 'axios';
|
||||
import Partner from '../Component/partner';
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ function HeaderPage(props){
|
|||
getProjectList();
|
||||
getNewsList();
|
||||
getPersonList();
|
||||
getPartnerList();
|
||||
getPartner();
|
||||
}
|
||||
},[id])
|
||||
|
||||
|
|
@ -49,9 +49,8 @@ function HeaderPage(props){
|
|||
}).catch(console.error())
|
||||
}
|
||||
|
||||
function getPartnerList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/partners/list`;
|
||||
axios.get(url).then(result=>{
|
||||
function getPartner(){
|
||||
getPartnerList(id).then(result => {
|
||||
if(result){
|
||||
const array = result.data.rows;
|
||||
const newArray = [];
|
||||
|
|
@ -66,7 +65,7 @@ function HeaderPage(props){
|
|||
}
|
||||
setParterList(newArray);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
})
|
||||
}
|
||||
return(
|
||||
<div className="zone_box">
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ import ra from '../img/ra.png'
|
|||
import title from '../img/title.png'
|
||||
import { Link } from 'react-router-dom';
|
||||
import shijian from '../img/shijian.png';
|
||||
import axios from 'axios';
|
||||
import Nodata from '../../Nodata';
|
||||
import Projects from '../Component/projects';
|
||||
import Contributor from '../Component/contributor';
|
||||
import Partner from '../Component/partner';
|
||||
import '../indexZone1.scss'
|
||||
import { getProjectsLists, getPartnerList, getHomePageList, gethomePageDocList } from '../api'
|
||||
|
||||
function HeaderPage(props){
|
||||
const [ projectList , setProjectList ] = useState(undefined);
|
||||
|
|
@ -65,13 +65,12 @@ function HeaderPage(props){
|
|||
getProjectList();
|
||||
getNewsList();
|
||||
getPersonList();
|
||||
getPartnerList();
|
||||
getPartner();
|
||||
}
|
||||
},[id])
|
||||
|
||||
function getPersonList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/member/homePageList`;
|
||||
axios.get(url).then(result=>{
|
||||
getHomePageList(id).then(result=>{
|
||||
if(result){
|
||||
setPersonList(result.data.rows);
|
||||
}
|
||||
|
|
@ -79,19 +78,14 @@ function HeaderPage(props){
|
|||
}
|
||||
|
||||
function getNewsList(){
|
||||
const url = `${httpUrl}/cms/doc/open/zone/${id}/homePageDocList`;
|
||||
axios.get(url).then(result=>{
|
||||
gethomePageDocList(id).then(result=>{
|
||||
if(result){
|
||||
setNewsList(result.data.rows);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getProjectList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/project/list`;
|
||||
axios.get(url,{params:{
|
||||
isHomepage:1
|
||||
}}).then(result=>{
|
||||
getProjectsLists(id,{ isHomepage:1 }).then(result=>{
|
||||
if(result){
|
||||
if (result.data.rows.length < 3) {
|
||||
setProjectList(result.data.rows)
|
||||
|
|
@ -99,12 +93,11 @@ function HeaderPage(props){
|
|||
setProjectList([...result.data.rows, {}]);
|
||||
}
|
||||
}
|
||||
}).catch(console.error())
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function getPartnerList(){
|
||||
const url = `${httpUrl}/zone/open/${id}/partners/list`;
|
||||
axios.get(url).then(result=>{
|
||||
function getPartner(){
|
||||
getPartnerList(id).then(result => {
|
||||
if(result){
|
||||
const array = result.data.rows;
|
||||
const newArray = [];
|
||||
|
|
@ -119,7 +112,7 @@ function HeaderPage(props){
|
|||
}
|
||||
setParterList(newArray);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
})
|
||||
}
|
||||
return(
|
||||
<div className="zone1_box">
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function NewsCreate(props){
|
|||
const [dirList, setDirList] = useState(undefined);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const { sectionCmsTitle } = props.data;
|
||||
const layout = {
|
||||
labelCol: { span: 2 },
|
||||
wrapperCol: { span: 14 },
|
||||
|
|
@ -123,7 +124,7 @@ function NewsCreate(props){
|
|||
return(
|
||||
<div className='boxmain pt30 newsCreateBox pb100'>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{ sectionCmsTitle }</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{isEdit ? '编辑' : '新建'}文章</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className='formBox'>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import liulan from '../img/liulan.png';
|
|||
import RenderHtml from '../../../components/render-html';
|
||||
import { Base64 } from 'js-base64';
|
||||
import { getNewsDetail } from '../api';
|
||||
import { IsPC } from 'educoder';
|
||||
import { isPhone } from 'educoder';
|
||||
import { tempConfig } from '../tempInfo';
|
||||
import Acce from '../Component/mobile/accessory';
|
||||
import { addMeta, setSeoMeta } from 'educoder';
|
||||
|
|
@ -23,7 +23,13 @@ function NewsDetail(props){
|
|||
|
||||
useEffect(()=>{
|
||||
let initialContent = undefined;
|
||||
if(IsPC() && zonedetail){
|
||||
// 设置网页标题
|
||||
if(detail){
|
||||
const { name, cmsDir, summary} = detail;
|
||||
document.title = `${ name }/${ cmsDir.name }`;
|
||||
addMeta('Keywords', `${ name },${ cmsDir.name },${ summary }`);
|
||||
}
|
||||
if(isPhone() && zonedetail){
|
||||
setTimeout(()=>{
|
||||
window.scrollTo(0,1);
|
||||
if(detail)
|
||||
|
|
@ -33,36 +39,23 @@ function NewsDetail(props){
|
|||
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width, user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0');
|
||||
}
|
||||
return()=>{
|
||||
if(IsPC()){
|
||||
if(isPhone()){
|
||||
document.querySelector('meta[name="viewport"]').setAttribute('content', initialContent);
|
||||
}
|
||||
if (zonedetail) {
|
||||
document.title= zonedetail.mainTitle;
|
||||
setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}
|
||||
},[zonedetail,detail])
|
||||
|
||||
useEffect(()=>{
|
||||
if(id){
|
||||
window.scrollTo(0,IsPC() ? 0 : 450);
|
||||
window.scrollTo(0,isPhone() ? 0 : 450);
|
||||
getDetails();
|
||||
}
|
||||
},[id])
|
||||
|
||||
useEffect(()=>{
|
||||
// 设置网页标题
|
||||
if(detail){
|
||||
const { name, cmsDir, summary} = detail;
|
||||
document.title = `${ name }/${ cmsDir.name }`;
|
||||
addMeta('Keywords', `${ name },${ cmsDir.name },${ summary }`);
|
||||
}
|
||||
return componentWillUnmount
|
||||
}, [detail])
|
||||
|
||||
function componentWillUnmount() {
|
||||
if (zonedetail) {
|
||||
document.title= zonedetail.name;
|
||||
setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}
|
||||
|
||||
function getDetails(){
|
||||
setIsSpin(true)
|
||||
getNewsDetail(id).then(result=>{
|
||||
|
|
@ -82,24 +75,24 @@ function NewsDetail(props){
|
|||
return(
|
||||
<React.Fragment>
|
||||
{
|
||||
IsPC() && <Acce type="head"/>
|
||||
isPhone() && <Acce type="head"/>
|
||||
}
|
||||
<div className={IsPC() ? "detail_news_phone" :"detail_news_all"}>
|
||||
<div className={isPhone() ? "detail_news_phone" :"detail_news_all"}>
|
||||
<Spin spinning={isSpin} size="large">
|
||||
{
|
||||
detail &&
|
||||
<div className="d_news_box">
|
||||
{
|
||||
IsPC() && zonedetail &&
|
||||
isPhone() && zonedetail &&
|
||||
<div className="p_title_box">
|
||||
<p className="p_t_title"><a href={`/zone/${deptId}`}>{zonedetail.name}</a></p>
|
||||
<p className="p_t_desc" dangerouslySetInnerHTML={{ __html: zonedetail.introductionContent }}></p>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
!IsPC() &&
|
||||
!isPhone() &&
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{ zonedetail.sectionCmsTitle }</Breadcrumb.Item>
|
||||
{ cmsDir && <Breadcrumb.Item href={`/zone/${deptId}/news/${cmsDir.id}`}>{cmsDir.name}</Breadcrumb.Item> }
|
||||
<Breadcrumb.Item>正文</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
|
@ -115,7 +108,7 @@ function NewsDetail(props){
|
|||
{ detail.auditStatus === '0' && <li><Badge color="#eb1212" text="未通过" className='failed'/></li>}
|
||||
</ul>
|
||||
</div>
|
||||
{ !IsPC() && <Divider dashed={true} /> }
|
||||
{ !isPhone() && <Divider dashed={true} /> }
|
||||
{
|
||||
content ?
|
||||
<RenderHtml className="informations_detail imageLayerParent" value={content} url={props.history.location} />
|
||||
|
|
@ -125,7 +118,7 @@ function NewsDetail(props){
|
|||
</div>
|
||||
{
|
||||
// 审核通过才有评论
|
||||
detail.auditStatus === '1' && <div className="info_text mt30">
|
||||
detail.auditStatus === '1' && <div>
|
||||
<CommentList {...props} docId={ id } reload={commentReload} author={ detail.createBy } reloadComment={()=>{setCommentReload(Math.random())}}/>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -135,7 +128,7 @@ function NewsDetail(props){
|
|||
</Spin>
|
||||
</div>
|
||||
{
|
||||
IsPC() && <Acce type="foot" />
|
||||
isPhone() && <Acce type="foot" />
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function SelfList(props){
|
|||
const pathname = props.location.pathname;
|
||||
const { deptId} = props.match.params;
|
||||
const { id , temp , data } = props;
|
||||
const { sectionCmsTitle } = data;
|
||||
const limit = 15;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -142,7 +143,7 @@ function SelfList(props){
|
|||
</div>
|
||||
</Modal>
|
||||
<Breadcrumb separator=">" style={{paddingTop:"20px"}}>
|
||||
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{source ? "资源发布": temp === tempEnum.zone1 ? "新闻资讯":"领域资讯"}</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item><Link className="primaryColor" to={pathname.replace("/self","")}>{ sectionCmsTitle }</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item>我的{source ? "资源":"文章"}</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<ul className="selfMenu">
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function SourceDetail(props){
|
|||
|
||||
function componentWillUnmount() {
|
||||
if (zonedetail) {
|
||||
document.title= zonedetail.name;
|
||||
document.title= zonedetail.mainTitle;
|
||||
setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ export function getAllList(id,params){
|
|||
})
|
||||
}
|
||||
|
||||
export function getPartnerList(id){
|
||||
return fetch({
|
||||
url:`/zone/open/${id}/partners/list`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**领域资讯 */
|
||||
export function getNewsAllList(id,params){
|
||||
return fetch({
|
||||
|
|
|
|||
|
|
@ -5,11 +5,22 @@ function beforeFetch(actionUrl){
|
|||
if (window.location.href.indexOf('localhost') < 0) {
|
||||
axios.defaults.withCredentials = true;
|
||||
}
|
||||
|
||||
const service = axios.create({
|
||||
const config = {
|
||||
baseURL: actionUrl,
|
||||
timeout: 1800000, // 请求超时时间
|
||||
});
|
||||
}
|
||||
|
||||
const service = axios.create(config);
|
||||
|
||||
service.interceptors.request.use(request => {
|
||||
let deptId = sessionStorage.getItem('deptId')
|
||||
|
||||
if (deptId) {
|
||||
// 用于权限区分
|
||||
request.headers['Dept-Id'] = deptId
|
||||
}
|
||||
return request
|
||||
})
|
||||
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import Loading from "../../Loading";
|
|||
import { getMainInfos , getCheckZoneRole, getCurrentRole } from './api';
|
||||
import PublicBanner from "./Component/publicBanner";
|
||||
import './index.scss';
|
||||
import { IsPC } from 'educoder';
|
||||
import { isPhone } from 'educoder';
|
||||
import "slick-carousel/slick/slick.css";
|
||||
import "slick-carousel/slick/slick-theme.css";
|
||||
import { tempEnum } from "./tempInfo";
|
||||
|
|
@ -98,7 +98,7 @@ function Index(props){
|
|||
const [ temp , setTemp ] = useState(tempEnum.zone);
|
||||
const [ role , setRole ] = useState(undefined);
|
||||
const { pathname } = props.history.location;
|
||||
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && IsPC();
|
||||
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && isPhone();
|
||||
const {current_user} = props;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -124,16 +124,18 @@ function Index(props){
|
|||
return
|
||||
}
|
||||
let data = result.data.data;
|
||||
if (data.template) {
|
||||
if (data && data.template) {
|
||||
setTemp( data.template )
|
||||
}
|
||||
setData(data);
|
||||
document.title= data && data.name;
|
||||
document.title= data && data.mainTitle;
|
||||
setId(data.id);
|
||||
if(data.id){
|
||||
getAdminUrl(data.id);
|
||||
getRole(data.id)
|
||||
}
|
||||
// 存储deptId,所有专区接口header带上
|
||||
sessionStorage.setItem('deptId', data.deptId)
|
||||
setSeoMeta(`${data.name},`, data.name, data.subTitle, `/zone/${deptId}`)
|
||||
}
|
||||
}).catch(console.error())
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@ function List(props){
|
|||
}else{
|
||||
Init();
|
||||
}
|
||||
// 标签列表页点击跳转issue列表页并筛选
|
||||
if (props.location.state && props.location.state.issue) {
|
||||
chooseTagFunc(props.location.state.issue)
|
||||
}
|
||||
},[])
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
|
|||
|
|
@ -189,6 +189,12 @@ function Sign(props){
|
|||
c && setDefaultColor(`#${c}`);
|
||||
setEdit(true);
|
||||
}
|
||||
|
||||
// 标签列表页点击跳转issue列表页并筛选
|
||||
function toIssues(issue) {
|
||||
props.history.push({ pathname: `/${owner}/${projectsId}/issues`, state: { issue: issue } });
|
||||
}
|
||||
|
||||
return(
|
||||
<div>
|
||||
<DelBox
|
||||
|
|
@ -236,11 +242,11 @@ function Sign(props){
|
|||
<p>
|
||||
<span className="square mr10" style={{backgroundColor:`${i.color}`}}></span>
|
||||
<i className="iconfont icon-biaoji mr3 font-12 " style={{color:`${i.color}`}}></i>
|
||||
<span className="task-hide" title={i.name} style={{maxWidth:210}}>{i.name}</span>
|
||||
<span className="task-hide color-blue pointer" title={i.name} style={{maxWidth:210}} onClick={() => toIssues(i) }>{i.name}</span>
|
||||
</p>
|
||||
<p style={{flex:2}} className="task-hide">{i.description}</p>
|
||||
<p>
|
||||
<span>{i.issues_count || 0} 疑修</span>
|
||||
<span><span className="task-hide color-blue pointer" onClick={() => toIssues(i) } >{i.issues_count || 0} </span> 疑修</span>
|
||||
{/* <span className="line">{i.pull_requests_count || 0} 合并请求</span> */}
|
||||
</p>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -511,9 +511,9 @@ function CoderDepot(props){
|
|||
}
|
||||
{
|
||||
checkIfLogin && checkIfLogin()?
|
||||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE <div className='newBtnImg'></div></a>
|
||||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE</a>
|
||||
:
|
||||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE <div className='newBtnImg'></div></a>
|
||||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE</a>
|
||||
}
|
||||
|
||||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||
|
|
|
|||
|
|
@ -551,4 +551,10 @@
|
|||
|
||||
.replaceStyle{
|
||||
height: 140px!important;
|
||||
}
|
||||
.hovergrey:hover{
|
||||
border-color: #afb7c2;
|
||||
color:#4c5b76;
|
||||
background-color: rgba(175, 183, 194, 0.16);
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import { AlignCenter } from '../Component/layout';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
|
@ -78,6 +78,10 @@ class IndexItem extends Component {
|
|||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
||||
</span>
|
||||
{/* <span>
|
||||
<Button type="primary" size="small">置顶</Button>
|
||||
<Button size="small" style={{height:"26px",lineHeight:"24px"}} className="hovergrey">取消置顶</Button>
|
||||
</span> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<li className={pathname==="devops" ? "active" : ""}>
|
||||
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */}
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}>
|
||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>引擎(Engine)<div className='newBtnImg'></div>
|
||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>引擎(Engine)
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
|
|
@ -138,7 +138,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<li className={pathname === "server" ? "active" : ""}>
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/service`, state }}>
|
||||
<i className={"iconfont icon-fuwuicon color-grey-3 mr5 font-15"} style={{marginTop:"1px"}}></i>
|
||||
<span>服务</span><div className='newBtnImg'></div>
|
||||
<span>服务</span>
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_u
|
|||
if(value.length > 5){
|
||||
callback("最多创建5个标签");
|
||||
}else if(boolLength.length){
|
||||
callback("每个标签最多支持20个汉字");
|
||||
callback("每个标签最多支持20个字符");
|
||||
}else if(bool.length){
|
||||
callback("标签名只允许包含中文、字母、数字或者中划线(-), 不能以中划线开头");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect, Fragment } from "react";
|
||||
import { Button, message, Form, Input, Select } from "antd";
|
||||
import { Button, message, Form, Input, Select, Modal, Checkbox } from "antd";
|
||||
import "./index.scss";
|
||||
import "../../users/Material/Index.scss";
|
||||
import axios from "axios";
|
||||
|
|
@ -17,6 +17,9 @@ function CreateSite(props) {
|
|||
const [language, setLanguage] = useState(undefined);
|
||||
const [themes, setThemes] = useState([]);
|
||||
const [theme, setTheme] = useState(undefined);
|
||||
const [modalVisibal, setmodalVisibal] = useState(false);
|
||||
const [accept, setAccept] = useState(false);
|
||||
const [formValues, setFormValues] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "创建站点";
|
||||
|
|
@ -59,22 +62,34 @@ function CreateSite(props) {
|
|||
e.preventDefault();
|
||||
validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
axios.post(`/projects/page_migrate.json`,{
|
||||
...values,
|
||||
clone_addr: theme && theme.clone_url,
|
||||
theme: theme && theme.name,
|
||||
user_id: current_user.user_id,
|
||||
identifier: values.identifier.split("http://")[1]
|
||||
}).then(res=>{
|
||||
if(res && res.status === 200){
|
||||
message.success("新建成功");
|
||||
history.push(`/settings/mysite`);
|
||||
}
|
||||
})
|
||||
setmodalVisibal(true)
|
||||
setFormValues(values)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function confirmSubmit() {
|
||||
axios.post(`/projects/page_migrate.json`,{
|
||||
...formValues,
|
||||
site_name: formValues.identifier,
|
||||
clone_addr: theme && theme.clone_url,
|
||||
theme: theme && theme.name,
|
||||
user_id: current_user.user_id,
|
||||
identifier: formValues.identifier.split("http://")[1]
|
||||
}).then(res=>{
|
||||
onCancel()
|
||||
if(res && res.status === 200){
|
||||
message.success("新建成功");
|
||||
history.push(`/settings/mysite`);
|
||||
}
|
||||
})
|
||||
}
|
||||
function onCancel() {
|
||||
setmodalVisibal(false);
|
||||
setAccept(false);
|
||||
setFormValues({});
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="mySites_head mb30"><Link to={`/settings/mysite`} className="font-16">我的站点 / </Link><span>新建站点</span></div>
|
||||
|
|
@ -89,22 +104,18 @@ function CreateSite(props) {
|
|||
onSubmit={submit}
|
||||
>
|
||||
<div className="formTitle font-16 mb20 ml20">站点配置</div>
|
||||
<Form.Item name="站点名称" label="站点名称">
|
||||
{/* <Form.Item name="站点名称" label="站点名称">
|
||||
{getFieldDecorator("site_name", {
|
||||
rules: [{ required: true, message: "请输入站点名称" },
|
||||
{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
})(<Input placeholder="请输入站点名称" />)}
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<Form.Item
|
||||
name="站点标识"
|
||||
label="站点标识"
|
||||
className="Create-Form-biaoshi"
|
||||
>
|
||||
{getFieldDecorator("identifier", {
|
||||
rules: [{ required: true, message: "请输入站点标识" },
|
||||
// {pattern: /^[a-zA-Z0-9]{2,100}$/, message: '长度2-100,只能包含数字和字母'}
|
||||
],
|
||||
})(
|
||||
{getFieldDecorator("identifier")(
|
||||
<Input
|
||||
onChange={(e) => {
|
||||
setTag(e.target.value);
|
||||
|
|
@ -154,7 +165,7 @@ function CreateSite(props) {
|
|||
{/* <span className="mb20 font-18">/</span> 0.87 */}
|
||||
<Form.Item name="项目标识" label="项目标识" style={{flex: '0.83'}} labelCol={{span: 4}}>
|
||||
{getFieldDecorator("repository_name", {
|
||||
rules: [{ required: true, message: "请输入项目标识" },
|
||||
rules: [
|
||||
{pattern: /^[a-zA-Z0-9][a-zA-Z0-9_.-]{2,100}[a-zA-Z0-9]$/, message: "长度2-100,只能包含数字、字母、下划线、中划线、英文句号,必须以数字和字母开头,不能以下划线/中划线/英文句号开头和结尾"}],
|
||||
})(
|
||||
<Input placeholder="请输入项目标识" disabled/>
|
||||
|
|
@ -166,8 +177,7 @@ function CreateSite(props) {
|
|||
label="项目名称"
|
||||
>
|
||||
{getFieldDecorator("name", {
|
||||
rules: [{ required: true, message: "请输入项目名称" },
|
||||
{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
rules: [{type: 'string', max: 50, min: 1, message: "长度1-50"}],
|
||||
})(
|
||||
<Input placeholder="请输入项目名称" disabled/>
|
||||
)}
|
||||
|
|
@ -192,6 +202,40 @@ function CreateSite(props) {
|
|||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Modal
|
||||
visible={modalVisibal}
|
||||
onCancel={onCancel}
|
||||
footer={null}
|
||||
closable={false}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
width={'650px'}
|
||||
>
|
||||
<div className="m-header">
|
||||
个人建站声明
|
||||
<i className="iconfont icon-shanchuicon2 mr5 font-14" onClick={onCancel}></i>
|
||||
</div>
|
||||
<div className="m-content">
|
||||
<p>个人建站服务仅供Jekyll、Hugo、Hexo静态网站效果演示用途,请勿用于违规内容,包括但不仅限于:</p>
|
||||
<ul>
|
||||
<ol>发布诱导分享/诱导关注/诱导下载/诱导跳转内容</ol>
|
||||
<ol>发布欺诈/谣言/骚扰信息/广告信息/垃圾信息/特殊识别码、口令类信息</ol>
|
||||
<ol>发布低俗内容/“宗教性捐献”及相关信息</ol>
|
||||
<ol>发布侵害他人权利/违法经营及可疑服务类内容</ol>
|
||||
<ol>发布其它违反国家法律法规的内容</ol>
|
||||
</ul>
|
||||
<p>平台保留使用规则最终解释权,如发现上述违规行为,平台将视违规情况严重程度予以建站服务封禁以至账号永久封禁惩罚。</p>
|
||||
<Checkbox checked={accept} onChange={(e) => { setAccept(e.target.checked) }}>我已阅读并接受 《个人建站声明条款》</Checkbox>
|
||||
<div className="divider"></div>
|
||||
</div>
|
||||
<div className="m-footer">
|
||||
<Button onClick={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" className="mr20" disabled={ !accept } onClick={confirmSubmit}>
|
||||
确认
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,71 @@
|
|||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.m-header {
|
||||
background: url(../img/header.png) no-repeat;
|
||||
background-size: 101% 100%;
|
||||
height: 56px;
|
||||
text-align: center;
|
||||
line-height: 56px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
position: relative;
|
||||
i {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.m-content {
|
||||
padding: 19px 26px;
|
||||
font-size: 15px;
|
||||
color: #4C5B76;
|
||||
line-height: 30px;
|
||||
ul {
|
||||
padding: 10px 0;
|
||||
}
|
||||
ol {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: #202D40;
|
||||
opacity: 1;
|
||||
border-radius: 100%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
opacity: 1;
|
||||
border: 1px solid rgba(153,153,153,0.1);
|
||||
margin-top: 21px;
|
||||
}
|
||||
}
|
||||
.m-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px 0 27px 0;
|
||||
button {
|
||||
width: 120px;
|
||||
height: 36px;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
&:nth-of-type(1) {
|
||||
color: #666666;
|
||||
margin-right: 78px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -561,4 +561,19 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.plusCard{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
background-color: #fafafa;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1,22 +1,26 @@
|
|||
import React,{ forwardRef , useCallback , useEffect, useState } from 'react';
|
||||
import './Index.scss';
|
||||
import { Form , Input , Radio , Checkbox , Button } from "antd";
|
||||
import UploadImage from './Component/UploadImage';
|
||||
import { Form , Input , Icon , Checkbox , Button } from "antd";
|
||||
// import UploadImage from './Component/UploadImage';
|
||||
import AvatarModal from '../users/Avatar/Index';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
const port = window.location.port;
|
||||
const hostname = window.location.hostname;
|
||||
export default Form.create()(
|
||||
forwardRef(({ form , showNotification , history, showNpsModal })=>{
|
||||
const [ image , setImage ] = useState(undefined);
|
||||
const [ imageFlag , setImageFlag] = useState(false);
|
||||
const [ imageVisible , setIamgeVisible ] = useState(false);
|
||||
const [ descNum ,setDescNum ] = useState(0);
|
||||
|
||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
}
|
||||
// const radioStyle = {
|
||||
// display: 'block',
|
||||
// height: '30px',
|
||||
// lineHeight: '30px',
|
||||
// }
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, isRequired = true) => (
|
||||
<React.Fragment>
|
||||
|
|
@ -68,14 +72,27 @@ export default Form.create()(
|
|||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if(value && !value.match(/^[a-zA-Z0-9][a-zA-Z0-9_-]{3,19}$/)){
|
||||
callback("只能使用以字母、数字开头,包含字母、数字、下划线、横杠等,长度4到20个字符");
|
||||
let reg = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*$/
|
||||
if(value && !value.match(reg)){
|
||||
callback("只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符");
|
||||
}
|
||||
if(value && (value.length<4 || value.length>50)){
|
||||
callback("只能以数字或字母开头,仅支持横杠、下划线、点三种符号,不允许符号连续排列,长度4-50个字符12");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
function saveImgFunc(imgUrl){
|
||||
setImage(imgUrl);
|
||||
setIamgeVisible(false);
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="main" style={{padding:"0px",border:"none"}}>
|
||||
{
|
||||
imageVisible &&
|
||||
<AvatarModal avatarImg={image} onCancel={()=>{setIamgeVisible(false)}} saveFunc={saveImgFunc}/>
|
||||
}
|
||||
<div className="teamBox">
|
||||
<p className="teamBox-title">新建组织</p>
|
||||
<Form className="teamBox-form">
|
||||
|
|
@ -90,7 +107,7 @@ export default Form.create()(
|
|||
],
|
||||
<Input
|
||||
addonBefore={port ? `${hostname}:${port}/`:`https://${hostname}/`}
|
||||
placeholder="组织账号" maxLength={100}
|
||||
placeholder="组织账号" maxLength={50}
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
|
|
@ -131,11 +148,23 @@ export default Form.create()(
|
|||
<Radio style={radioStyle} value="privacy" key={3}>私有<span className="color-grey-8">(仅对组织成员可见)</span></Radio>
|
||||
</Radio.Group>
|
||||
)} */}
|
||||
|
||||
<p className="font-16 lables must">选择头像</p>
|
||||
<UploadImage getImage={getImage}/>
|
||||
{imageFlag && <p className="color-red" style={{marginTop:"-10px"}}>请上传头像</p> }
|
||||
|
||||
<div className="mb25">
|
||||
<p className="font-16 lables must mb10">选择头像</p>
|
||||
{/* <UploadImage getImage={getImage}/> */}
|
||||
<div className="plusCard" onClick={()=>{setIamgeVisible(true)}}>
|
||||
{
|
||||
image ?
|
||||
<img src={image} alt="avatar" style={{ width: '100%' }} />
|
||||
:
|
||||
<React.Fragment>
|
||||
<Icon type={'plus'} />
|
||||
<div className="ant-upload-text">点击上传</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
{/* <Button onClick={()=>{setIamgeVisible(true)}} type={"primary"}>点击选择</Button> */}
|
||||
{imageFlag && <p className="color-red">请上传头像</p> }
|
||||
</div>
|
||||
{helper(
|
||||
'权限',
|
||||
"repo_admin_change_team_access",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import React, { forwardRef , useCallback , useEffect, useState } from 'react';
|
||||
import { Form , Input , Radio ,Checkbox , Divider , Button , InputNumber } from 'antd';
|
||||
import { Form , Input , Icon ,Checkbox , Divider , Button , InputNumber } from 'antd';
|
||||
import { WhiteBack , FlexAJ } from '../../Component/layout';
|
||||
import Title from '../../Component/Title';
|
||||
import styled from 'styled-components';
|
||||
import UploadImage from '../Component/UploadImage';
|
||||
// import UploadImage from '../Component/UploadImage';
|
||||
import axios from 'axios';
|
||||
import Modals from '../Component/Modals';
|
||||
import AvatarModal from '../../users/Avatar/Index';
|
||||
|
||||
import { getImageUrl } from 'educoder';
|
||||
const TextArea = Input.TextArea;
|
||||
|
|
@ -27,6 +28,7 @@ export default Form.create()(
|
|||
const [ visible , setVisible ] = useState(false);
|
||||
const [ privacyVisible , setPrivacyVisible ] = useState(false);
|
||||
const [ descNum , setDescNum ] = useState(0);
|
||||
const [ imageVisible , setIamgeVisible ] = useState(false);
|
||||
const { getFieldDecorator , validateFields , setFieldsValue , getFieldsValue} = form;
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -75,7 +77,7 @@ export default Form.create()(
|
|||
function getImage(image){
|
||||
setImageFlag(true);
|
||||
setImage(image);
|
||||
console.log(image);
|
||||
setIamgeVisible(false);
|
||||
}
|
||||
|
||||
// 删除组织
|
||||
|
|
@ -123,6 +125,10 @@ export default Form.create()(
|
|||
}
|
||||
return(
|
||||
<div style={{border:"1px solid #eee"}}>
|
||||
{
|
||||
imageVisible &&
|
||||
<AvatarModal avatarImg={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} onCancel={()=>{setIamgeVisible(false)}} saveFunc={getImage}/>
|
||||
}
|
||||
<WhiteBack>
|
||||
<Title>基本设置</Title>
|
||||
<Modals visible={privacyVisible} okText={"确认"} cancelText={"取消"} onCancel={concelChangePrivacy} onOk={()=>setPrivacyVisible(false)}>
|
||||
|
|
@ -196,8 +202,19 @@ export default Form.create()(
|
|||
<InputNumber value="-1" max={1000} style={{width:"350px"}}/>,false,false,
|
||||
"当输入栏为空时,默认数量无限制"
|
||||
)}
|
||||
<p>选择头像:</p>
|
||||
<UploadImage url={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} getImage={getImage}/>
|
||||
<p className="font-15 mb10">选择头像:</p>
|
||||
{/* <UploadImage url={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} getImage={getImage}/> */}
|
||||
<div className="plusCard mb20" onClick={()=>{setIamgeVisible(true)}}>
|
||||
{
|
||||
image ?
|
||||
<img src={image&&image.startsWith('images/avatars/Organization')?getImageUrl(`/${image}`):image} alt="avatar" style={{ width: '100%' }} />
|
||||
:
|
||||
<React.Fragment>
|
||||
<Icon type={'plus'} />
|
||||
<div className="ant-upload-text">点击上传</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
<Button type={"primary"} onClick={updateDetail}>更新组织设置</Button>
|
||||
</Form>
|
||||
</Div>
|
||||
|
|
|
|||
|
|
@ -55,28 +55,28 @@ function Detail(props){
|
|||
|
||||
useEffect(()=>{
|
||||
if(OIdentifier){
|
||||
getDetail(OIdentifier);
|
||||
getDetail();
|
||||
}
|
||||
},[OIdentifier]);
|
||||
|
||||
function getDetail(id) {
|
||||
const url = `/organizations/${id}.json`;
|
||||
function getDetail() {
|
||||
const url = `/organizations/${OIdentifier}.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result && result.data){
|
||||
setDetail(result.data);
|
||||
let keyWords=`${result.data.nickname},${id},`;
|
||||
let title= result.data.nickname+'('+ id +') ' +result.data.description;
|
||||
setSeoMeta(keyWords,title,title,`/${id}`,id);
|
||||
let keyWords=`${result.data.nickname},${OIdentifier},`;
|
||||
let title= result.data.nickname+'('+ OIdentifier +') ' +result.data.description;
|
||||
setSeoMeta(keyWords,title,title,`/${OIdentifier}`,OIdentifier);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function updateDetail(name,desc){
|
||||
let d = detail;
|
||||
d.name = name;
|
||||
d.description = desc;
|
||||
setDetail(d);
|
||||
}
|
||||
// function updateDetail(name,desc){
|
||||
// let d = detail;
|
||||
// d.name = name;
|
||||
// d.description = desc;
|
||||
// setDetail(d);
|
||||
// }
|
||||
return(
|
||||
<div className="teamDetail">
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ function Detail(props){
|
|||
<Route
|
||||
path="/:OIdentifier/setting"
|
||||
render={(p) => {
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={updateDetail}/>
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={getDetail}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -18,7 +18,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
let wikiName = ''
|
||||
let key = '';
|
||||
if (!pathname.endsWith('/wiki/add')) {
|
||||
wikiName = pathname.split('/')[4];
|
||||
wikiName = decodeURI(pathname.split('/')[4]);
|
||||
key = pathname.split('/')[5];
|
||||
}else{
|
||||
key = search.split('=').pop();
|
||||
|
|
@ -116,6 +116,12 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
};
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(values.title)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
setOperateFlag(false);
|
||||
return;
|
||||
}
|
||||
const {md_content, title} = values;
|
||||
if (wikiName && search!== "?copy") {
|
||||
updateWiki({
|
||||
|
|
@ -124,7 +130,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: wikiName,
|
||||
title,
|
||||
message: '',
|
||||
commit_message: '',
|
||||
content_base64: Base64.encode(md_content)
|
||||
}).then(res => dealRes(res, title));
|
||||
} else {
|
||||
|
|
@ -217,7 +223,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
message: '',
|
||||
commit_message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -327,7 +333,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
"title",
|
||||
[
|
||||
{ required: true, message: "请输入标题" },
|
||||
{ pattern: /^(?!-).*$/, message: '不能以-开头' }
|
||||
// { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '不允许部分特殊字符' }
|
||||
],
|
||||
<Input
|
||||
placeholder={"请输入标题"}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ export default (props) => {
|
|||
project && checkItem.name && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.sub_url,
|
||||
pageName: checkItem.name,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -190,6 +190,11 @@ export default (props) => {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError("不能有特殊字符: \\ / : * ? \" < > | [ \] -");
|
||||
return;
|
||||
}
|
||||
// 校验一级目录中是否有相同名称
|
||||
const oneMenuList = fileList.filter(item=>!item.title.trim().startsWith('[[')).map(i=>i.title.trim())
|
||||
if(oneMenuList.includes(`- ${menuName}`)){
|
||||
|
|
@ -210,7 +215,7 @@ export default (props) => {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
message: '',
|
||||
commit_message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -228,7 +233,7 @@ export default (props) => {
|
|||
}
|
||||
|
||||
function goEdit(params) {
|
||||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.sub_url)}/${checkItem.key}/edit${params}`);
|
||||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.name)}/${checkItem.key}/edit${params}`);
|
||||
}
|
||||
|
||||
function preview() {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export default (props) => {
|
|||
projectsId && checkItem.name && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.sub_url,
|
||||
pageName: checkItem.name,
|
||||
projectId: projectId,
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
|
|||
|
|
@ -116,16 +116,13 @@ export function markdownToTree(markdownText){
|
|||
lines.map((item, index) =>{
|
||||
const title = item.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
const titleStr = isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length)
|
||||
const node = {
|
||||
// 带空格+[[]]或者- 标识
|
||||
title: item,
|
||||
children: [],
|
||||
key: undefined,
|
||||
// 纯内容
|
||||
titleStr,
|
||||
// 编码后的title,获取wiki内容用title_sub
|
||||
title_sub: encodeURIComponent(titleStr),
|
||||
titleStr: isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length),
|
||||
// 是否是wiki文件
|
||||
isFile: isFile
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export default function Sidebar(props) {
|
|||
const {node, children, key} = item;
|
||||
if(isFile){
|
||||
// 删除页面
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: item.title_sub}).then(res => {
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: title}).then(res => {
|
||||
if(res && res.message === "204"){
|
||||
// 递归过滤相同key值的节点,执行删除操作
|
||||
const menuListByDel = findSameKeyByDel(menuList, key);
|
||||
|
|
@ -267,7 +267,7 @@ export default function Sidebar(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
message: '',
|
||||
commit_message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -303,18 +303,20 @@ export default function Sidebar(props) {
|
|||
e.stopPropagation();
|
||||
setVisible(item);
|
||||
setIsEditName(type);
|
||||
const {titleStr, title_sub} = item;
|
||||
let title = item.title.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
title = isFile ? title.substring(2,title.length-2) : title.substring(2, title.length);
|
||||
type === 2 && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: title_sub,
|
||||
pageName: title,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
setWikiContent(res.data.md_content);
|
||||
}
|
||||
})
|
||||
setMenuName(titleStr);
|
||||
setMenuName(title);
|
||||
}
|
||||
|
||||
// 新增子目录 或者 重命名目录
|
||||
|
|
@ -327,8 +329,9 @@ export default function Sidebar(props) {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
if (isEditName === 2 && /^-/.test(menuName)) {
|
||||
setAddMenuError('不能以-开头');
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError('不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
return;
|
||||
}
|
||||
if(!isEditName){
|
||||
|
|
@ -353,15 +356,14 @@ export default function Sidebar(props) {
|
|||
}else{
|
||||
// isEditName 1 编辑目录名称 2编辑页面名称
|
||||
const titleToJudge = isEditName === 2 ? `[[${menuName}]]` : `- ${menuName}`;
|
||||
const {key, titleStr, title_sub} = visible;
|
||||
// 判断是否有修改名称
|
||||
if(titleStr === menuName){
|
||||
const {title, key} = visible;
|
||||
if(title.trim() === titleToJudge){
|
||||
setAddMenuError("请修改名称");
|
||||
return
|
||||
}
|
||||
// 找兄弟节点
|
||||
const list = findBrotherNodesByKey(menuList, key) || [];
|
||||
if(list.map(item=>item.titleStr).includes(menuName)){
|
||||
if(list.map(item=>item.title.trim()).includes(titleToJudge)){
|
||||
setAddMenuError("不能与同级目录名称相同");
|
||||
return
|
||||
}
|
||||
|
|
@ -379,16 +381,17 @@ export default function Sidebar(props) {
|
|||
})
|
||||
if(isEditName === 2){
|
||||
// 编辑页面名称-> 修改wiki
|
||||
const oldTitle = title.substring(title.indexOf('[[')+2, title.indexOf(']]'))
|
||||
updateWiki({
|
||||
owner,
|
||||
repo: projectsId,
|
||||
projectId: project.id,
|
||||
// 原名称
|
||||
pageName: title_sub,
|
||||
pageName: oldTitle,
|
||||
// 现名称
|
||||
title: menuName,
|
||||
content_base64: wikiContent,
|
||||
message: '',
|
||||
commit_message: '',
|
||||
}).then(res=>{
|
||||
if(res && res.message === '200'){
|
||||
// 修改wiki名称接口请求成功,更新sidebar
|
||||
|
|
|
|||
|
|
@ -59,8 +59,10 @@ export default function UploadWiki(props) {
|
|||
message.error('只能上传md、txt文件');
|
||||
return false;
|
||||
}
|
||||
if (/^-/.test(file.name)) {
|
||||
message.error('文件名不能以-开头');
|
||||
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(file.name)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +86,7 @@ export default function UploadWiki(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
message: '',
|
||||
commit_message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ import Cropper from 'react-cropper';
|
|||
import 'cropperjs/dist/cropper.css';
|
||||
import axios from 'axios';
|
||||
|
||||
function Index({onCancel,avatarImg,login}){
|
||||
console.log('avatarImg,login', avatarImg,login);
|
||||
|
||||
function Index({onCancel,avatarImg,login,saveFunc}){
|
||||
const [ avatarPhoto , setAvatarPhoto ] = useState(avatarImg);
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
@ -23,15 +21,19 @@ function Index({onCancel,avatarImg,login}){
|
|||
if (!imgUrl) {
|
||||
message.info('请先上传图片');
|
||||
}
|
||||
const url = `/users/${login}/update_image.json`;
|
||||
axios.put(url,{
|
||||
image:imgUrl
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
message.success("头像修改成功!");
|
||||
onCancel(true);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
if(login){
|
||||
const url = `/users/${login}/update_image.json`;
|
||||
axios.put(url,{
|
||||
image:imgUrl
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
message.success("头像修改成功!");
|
||||
onCancel(true);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}else{
|
||||
saveFunc && saveFunc(imgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
function onChange(e){
|
||||
|
|
@ -73,30 +75,35 @@ function Index({onCancel,avatarImg,login}){
|
|||
footer={null}
|
||||
centered
|
||||
maskClosable={false}
|
||||
title="修改头像"
|
||||
title={`${login ? "修改": "上传组织" }头像`}
|
||||
onCancel={()=>onCancel(false)}
|
||||
className="avatarBox"
|
||||
>
|
||||
<div className="avatarDiv">
|
||||
<div>
|
||||
<Cropper
|
||||
style={{ height: 320, width: 320 }}
|
||||
src={avatarPhoto}
|
||||
guides={false}
|
||||
preview="#updateAvatarImg"
|
||||
ref={cropper}
|
||||
aspectRatio={1}
|
||||
/>
|
||||
{/* <span className={"tips"}>仅支持JPG、GIF、PNG,且文件小于2M</span> */}
|
||||
</div>
|
||||
{
|
||||
avatarPhoto ?
|
||||
<div>
|
||||
<Cropper
|
||||
style={{ height: 320, width: 320 }}
|
||||
src={avatarPhoto}
|
||||
guides={false}
|
||||
preview="#updateAvatarImg"
|
||||
ref={cropper}
|
||||
aspectRatio={1}
|
||||
/>
|
||||
{/* <span className={"tips"}>仅支持JPG、GIF、PNG,且文件小于2M</span> */}
|
||||
</div>
|
||||
:
|
||||
<div className="font-18 tipsPosi">选择本地照片,上传编辑{!login && "组织"}头像</div>
|
||||
}
|
||||
<div className="previewBox">
|
||||
<div className={"previewImg"} id="updateAvatarImg"></div>
|
||||
<div className={`previewImg ${login ? "ring":""}`} id="updateAvatarImg"></div>
|
||||
<div className="uploadBtn">
|
||||
<label className={"uploadButton"} id="uploadBtn" htmlFor="inputImage">
|
||||
<input type="file" className="sr-only" id="inputImage" name="file" accept="image/*" style={{ display: "none" }} onChange={onChange}></input>
|
||||
点击上传
|
||||
</label>
|
||||
<a onClick={saveAvatar}>保存头像</a>
|
||||
{(login || (avatarPhoto && !login)) && <a onClick={saveAvatar}>{login ? "保存头像":"确定"}</a> }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,22 @@
|
|||
}
|
||||
.avatarDiv{
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 320px;
|
||||
.tipsPosi{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
top:40%;
|
||||
height: 30px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
.previewBox{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-left: 30px;
|
||||
margin-left: auto;
|
||||
.uploadBtn{
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
|
|
@ -57,10 +67,12 @@
|
|||
.previewImg{
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
width: 100px!important;
|
||||
height: 100px!important;
|
||||
&.ring{
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -90,6 +90,26 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
}
|
||||
|
||||
function Init(data,max,flag) {
|
||||
let piecesList = [];
|
||||
let number = 1;
|
||||
if(max>500){
|
||||
number = 6;
|
||||
}else if(max<=500 && max>200){
|
||||
number = 5;
|
||||
}else if(max<=200 && max>100){
|
||||
number = 4;
|
||||
}else if(max<=100 && max>=30){
|
||||
number = 3;
|
||||
}else if(max<30 && max>=10){
|
||||
number = 2;
|
||||
}else{
|
||||
number = 1;
|
||||
}
|
||||
for(var i=number;i>0;i--){
|
||||
let gt = {gt: parseInt(max/number*(i-1)+1,0), lte: parseInt(max/number*i,0)};
|
||||
piecesList.push(gt);
|
||||
}
|
||||
|
||||
var huan_val = document.getElementById("Calendar");
|
||||
var myEcharts = echarts.init(huan_val);
|
||||
let option = {
|
||||
|
|
@ -111,7 +131,17 @@ function Calendar({ userLogin , time , chooseTime }) {
|
|||
inRange:{
|
||||
color:flag ? ['#fafafa', '#216e39'] :['#fff','#fff']
|
||||
},
|
||||
show:flag
|
||||
show:flag,
|
||||
pieces: [
|
||||
// {gt: parseInt(max/5*4,0), lte: max},
|
||||
// {gt: parseInt(max/5*3,0), lte: parseInt(max/5*4,0)},
|
||||
// {gt: parseInt(max/5*2,0), lte: parseInt(max/5*3,0)},
|
||||
// {gt: parseInt(max/5*1,0), lte: parseInt(max/5*2,0)},
|
||||
// {gt: 1, lte: parseInt(max/5*1,0)},
|
||||
...piecesList,
|
||||
{max: 1,label:"0"}
|
||||
],
|
||||
itemGap:25
|
||||
},
|
||||
calendar: {
|
||||
top: 50,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import SupplyPhoneModal from '../../forge/Component/ProfileModal/SupplyPhone';
|
|||
import SystemNotice from '../../forge/Component/NoticeModal/SystemNotice';
|
||||
import cookie from 'react-cookies';
|
||||
import NpsModal from '../modals/npsModal';
|
||||
import { IsPC } from 'educoder';
|
||||
import { isPhone } from 'educoder';
|
||||
|
||||
export function TPMIndexHOC(WrappedComponent) {
|
||||
return class II extends React.Component {
|
||||
|
|
@ -287,7 +287,7 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
showNpsModal: this.showNpsModal
|
||||
};
|
||||
let path =this.props.location.pathname;
|
||||
let pathCheck = path.indexOf("/zone")>-1 && path.indexOf("/newdetail")>-1 && IsPC();
|
||||
let pathCheck = path.indexOf("/zone")>-1 && path.indexOf("/newdetail")>-1 && isPhone();
|
||||
return (
|
||||
<div className="indexHOC">
|
||||
<SystemNotice
|
||||
|
|
|
|||
Loading…
Reference in New Issue