Compare commits

...

84 Commits

Author SHA1 Message Date
jasder 01dff209d4 Merge pull request '工程认证弹框等特殊定制' (#247) from caishi/forgeplus-react:dev_educoder into dev_educoder 2021-11-08 14:29:33 +08:00
caishi d1effecd13 hostname 2021-11-05 18:41:31 +08:00
caishi c801666b62 工程认证弹框 2021-11-05 18:17:27 +08:00
jasder 8188ceae13 Merge pull request '加载时底部信息占据整个页面' (#245) from caishi/forgeplus-react:dev_educoder into dev_educoder 2021-11-03 18:46:23 +08:00
caishi bd7e1b2742 整体页面设置最低高度 2021-11-02 14:56:53 +08:00
jasder 7dda7fdf08 Merge pull request '个人中心-merge代码冲突问题' (#225) from caishi/forgeplus-react:dev_educoder into dev_educoder 2021-10-25 09:32:29 +08:00
caishi 64f946d51c 个人主页左侧去掉多余的点击选项 2021-10-25 09:26:46 +08:00
jasder a3cc73127d Merge pull request '分支页面-空数据无提示' (#223) from caishi/forgeplus-react:dev_educoder into dev_educoder 2021-10-23 17:08:03 +08:00
caishi 63a79c4296 分支无数据提示 2021-10-23 17:00:06 +08:00
jasder 999ff9eb7f Merge pull request '合并forge现有功能-educoder forge' (#222) from caishi/forgeplus-react:dev_educoder into dev_educoder 2021-10-23 16:10:50 +08:00
caishi bbca3d51e1 头部通知-跳转 2021-10-23 15:56:45 +08:00
caishi 9ae3c0e786 Merge branch 'pre_develop_dev' into dev_educoder
# Conflicts:
#	public/css/iconfont.js
#	src/AppConfig.js
#	src/forge/Head/Footer.jsx
#	src/forge/Head/Header.js
#	src/forge/Head/header.scss
#	src/forge/Main/CoderDepot.jsx
#	src/forge/Main/CoderRootCommit.js
#	src/forge/Main/sub/DetailBanner.jsx
#	src/forge/New/Index.js
#	src/forge/Source/Index.jsx
#	src/modules/tpm/TPMIndexHOC.js
2021-10-23 15:41:21 +08:00
caishi 3158953571 update 2021-09-08 17:47:40 +08:00
caishi 5eb542cfbf 同步账号密码 2021-09-08 16:50:16 +08:00
caishi 146e51c182 列表头部 2021-09-08 14:57:16 +08:00
caishi 58691ec2ea style 2021-09-08 14:23:01 +08:00
caishi 2f5d9d225c 路由 2021-09-08 11:29:55 +08:00
caishi d88179a486 转移项目-状态变化 2021-09-06 15:32:59 +08:00
caishi 58613bf4c1 merge 报错 2021-09-06 14:41:53 +08:00
caishi be379d39e3 merge-pre_develop_dev 2021-09-06 14:21:43 +08:00
caishi 3f918b53d9 merge 转移仓库完成 2021-09-06 11:36:15 +08:00
caishi c4bc8fc9c5 merge 93a53e2c7f 2021-09-06 11:36:15 +08:00
caishi a1b82d833b merge 4e48b0b363 2021-09-06 11:36:15 +08:00
caishi 350769d3d7 搜索用户 2021-09-06 11:35:32 +08:00
caishi af31c381f9 merge 09065383c1 2021-09-06 11:35:32 +08:00
caishi e7f997d3f6 hide 2021-09-06 11:34:44 +08:00
caishi a968287331 项目列表头部button需要更新样式 2021-09-06 11:33:55 +08:00
何童崇 7dd59f7711 merge 52e08e77e5 2021-09-06 11:33:01 +08:00
何童崇 c3b43bb5c7 merge ff75065a0a 2021-09-06 11:32:43 +08:00
caishi 159bc0c893 新建项目跳转地址login 2021-09-06 11:22:21 +08:00
caishi ca84851f0b banner 2021-09-06 11:22:21 +08:00
caishi 4dc0f974df 列表页:描述内容样式 2021-09-06 11:22:21 +08:00
caishi 5b60d92063 /默认跳转地址 2021-09-06 11:21:25 +08:00
caishi f2be69f4e3 新建:拥有者默认选中当前登录用户,默认路由 2021-09-06 11:19:53 +08:00
caishi aa93eade71 同上 update 2021-09-06 11:19:03 +08:00
caishi 02b48e8648 项目列表:banner部分样式版本更新 2021-09-06 11:17:58 +08:00
caishi f50c550816 update issue 2021-09-06 11:17:34 +08:00
caishi 16397c8743 头部的nav字符串内容中有标签要渲染 2021-09-06 11:15:36 +08:00
caishi 5ef79007e2 current fix update 2021-09-06 11:15:21 +08:00
caishi e3321fd676 项目邀请码-第一版测试版上线 2021-09-06 11:14:53 +08:00
caishi 80c559895a bug 2021-09-06 11:12:44 +08:00
caishi e804698d70 修改资料+密码管理 2021-09-06 11:12:19 +08:00
caishi dd20d02477 同上=issue修改 2021-09-06 11:11:20 +08:00
caishi 28d3b5bedd git cherry-pick 1432afebfd 2021-09-06 11:10:05 +08:00
caishi e1b73f582a git cherry-pick a9285f37e7 2021-09-06 11:08:28 +08:00
caishi f94edf90a5 git cherry-pick d41dce26b1 2021-09-06 11:07:55 +08:00
caishi c9a9da6de9 git cherry-pick 975d49 2021-09-06 11:07:55 +08:00
caishi 7d0abfb764 cherry-pick develop 个人中心第一版 2021-09-06 11:05:28 +08:00
caishi f25db9ccf1 eudocderforge头像url 2021-09-06 10:57:31 +08:00
caishi 2d79d144a0 邮箱弹框点击事件 2021-09-06 10:57:31 +08:00
caishi a209b29100 2021-05-28同步develop分支 2021-09-06 10:57:17 +08:00
caishi 7666efe1df git merge a1bd41795a 2021-09-06 10:56:04 +08:00
caishi a14eddda52 git merge 70af7dae5f 2021-09-06 10:54:57 +08:00
caishi c54433728b merge d029840874 2021-09-06 10:43:44 +08:00
caishi ee994458a9 导航-字体颜色 2021-09-06 10:42:09 +08:00
caishi ea57432cb4 merge 2021-09-06 10:40:02 +08:00
caishi 831ff66ebe merge develop 2021-09-06 10:34:54 +08:00
caishi bc0d60fea9 imageurl接口统一返回带iamges的字段 2021-09-06 10:32:48 +08:00
caishi 53c92383d2 去掉右侧悬浮手册按钮 2021-09-06 10:27:56 +08:00
caishi 7697449f05 账号同步框提示文字错误 2021-09-06 10:27:14 +08:00
caishi 2e66904f81 合并资源库 2021-09-06 10:27:14 +08:00
caishi 21f7a2530a 冲突 2021-09-06 10:26:44 +08:00
caishi d76416bf1a 构建列表 2021-09-06 10:25:57 +08:00
caishi a05d06bc1f tips(易修、复刻) 2021-09-06 10:25:16 +08:00
caishi 5f7eaa24c6 通知、消息的地址,trustie改为educoder 2021-09-06 10:24:09 +08:00
caishi e4e419beb2 冲突 2021-09-06 10:20:37 +08:00
caishi 14a68f9241 color 2021-09-06 10:20:17 +08:00
caishi dd0a9e50e5 合并 2021-09-06 10:20:17 +08:00
caishi 3148397343 头部 active 2021-09-06 10:15:53 +08:00
caishi 7f7a1021df toubu 2021-09-06 10:15:53 +08:00
caishi 882d8aef75 代码冲突 2021-09-06 10:15:22 +08:00
caishi 987688bcc9 新建项目 2021-09-06 10:14:34 +08:00
caishi 3bebbdc44d readme 2021-09-06 10:13:51 +08:00
caishi 7b4723b111 header 2021-09-06 10:13:24 +08:00
caishi 3a8d9698db condition 2021-09-06 10:12:59 +08:00
caishi 6b441fc919 delete 2021-09-06 10:12:12 +08:00
caishi b1725a00ee style 2021-09-06 10:11:26 +08:00
caishi 0294439f18 未登录不弹框 2021-09-06 10:11:26 +08:00
caishi e7acb2f142 导航栏和底部 2021-09-06 10:11:26 +08:00
caishi 21ab03f3da update 2021-09-06 10:07:35 +08:00
caishi 102b21f255 隐藏操作手册 2021-09-06 10:07:34 +08:00
caishi 76ed232f6a educoder和forge用户的密码是否一致 2021-09-06 10:06:31 +08:00
caishi f14443a6e8 弹框修改接口 2021-09-06 10:05:33 +08:00
caishi 146d4c9baa 邮箱绑定 2021-09-06 10:05:33 +08:00
46 changed files with 729 additions and 477 deletions

2
package-lock.json generated
View File

@ -14204,7 +14204,7 @@
},
"qr.js": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
"resolved": "https://registry.npm.taobao.org/qr.js/download/qr.js-0.0.0.tgz",
"integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8="
},
"qrcode.react": {

View File

@ -25,9 +25,6 @@ html {
min-width: 1200px
}
.newFooter {
max-height: 110px;
}
.newFooter {
position: absolute;

View File

@ -3604,7 +3604,6 @@ a.user_bluebg_btn {
margin-right: 5px;
}
/***** loading ******/
/*****载入中******/
#ajax-indicator {
@ -3971,7 +3970,7 @@ html>body #ajax-indicator {
display: block;
height: 100%;
width: 100%;
color: #333;
color: #fff;
font-size: 16px;
}

View File

@ -84,7 +84,7 @@ const EducoderLogin = Loadable({
loading: Loading,
})
const Search = Loadable({
loader: () => import('./modules/search/'),
loader: () => import('./search/SearchPage'),
loading: Loading,
})
const WikiPreview = Loadable({
@ -92,6 +92,7 @@ const WikiPreview = Loadable({
loading: Loading,
})
const ProjectIndex = Loadable({
loader: () => import("./forge/Index"),
loading: Loading,
@ -178,7 +179,6 @@ class App extends Component {
componentDidMount() {
document.title = "loading...";
this.getAppdata();
window.addEventListener('error', (event) => {

View File

@ -11,9 +11,9 @@ broadcastChannelOnmessage('refreshPage', () => {
})
function locationurl(list) {
if (window.location.port !== "3007") {
// if (window.location.port !== "3007") {
window.location.href = list
}
// }
}
// TODO 开发期多个身份切换
let debugType = ""
@ -32,7 +32,7 @@ export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
var proxy = "https://testforgeplus.trustie.net";
var proxy = "https://testforgeplus.educoder.net";
//响应前的设置
axios.interceptors.request.use(
config => {
@ -86,7 +86,7 @@ export function initAxiosInterceptors(props) {
if (response.data.status === 404) {
let responseURL = response.request ? response.request.responseURL:'';
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
if (responseURL.indexOf('/api/users/') === -1 || responseURL.indexOf('/api/organizations/') === -1 || responseURL.indexOf('/api/owners/') === -1) {
locationurl('/nopage');
}
}

View File

@ -8,16 +8,34 @@ const isDev = window.location.port == 3007;
const isdev2= window.location.hostname ==='www.educoder.net'
export const TEST_HOST = "https://testforgeplus.trustie.net/"
export function getImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net';
if (isDev) {
return `${local}/${path}`
const local = 'https://testforgeplus.educoder.net';
const normal = 'https://ali-cdn.educoder.net/images';
const normalend = 'https://ali-cdn.educoder.net';
if(path.substr(0, 7) !== "/system"){
if (isDev) {
return `${local}/${path}`
}
if(path.substr(0, 7) !== "/images"){
return `${normal}${path}`;
}else{
return `${normalend}${path}`;
}
}
return `${path}`;
}
export function openNewWindow(url) {
let link = document.createElement('a')
link.target = "_blank"
document.body.appendChild(link)
link.href = url
let evt = document.createEvent("MouseEvents")
evt.initEvent("click", false, false)
link.dispatchEvent(evt)
document.body.removeChild(link);
}
export function numFormat(num, digits){
let d = digits || 1;
var si = [
@ -179,7 +197,7 @@ export function getmyUrl(geturl) {
}
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
return `${getUrl()}/api/attachments.json`;
}
export function getUploadLogoActionUrl() {

View File

@ -7,6 +7,7 @@ export {
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, 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
, openNewWindow as openNewWindow
} from './UrlTool';
export { setmiyah as setmiyah } from './Component';

View File

@ -3,4 +3,9 @@
}
.ant-modal-wrap{
z-index: 1032;
}
.ant-modal-wrap{
.ant-form-explain{
position: absolute;
}
}

View File

@ -1,15 +1,32 @@
import React , {forwardRef, useEffect} from 'react';
import { Modal , Form , Input , Button } from 'antd';
import './EAccount.scss';
import axios from 'axios';
function EducoderAccount({form , visible , onOk , email}){
function EducoderAccount({form , visible , current_user , onCancel}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{
if(email){
setFieldsValue({email})
if(current_user && current_user.email){
setFieldsValue({email:current_user.email})
}
},[email])
},[current_user])
function onOk(values){
let url = `/accounts/gitea_register.json`;
const { email , is_sync_pwd} = current_user;
if(email && !is_sync_pwd){
url = `/users/change_password.json`;
}
axios.post(url,{
login:current_user && current_user.login,
...values
}).then(result=>{
if(result && result.data && result.data.status === 0){
window.location.reload();
}
}).catch(error=>{})
}
function onSure(){
validateFields((error,values)=>{
@ -27,7 +44,7 @@ function EducoderAccount({form , visible , onOk , email}){
visible={visible}
title="提示"
width="500px"
closable={false}
onCancel={onCancel}
footer={
<Button type="primary" onClick={onSure}>确定</Button>
}
@ -35,21 +52,26 @@ function EducoderAccount({form , visible , onOk , email}){
>
<div>
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
为确保您能正常使用平台功能请确认以下信息:
{
current_user && current_user.email ?
`平台已检测到您已绑定邮箱${current_user.email},请您确认如下操作`
:
"平台已检测到您未绑定邮箱,为不影响使用协同开发功能,请先绑定邮箱"
}
</p>
<Form {...layout}>
<Form.Item label="邮箱">
{getFieldDecorator("email",{
rules:[{required:true,message:"请输入邮箱账号"}]
})(
<Input placeholder="请输入您的邮箱账号" width="220px"/>
<Input placeholder="请输入您的邮箱账号" width="220px" disabled={current_user && current_user.email}/>
)}
</Form.Item>
<Form.Item label="密码">
{getFieldDecorator("password",{
rules:[{required:true,message:"请输入邮箱密码"}]
rules:[{required:true,message:"请输入您的平台密码"}]
})(
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
<Input.Password placeholder="请输入您的平台密码" width="220px"/>
)}
</Form.Item>
</Form>

View File

@ -1,17 +1,36 @@
import React from 'react';
import { useState } from 'react';
import EducoderAccount from '../EducoderAccount';
function Profile({children,sureFunc,showCompeleteDialog , completeProfile, className}) {
function Profile({
children,
sureFunc,
showCompeleteDialog ,
completeProfile,
className ,
current_user
}) {
const [ giteaVisible , setGiteaVisible ] = useState(false);
function checkProfile() {
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
sureFunc();
if(current_user && current_user.login){
if(!current_user.has_gitea_user || (current_user.has_gitea_user && !current_user.is_sync_pwd)){
setGiteaVisible(true);
}else{
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
sureFunc();
}
}
}
}
return(
<a className={className} onClick={checkProfile}>{children}</a>
<React.Fragment>
<EducoderAccount visible={giteaVisible} onCancel={()=>setGiteaVisible(false)} current_user={current_user}/>
<a className={className} onClick={checkProfile}>{children}</a>
</React.Fragment>
)
}
export default Profile;

View File

@ -12,7 +12,7 @@ function ServiceModal({sureModal}){
<div className="mt30" style={{textAlign:"center"}}>
<Radio.Group value={type} onChange={changeType}>
<Radio value={1}>自有服务器</Radio>
<Radio value={2}>Trustie服务器</Radio>
<Radio value={2}>EduCoder服务器</Radio>
</Radio.Group>
<p className="mt30"><Button type="primary" onClick={()=>sureModal(type)}>下一步</Button></p>
</div>

View File

@ -20,13 +20,6 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
if(owner && repo && visible===true){
getTeam();
}
if(!visible){
setFieldsValue({
owner_name:undefined,
identifier:undefined
})
setValue(undefined)
}
},[repo,owner,visible])
function getTeam(){
@ -127,7 +120,6 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
{getFieldDecorator("owner_name",{
rules:[{required:true,message:"请输入目标用户名"}]
})(
// <Input placeholder="" autoComplete={"off"}/>
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户" value={value}/>
)}
</Form.Item>
@ -153,11 +145,11 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
</Form.Item>
}
<Form.Item label="仓库标识:" style={{marginBottom:"0px"}}>
<Form.Item label="仓库标识:">
{getFieldDecorator("identifier",
{
rules:[
{required:true,message:"请输入仓库标识"},
{required:true,message:"请输入仓库标识"},
{
validator:checkIdentifier
}

View File

@ -0,0 +1,30 @@
import React from 'react';
import { Modal } from 'antd';
import { openNewWindow } from 'educoder';
function Engineer({QQVisible,setQQVisible}) {
return(
<Modal
centered
destroyOnClose={true}
visible={QQVisible}
title="提示"
width="500px"
// footer={null}ee
okText="立即联系"
cancelText="取消"
onOk={() => {
openNewWindow("https://qm.qq.com/cgi-bin/qm/qr?k=DWdqQHAbbfw7_rqm0d-Q_vDn5H6bMp91&jump_from=webapi")
}}
onCancel={() => setQQVisible(false)}
>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<p>您可以在QQ服务群向管理员申请获得继续操作的权限</p >
< img src={require("./teacherQQ.png")} width={200} height={200} alt=""/>
<p>群号693542422 </p >
</div>
</Modal >
)
}
export default Engineer

View File

@ -19,7 +19,7 @@ function Footer(){
return(
<div>
<div style={{height:"543px"}}></div>
<div style={{height:"810px"}}></div>
<div className="newFooter edu-txt-center">
{value && showhtml(value)}
{/* <div className="footerInfos">

View File

@ -1,9 +1,8 @@
import React, { Component } from 'react';
import AccountProfile from "../../modules/user/AccountProfile";
import { getImageUrl } from 'educoder'
import { getImageUrl , openNewWindow } from 'educoder';
import axios from 'axios';
import { Input , notification , Dropdown ,Popover, Menu,Badge, Button } from 'antd';
import { Link } from 'react-router-dom';
import { Input , notification , Dropdown , Menu } from 'antd';
import LoginDialog from '../../modules/login/LoginDialog';
import HeadSearch from '../Component/HeadSearch';
@ -13,13 +12,14 @@ import '../../modules/tpm/TPMIndex.css';
import CheckProfile from '../Component/ProfileModal/Profile';
import './header.scss';
import NoticeContent from './NoticeContent';
import Engineer from './Engineer';
const $ = window.$
// TODO 这部分脚本从公共脚本中直接调用
const { Search } = Input;
let old_url;
window._header_componentHandler = null;
const isPath= window.location.hostname ==='code.educoder.net' || window.location.hostname==='testforgeplus.educoder.net';
// 非trustie链接则新开页跳转
const str = ['www.trustie.net','forgeplus.trustie.net','forum.trustie.net','testforgeplus.trustie.net']
class NewHeader extends Component {
@ -49,6 +49,7 @@ class NewHeader extends Component {
visiblemyss: false,
openSearch:false,
visible:false, //浮动消息框展示控制
QQVisible:false
}
}
componentDidMount() {
@ -82,6 +83,36 @@ class NewHeader extends Component {
} catch (e) {}
}
SearchInput = (open,item)=>{
if(open){
return(
<div
onBlur={() => {
setTimeout(() => {
this.setState({
openSearch:false
})
}, 300)
}}
>
<Search placeholder="实践课程/教学课堂/实践项目/交流问答"
className={`search-input mr20`}
onSearch={(value)=>this.onGlobalSearch(value,item)}
autoFocus={true}
/>
</div>
)
}else{
return <i className="iconfont icon-sousuo font-18 color-white ml30" onClick={() => {
this.setState({openSearch:true})
}} />
}
}
onGlobalSearch=(value,item)=>{
window.location.href=`${item}?value=` + value;
}
openNotification = (messge) => {
notification.open({
message: "提示",
@ -96,6 +127,26 @@ class NewHeader extends Component {
})
}
submitsubmitapplications = () => {
let {
submitapplicationssum,
submitapplicationsvaluedata
} = this.state;
this.setState({
submitapplications: false,
RadioGroupvalue: undefined
})
if (submitapplicationssum === 0) {
if (submitapplicationsvaluedata !== undefined) {
window.location.href = "/courses/" + submitapplicationsvaluedata;
}
} else if (submitapplicationssum === 1) {
if (submitapplicationsvaluedata !== undefined) {
window.location.href = "/projects/" + submitapplicationsvaluedata;
}
}
}
educoderlogin = () => {
//登录账号
this.setState({
@ -132,6 +183,24 @@ class NewHeader extends Component {
})
};
hidetojoinclass = () => {
this.setState({
tojoinclasstype: false,
tojoinitemtype: false,
tojoinclasstitle: undefined,
rolearr: ["", ""],
Checkboxteacherchecked: false,
Checkboxstudentchecked: false,
Checkboxteachingchecked: false,
Checkboxteachertype: false,
Checkboxteachingtype: false,
code_notice: false,
checked_notice: false,
RadioGroupvalue: undefined
})
}
// 关闭
cancelModulationModels = () => {
this.setState({ isRenders: false })
@ -278,10 +347,32 @@ class NewHeader extends Component {
this.setState({ visible });
};
turntoEngineer=(url)=>{
const { current_user } = this.props;
if(current_user && current_user.login){
if(url){
window.location.href=url;
}else{
this.setState({
QQVisible:true
})
}
}else{
this.educoderlogin();
}
}
setQQVisible=()=>{
this.setState({
QQVisible:false
})
}
render() {
const { match ,resetUserInfo ,showNotification} = this.props;
const { match } = this.props;
let current_user = this.props.user;
let {
QQVisible,
AccountProfiletype,
user,
isRender,
@ -369,6 +460,7 @@ class NewHeader extends Component {
let search_url = settings && settings.common && settings.common.search;
return (
<div className="newHeaders" id="nHeader">
<Engineer QQVisible={QQVisible} setQQVisible={this.setQQVisible}/>
<div className="headerContent">
{isRender === true ?
<LoginDialog
@ -418,12 +510,19 @@ class NewHeader extends Component {
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
var wl = waiLian && waiLian.length>0;
return (
<li key={key} onClick={() => this.headtypesonClick(item.link, true)} className={`${this.matchpaths(item.link) === true ? 'pr active' : 'pr'}`} style={!is_hidden ? { display: 'flex' } : { display: 'none' }}>
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
<li key={key} onClick={() => this.headtypesonClick(item.link, true)} className={`${((isPath && item.name === "大学开源") || this.matchpaths(item.link) === true) ? 'pr active' : 'pr'}`} style={!is_hidden ? { display: 'flex' } : { display: 'none' }}>
<a href={new_link} target={wl ? "_self":"_blank"}><div dangerouslySetInnerHTML={{ __html: item.name }}></div></a>
</li>
)
})
}
{
settings && settings.engineer_url !== undefined ?
<li>
<a onClick={()=>this.turntoEngineer(settings.engineer_url)}>工程认证</a>
</li>
:""
}
</ul>
: ""
}
@ -438,29 +537,20 @@ class NewHeader extends Component {
}
{ (settings && settings.common && settings.common.notice) && (current_user && current_user.login)?
<Popover
overlayClassName="notice-popover"
placement={`bottomRight`}
content={<NoticeContent visible={visible} current_user={current_user} showNotification={showNotification} resetUserInfo={resetUserInfo}/>}
visible={visible}
onVisibleChange={this.handleVisibleChange}
destroyTooltipOnHide
>
<Link to={"/settings/notice"} className="message-icon">
{current_user && <Badge count={current_user.message_unread_total}>
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
</Badge>}
</Link>
</Popover>
<a href={settings.common.notice} className="message-icon">
{current_user &&
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
}
</a>
: ""
}
</div>
{!user || (user && !user.login) ?
<span className="font-15 ml30">
<a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a>
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
{
settings && settings.common && settings.common.register &&
<span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.common.register}`} target="_blank"></a></span>
<span><em className="vertical-line"></em><a className="ml5 color-white" href={`${settings.common.register}`} target="_blank"></a></span>
}
</span>
:

View File

@ -184,11 +184,11 @@ function NoticeContent({ visible, showNotification, resetUserInfo, current_user:
className='hoverNotice-body' // className
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //ajaxfunction
// type={2} //
count={noticeUnreadList.length} //
count={noticeUnreadList && noticeUnreadList.length} //
pageSize={10} //
>
{
noticeUnreadList.map(item => {
noticeUnreadList && noticeUnreadList.length>0 && noticeUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className={`noticeCont ${item.notification_url?'pointer':''}`}>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/forge/Images/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -79,6 +79,12 @@ class Index extends Component {
<ProjectIndex {...this.props} {...props} />
)}
></Route>
<Route
path="/"
render={(props) => (
<ProjectIndex {...this.props} {...props} />
)}
></Route>
</Switch>
</div>
);

View File

@ -11,8 +11,9 @@ import ListItem from './IndexItem'
import axios from 'axios';
import img_new from '../Images/new.png';
import img_array from '../Images/array.png';
import banner from '../Images/banner_list.jpg';
import banner from '../Images/banner.png';
import CheckProfile from '../Component/ProfileModal/Profile';
import AddProjectModal from '../Head/AddProjectModal';
const Search = Input.Search;
@ -291,35 +292,33 @@ class Index extends Component {
arrows:false,
adaptiveHeight:true
}
const settings={
dots: true,
infinite: true,
speed: 500,
slidesToShow: 6,
slidesToScroll: 6,
autoplay:false,
arrows:false,
adaptiveHeight:true
}
return (
<div>
<p className="t_project_banner">
<img src={banner} width="100%" alt=""/>
</p>
{/* {
recommendOriList && recommendOriList.length>0?
<Slider {...settings} className="recommandOri">
{
recommendOriList.map((i,k)=>{
return(
<li><Link to={''}><img src={getImageUrl(`/${i.avatar_url}`)} alt={i.name} title={i.name} width="80px"/></Link></li>
)
})
}
</Slider>
:""
} */}
<div class="subjectBanner">
<img src={banner} width="100%" height="100%" alt=""/>
<div class="bannerBox">
<div class="subjectleft">
<span>头歌开源</span>
<span>
<span>
<span class="words">让大学绽放开源之花</span>
<p class="font-13" style={{color: "rgb(204, 204, 204)"}}>Powered by Trustie</p>
</span>
</span>
</div>
<CheckProfile {...this.props} sureFunc={()=>this.props.history.push("/projects/deposit/new")}>
<i class="iconfont icon-xinjianxiangmu"></i>
<a>新建项目</a>
</CheckProfile>
<a>
<i class="iconfont icon-jiaruketang1"></i>
<AddProjectModal {...this.props} showNotification={this.props.showNotification}/>
</a>
<a href="https://data.educoder.net/api/attachments/1955244?disposition=inline" target="_blank">
<i class="iconfont icon-xinshouzhiyin"></i>
</a>
</div>
</div>
{
recommendList && recommendList.length>0 &&
<Slider {...setting} className={recommendList.length>5 ? "recommandProjects":"recommandProjects mb20"}>
@ -345,7 +344,7 @@ class Index extends Component {
<div className="ProjectListIndex">
<div className="list-left">
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i></li>
<li className="MenuTitle"><i className="iconfont icson-xiangmuleixing color-grey-9 font-15 mr5"></i></li>
{typeList}
</ul>
<ul className="list-l-Menu">

View File

@ -1,10 +1,78 @@
.lineH2{line-height:2}
.t_project_banner {
/* height: 260px;
background: url(../Images/banner_list.jpg) no-repeat center; */
.subjectBanner {
height: 160px;
position: relative;
overflow: hidden;
background-color: #050d34;
}
.subjectleft{
margin-top: 40px;
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
}
.bannerBox{
width: 1200px;
position: absolute;
z-index: 2;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.subjectleft>span:first-child{
width: 140px;
height: 30px;
font-size: 30px;
font-weight: 600;
color: #fff;
line-height: 30px;
letter-spacing: 4px;
}
.subjectleft>span:last-child{
height: 16px;
font-size: 16px;
color: #fff;
line-height: 16px;
margin-left: 16px;
}
.subjectleft>span:last-child .words{
letter-spacing: 3px;
display: block;
margin-top: -6px;
margin-bottom: 2px!important;
}
.bannerBox > a{
display: inline-block;
width: 104px;
height: 30px;
line-height: 28px;
text-align: center;
border-radius: 4px;
border: 1px solid #666;
margin-right: 30px;
margin-top: 30px;
color: #fff;
cursor: pointer;
}
.bannerBox .ant-btn{
margin-top: 30px;
height: 40px;
font-size: 16px;
width: 120px;
border-radius: 4px;
margin-right: 40px;
}
.bannerBox > a > i{
font-size: 14px!important;
display: inline-block;
margin-right: 10px;
}
.bannerBox > a > a{
color: #fff!important;
}
.ProjectListIndex{
width: 1200px;
margin:20px auto;
@ -53,8 +121,9 @@
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
padding:25px 30px;
padding:0px 30px;
border-bottom: 1px solid #E0E0E0;
height: 62px;
}
.list-r-Search{
width: 400px;

View File

@ -20,7 +20,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
return(
<div className="f-wrap-between mt25">
{
menuName && projectDetail ?
menuName && menuName.length> 0 && projectDetail ?
<ul className="headerMenu-wrapper">
{
Array.isArray(menuName)&& menuName.map((item,key)=>{
@ -66,7 +66,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
</Link>
</li>:""
}
{
{/* {
item.menu_name === "wiki" &&
<li className={pathname === "wiki" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/wiki`, state }}>
@ -74,7 +74,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
<span>Wiki</span>
</Link>
</li>
}
} */}
{
item.menu_name === "devops" && platform ?
<li className={pathname==="devops" ? "active" : ""}>

View File

@ -4,6 +4,7 @@ import { truncateCommitId } from '../../common/util';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import { Dropdown , Menu , Spin } from 'antd';
import Nodata from '../../Nodata';
import './Index.scss';
import Tree from '../img/tree.png';
@ -107,6 +108,9 @@ function Index(props) {
)
})
}
{
list && list.length === 0 && <Nodata _html="暂无数据"/>
}
</div>
</Spin>
)

View File

@ -102,7 +102,7 @@ class MergeSubmit extends Component{
<span className="f-wrap-alignCenter">
<Link to={`/${item.login}`} className="show-user-link">
<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
<label className="hide-1" style={{maxWidth:"75px",'vertical-align':'middle'}}>{text}</label>
<label className="hide-1" style={{maxWidth:"75px",verticalAlign:'middle'}}>{text}</label>
</Link>
</span>
),

View File

@ -18,6 +18,7 @@ function Index(props){
const username = props.match.params.username;
const pathname = props.history.location.pathname;
const user = props.user;
const undo_messages = props.undo_messages;
const [ menu , setMenu ] = useState("undo");
const [ messagesCount , setMessagesCount ] = useState(0);

View File

@ -14,8 +14,24 @@ function Notify(props){
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
props && props.deleteEvent("notify",0);
},[])
if(username){
getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_messages.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_messages);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
useEffect(()=>{
if(username){
@ -71,6 +87,20 @@ function Notify(props){
}
}
function renderApplyStatus(status,applied) {
let { project } = applied;
if(status){
switch(status){
case 'successed':
return <p>已通过你加入<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>项目的申请</p>
default:
return <p>已拒绝你加入<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>项目的申请</p>
}
}else{
return ""
}
}
return(
<div>
<Spin spinning={isSpin}>

View File

@ -14,6 +14,7 @@ function UndoEvent(props){
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
if(username){
setIsSpin(true);
@ -93,7 +94,7 @@ function UndoEvent(props){
i.status === "canceled" && <span className="color-grey-9">对方已取消转移</span>
}
{
i.status === "accepted" && <span className="color-grey-9">已接受</span>
i.status === "accept" && <span className="color-grey-9">已接受</span>
}
{
i.status === "refused" && <span className="color-grey-9">已拒绝</span>

View File

@ -14,7 +14,7 @@ const menu = [
{name:"代码库",index:"code"},
{name:"易修 (Issue)",index:"issues"},
{name:"合并请求",index:"pulls"},
{name:"Wiki",index:"wiki"},
// {name:"Wiki",index:"wiki"},
{name:"工作流(beta版)",index:"devops"},
// {name:"资源库",index:"resources"},
{name:"里程碑",index:"versions"},
@ -31,7 +31,8 @@ class Setting extends Component {
project_units:['home',"activity","code"],
divertVisible:false,
is_transfering:undefined,
projectName:undefined
projectName:undefined,
permission:undefined
};
}
@ -245,6 +246,7 @@ class Setting extends Component {
let mirror = projectDetail && projectDetail.mirror;
let type = projectDetail && projectDetail.type;
const forked_from_project_id = this.props && this.props.projectDetail && this.props.projectDetail.forked_from_project_id;
return (
<div>
<DivertModal

View File

@ -1,18 +1,17 @@
import React, { useEffect, useState } from 'react';
import './Index.scss';
import { AlignCenter, Blueback , FlexAJ } from '../Component/layout';
import { Dropdown, Input , Menu , Pagination, Spin , Popconfirm, Button } from 'antd';
import { Blueback , FlexAJ } from '../Component/layout';
import { Dropdown, Input , Menu , Pagination } from 'antd';
import { Link } from 'react-router-dom';
import UploadSource from './UploadSource';
import AddTag from './AddTag';
import { getImageUrl } from 'educoder';
import Nodata from '../Nodata';
import axios from 'axios';
const { Search } = Input;
const sort = [
"按上传时间排序",
"按下载次数排序"
"按下载次数排序",
"按引用排序"
]
const limit = 15;
const https = 'https://testfiles.trustie.net';
@ -22,22 +21,13 @@ function Index(props){
const [ total , setTotal ] = useState(0);
const [ search , setSearch ] = useState(undefined);
const [ data , setData ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true);
const [ error , setError ] = useState(false);
const [ attachments , setAttachments ] = useState(undefined);
const [ id , setId ] = useState(undefined);
const [ visible , setVisible ] = useState(false);
const [ addVisible , setAddVisible ] = useState(false);
const repo_id = props.projectDetail && props.projectDetail.repo_id;
const owner = props.match.params.owner;
const current_user = props.current_user;
useEffect(()=>{
if(owner && repo_id){
setIsSpin(true);
getData();
}
},[repo_id,owner,search,sortValue,page])
@ -56,10 +46,8 @@ function Index(props){
if(result && result.data){
setData(result.data.data.rows);
setTotal(result.data.data.total);
setIsSpin(false);
setError(false);
}
}).catch(error=>{setIsSpin(false);setError(true);})
}).catch(error=>{})
}
//
@ -85,52 +73,16 @@ function Index(props){
</Menu>
)
function listmenu(id,attachments,isPublic){
return(
<Menu>
<Menu.Item onClick={()=>{setId(id);setVisible(true);setAttachments(attachments)}}>更新版本</Menu.Item>
<Menu.Item onClick={()=>changeStatus(id,isPublic===1?0:1)}>{isPublic === 1 ? "设为私有":"设为公开"}</Menu.Item>
<Menu.Item onClick={()=>deleteSourceFunc(id)}>删除资源</Menu.Item>
</Menu>
)
}
//
function changeStatus(id,isPublic){
const url = https+`/api/project/achievement/updateStatus`;
axios.put(url,{
id,status:isPublic
}).then(result=>{
if(result && result.data){
props.showNotification(`资源${isPublic === 1 ? "设为公开":"设为私有"}成功!`);
setIsSpin(true);
getData();
}
}).catch({})
}
//
function deleteSourceFunc(id){
props.confirm({
content: "是否确认删除所选资源文件?",
onOk: () => {
const url = https + `/api/project/achievement/${id}`;
axios.delete(url).then(result=>{
if(result && result.data && result.data.code === "1"){
props.showNotification("资源删除成功");
setIsSpin(true);
getData();
}
})
}
})
}
const listmenu=(
<Menu>
<Menu.Item>更新版本</Menu.Item>
<Menu.Item>设为私有</Menu.Item>
<Menu.Item>删除资源</Menu.Item>
</Menu>
)
//
function onOk(){
setVisible(false);
setIsSpin(true);
getData();
}
@ -142,42 +94,14 @@ function Index(props){
}).then(result=>{
if(result && result.data){
props.showNotification("标记删除成功");
setIsSpin(true);
getData();
}
}).then(error=>{})
}
function addPanel(id){
setAddVisible(true);
setId(id);
}
function onCancelAdd(){
setId(undefined);
setAddVisible(false);
}
//
function sureAddTag(values){
const url = https+`/api/project/achievement/addTag?id=`+id+`&tagName=`+values.tagName;
axios.put(url).then(result=>{
if(result){
setId(undefined);
setAddVisible(false);
setIsSpin(true);
getData();
}
})
}
return(
<div className="sourcePanel">
<AddTag
visible={addVisible}
onCancel={onCancelAdd}
onOk={sureAddTag}
/>
<UploadSource
visible={visible}
onCancel={()=>setVisible(false)}
@ -185,15 +109,11 @@ function Index(props){
showNotification={props.showNotification}
owner={owner}
projectsId={repo_id}
id={id}
attachments={attachments}
/>
<div className="headtitle">
<FlexAJ>
<span className="font-18">资源库{total ? <span>({total})</span>:""}</span>
{ current_user && current_user.login && (props.projectDetail && props.projectDetail.permission) ?
<Blueback onClick={()=>{setId(undefined);setVisible(true);}}>上传资源</Blueback>:""
}
<span className="font-18">资源库(18)</span>
<Blueback onClick={()=>setVisible(true)}>上传资源</Blueback>
</FlexAJ>
</div>
<FlexAJ className="subHeadtitle">
@ -208,65 +128,43 @@ function Index(props){
<span className="color-grey-9">{sort[sortValue]}<i className="iconfont icon-sanjiaoxing-down font-16 color-grey-9 ml3"></i></span>
</Dropdown>
</FlexAJ>
<Spin spinning={isSpin}>
<div className="bodycontent">
{
data && data.length> 0 &&
<ul className="bodycontentul">
{
data.map((item,key)=>{
return(
<li>
<Link to= {`/${item.login}`} className="infoImg"><img src={getImageUrl(`/${item.imageUrl}`)} alt="" /></Link>
<div style={{flex:'1',width:"0"}}>
<FlexAJ>
<AlignCenter>
<a href={https+`/busiAttachments/download/${item.attachId}`} download className="infoname">{item.fileName}</a>
<a href={https + `/busiAttachments/view/${item.attachId}`}><i className="iconfont icon-shenqinggongkai font-15 ml10 color-grey-9"></i></a>
{item.isPublic === 0 && <span className="privateTip">私有</span>}
</AlignCenter>
{ current_user && current_user.login &&
<Dropdown overlay={()=>listmenu(item.id,item.attachments,item.isPublic)} placement={'bottomRight'}>
<i className="iconfont icon-gengduo1 color-grey-6"></i>
</Dropdown>
}
</FlexAJ>
<p className="infos">
<span>上传时间<span>{item.uploadTime}</span></span>
<span>文件大小<span>{item.fileSize}</span></span>
<span>下载<span>{item.download}</span></span>
</p>
<p className="infodesc task-hide-2">{item.remark}</p>
<div className="bodycontent">
<ul className="bodycontentul">
{
data && data.length> 0 && data.map((item,key)=>{
return(
<li>
<Link to= {`/users/${item.login}`} className="infoImg"><img src={getImageUrl(`${item.imageUrl}`)} alt="" /></Link>
<div style={{flex:'1',width:"0"}}>
<FlexAJ>
<a href={``} className="infoname">{item.fileName}</a>
<Dropdown overlay={listmenu} placement={'bottomRight'}>
<i className="iconfont icon-gengduo1 color-grey-6"></i>
</Dropdown>
</FlexAJ>
<p className="infos">
<span>上传时间<span>{item.uploadTime}</span></span>
<span>文件大小<span>{item.fileSize}</span></span>
<span>下载<span>{item.download}</span></span>
</p>
<p className="infodesc task-hide-2">{item.remark}</p>
{ item.tags && item.tags.length>0 &&
<div className="infotag">
{
item.tags && item.tags.length>0 && item.tags.map((i,k)=>{
item.tags.map((i,k)=>{
return(
<span>{i}
{
current_user && (current_user.login === item.login) ?
<Popconfirm title="确定要删除当前标签?" onConfirm={()=>removeTagFunc(item.id,i)} okText="是" cancelText="否">
<i className="iconfont icon-guanbi font-12 ml2"></i>
</Popconfirm>:""
}
</span>
<span>{i}<i className="iconfont icon-guanbi font-12 ml2" onClick={removeTagFunc}></i></span>
)
})
}
{
current_user && (current_user.login === item.login) &&
<a className="color-blue font-12" onClick={()=>addPanel(item.id)} style={{height:"20px",lineHeight:"20px"}}>+新增标签</a>
}
</div>
</div>
</li>
)
})
}
</ul>
}
{
((data && data.length === 0) || error) && <Nodata _html="暂无数据"/>
}
}
</div>
</li>
)
})
}
</ul>
{
total > limit &&
<div className="pt20 pb20 edu-txt-center">
@ -280,7 +178,6 @@ function Index(props){
</div>
}
</div>
</Spin>
</div>
)
}

View File

@ -21,7 +21,6 @@
}
.bodycontent{
padding:0px 20px;
min-height: 500px;
& > ul.bodycontentul > li{
display: flex;
border-bottom: 1px solid #eee;
@ -41,16 +40,6 @@
.infoname{
font-size: 16px;
}
.privateTip{
display: block;
font-size: 12px;
margin-left: 10px;
background-color: orange;
height: 18px;
line-height: 18px;
padding:0px 3px;
color: #fff;
}
.infos{
& > span{
margin-right: 20px;
@ -84,26 +73,4 @@
}
}
}
}
.versionTable{
.currentTip{
display: block;
padding:0px 3px;
border-radius: 2px;
border:1px solid #68c7ec;
font-size: 12px;
color: #68c7ec;
height: 18px;
line-height: 18px;
margin-left: 5px;
}
.ant-table-body{
margin:0px!important;
thead{
background-color: #eee;
}
thead >tr >th,tbody > tr > td{
padding:4px 5px!important;
}
}
}

View File

@ -79,4 +79,4 @@ function Uploads({ className , size , actionUrl,fileList,showNotification , load
</Upload>
)
}
export default Uploads;
export default Uploads;

View File

@ -5,18 +5,18 @@ import { AlignCenter } from '../Component/layout';
import axios from 'axios';
const { TextArea } = Input;
const data = [
{name:"sdfkjsfj.pdf",loadNum:"10",citeNum:"15",time:"2021-04-01 10:45"},
{name:"sdfkjsfj.pdf",loadNum:"10",citeNum:"15",time:"2021-04-01 10:45"},
{name:"sdfkjsfj.pdf",loadNum:"10",citeNum:"15",time:"2021-04-01 10:45"}
]
const https = 'https://testfiles.trustie.net';
function UploadSource({ form , visible , onCancel , onOk , showNotification , attachments , id ,owner,projectsId}){
const [ tableData , setTableData ] = useState(undefined);
function UploadSource({ form , visible , onCancel , onOk , showNotification ,owner,projectsId}){
const [ tableData , setTableData ] = useState(data);
const [ fileId , setFilesId ] = useState(undefined);
const [ fileName , setFileName ] = useState(undefined);
const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{
if(id && attachments){
setTableData(attachments);
}
},[id,attachments])
// id
function UploadFunc(id,name){
setFilesId(id);
@ -25,36 +25,37 @@ function UploadSource({ form , visible , onCancel , onOk , showNotification , at
const columns = [
{
dataIndex:"fileName",
key:"fileName",
dataIndex:"name",
key:"name",
title:"资源名称",
width:"42%",
width:"45%",
ellipsis:true,
render:(value,item,key)=>{
return <AlignCenter>
<div className="task-hide" style={{maxWidth:key===0 ? "240px":"100%"}}>{value}</div>
<div className="task-hide" style={{maxWidth:key===0 ? "250px":"100%"}}>{value}</div>
{ key === 0 && <span className="currentTip">当前版本</span> }
</AlignCenter>
}
},
{
dataIndex:"downloads",
key:"downloads",
dataIndex:"loadNum",
key:"loadNum",
title:"下载数",
width:"14%",
width:"15%",
className:"edu-txt-center"
},
{
dataIndex:"fileSizeString",
key:"fileSizeString",
title:"文件大小",
width:"16%",
dataIndex:"citeNum",
key:"citeNum",
title:"引用数",
width:"15%",
className:"edu-txt-center"
},
{
dataIndex:"createdAt",
key:"createdAt",
dataIndex:"time",
key:"time",
title:"上传时间",
width:"25%"
}
]
@ -73,35 +74,22 @@ function UploadSource({ form , visible , onCancel , onOk , showNotification , at
function postInfo(values){
const url = https+`/api/project/achievement/`;
if(id){
//
axios.put(url,{
id,fileName,fileId:`${fileId}`,
remark:values.remark
}).then(result=>{
if(result && result.data){
onOk();
}
}).catch(error=>{})
}else{
//
axios.post(url,{
fileId:`${fileId}`,
fileName,
login:owner,
projectId:projectsId,
...values
}).then(result=>{
if(result && result.data){
onOk();
}
}).catch(error=>{})
}
axios.post(url,{
fileId:`${fileId}`,
fileName,
login:owner,
projectId:projectsId,
...values
}).then(result=>{
if(result && result.data){
onOk();
}
}).catch(error=>{})
}
return(
<Modal
title={id?"更新资源版本":"上传资源"}
title={"上传资源"}
closable={false}
visible={visible}
onCancel={onCancel}
@ -113,8 +101,8 @@ function UploadSource({ form , visible , onCancel , onOk , showNotification , at
>
<div>
<Form>
{id && <Table className="versionTable mb20" columns={columns} dataSource={tableData} pagination={false} size={"small"}/> }
<Form.Item style={{display:id?"none":"block"}}>
<Table className="versionTable" columns={columns} dataSource={tableData} pagination={false} size={"small"}/>
<Form.Item>
{getFieldDecorator("tagNames",{
rules:[]
})(
@ -147,4 +135,4 @@ function UploadSource({ form , visible , onCancel , onOk , showNotification , at
</Modal>
)
}
export default Form.create()(forwardRef(UploadSource));;
export default UploadSource;

View File

@ -218,7 +218,7 @@ export default Form.create()(
[],
<Checkbox checked={check_box} onChange={change_check_box_status} style={OptionStyle}>新建项目<span className="color-grey-8 ml10">(成员可以在组织中新建项目创建者将自动获得新建的项目的管理员权限)</span></Checkbox>, false, 20,onwers ? "hide":""
)}
{helper(
{/* {helper(
'版本库权限:',
"authorize",
[],
@ -227,7 +227,7 @@ export default Form.create()(
<Radio value="write" style={addStyle}>写入权限<span className="color-grey-8 ml10">(成员可以查看和推送提交到团队项目)</span></Radio>
<Radio value="admin" style={OptionStyle}>管理员权限<span className="color-grey-8 ml10">(成员可以拉取和推送到团队项目同时可以添加协作者)</span></Radio>
</Radio.Group>, false, 20,onwers ? "hide":""
)}
)} */}
</Form>
{/* <div className={(auth!=="owner" && auth !=="admin") ? "" :"hide"}>
<p className="required">允许访问项目单元</p>

View File

@ -217,7 +217,6 @@ export default (props) => {
<Button type="default" className="ml10">导出<Icon type="caret-down" /></Button>
</Dropdown>
<Button type="default" className="ml10" onClick={preview}>预览</Button>
</div>
</div>

View File

@ -0,0 +1,56 @@
.delete-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.delete-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.delete-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.foot-submit {
margin-left: 3rem;
color: #df0002;
&:hover {
border-color: #df0002;
}
}
}

View File

@ -12,7 +12,7 @@ if (window.location.href.indexOf('localhost') > -1) {
actionUrl = "https://test-search.trustie.net";
// actionUrl = 'https://testforgeplus.trustie.net';
axios.defaults.withCredentials = true;
}else if (window.location.href.indexOf('forgeplus') > -1) {
}else if (window.location.href.indexOf('wiki-api') > -1) {
actionUrl = "https://wiki-api.trustie.net";
axios.defaults.withCredentials = true;
}

View File

@ -13,8 +13,10 @@ function Cloud({data}) {
var div = new Js2WordCloud(document.getElementById('cloud'))
let textList= d.categories;
let cyList=[]
for(let i=0;i<textList.length;i++){
cyList.push([textList[i],textList.length-i])
if(textList && textList.length > 0){
for(let i=0;i<textList.length;i++){
cyList.push([textList[i],textList.length-i]);
}
}
div.setOption({
backgroundColor:'transparent',

View File

@ -6,7 +6,7 @@ import CheckProfile from '../../Component/ProfileModal/Profile';
const { Search } = Input;
const limit = 20;
function ConcentrateBox({ visible , onCancel , onSure , username , choosed , history , showCompeleteDialog , completeProfile }) {
function ConcentrateBox({ visible , onCancel , onSure , username , choosed , history , showCompeleteDialog , completeProfile , current_user }) {
const [ page , setPage ]= useState(1);
const [ total , setTotal ]= useState(0);
const [ pageSize , setPageSize ] = useState(false);
@ -16,12 +16,14 @@ function ConcentrateBox({ visible , onCancel , onSure , username , choosed , his
const [ value , setValue ]= useState([]);
const [ isSpin , setIsSpin ]= useState(true);
const [ disable , setDisable ] = useState(false);
const [ loadCount , setLoadCount ] = useState(0);
const [ copyList , setCopyList ] = useState([]);
const [ copyAllList , setCopyAllList ] = useState([]);
useEffect(()=>{
if(visible){
if(visible && loadCount === 0){
setLoadCount(loadCount+1);
setIsSpin(true);
getProjectList();
}else{
@ -169,6 +171,7 @@ function ConcentrateBox({ visible , onCancel , onSure , username , choosed , his
(list && list.length === 0) && (copyList && copyList.length === 0) &&
<div style={{textAlign:"center"}}>您还没有公开的{search && `${search}`}项目先去
<CheckProfile
current_user={current_user}
showCompeleteDialog={showCompeleteDialog}
completeProfile={completeProfile}
sureFunc={()=>{history.push(`/projects/deposit/new`)}}

View File

@ -133,12 +133,7 @@ class Infos extends Component {
undo_events:e
});
})
.catch((error) => {
this.setState({
isSpin: false,
});
});
};
}
change_devops_type=(type)=>{
const {user} = this.state;
@ -194,7 +189,7 @@ class Infos extends Component {
render() {
const { current_user } = this.props;
const { username } = this.props.match.params;
const { user, isSpin, route_type , undo_events , menuKey } = this.state;
const { user, isSpin, route_type , undo_events , menuKey , project_type } = this.state;
return (
<div className="newMain clearfix">
<Spin spinning={isSpin}>
@ -207,14 +202,14 @@ class Infos extends Component {
<span>
{
user && user.gender===1?
<i className="iconfont icon-nan1"></i>
<i className="iconfont icon-nan"></i>
:
<i className="iconfont icon-nv1"></i>
<i className="iconfont icon-nv"></i>
}
</span>
</span>
<div className="text-center mt15 font-24 task-hide" title={user && user.username}>
<div className="text-center mt15 font-16 fwb">
{user && user.username}
</div>
<div className="userDescription">

View File

@ -143,18 +143,18 @@ function Index(props) {
topThree && topThree.length > 0 &&
<div className="roundBox">
<Round num={topThree[0][1]} color="#FF7F69" name={topThree[0][0]}/>
{ topThree[1] && <Round num={topThree[1][1]} color="#99dfff" name={topThree[1][0]}/> }
{ topThree[2] && <Round num={topThree[2][1]} color="#ff9e48" name={topThree[2][0]}/> }
<Round num={topThree[1][1]} color="#99dfff" name={topThree[1][0]}/>
<Round num={topThree[2][1]} color="#ff9e48" name={topThree[2][0]}/>
</div>
}
{
percentData &&
<div className="pBox">
<div className="progress">
<div class="progress">
{
percentData.map((i,k)=>{
return(
<span key={i.name} style={{width: `${i.p}%`, backgroundColor:`${i.color}`}}></span>
<span style={{width: `${i.p}%`, backgroundColor:`${i.color}`}}></span>
)
})
}
@ -163,8 +163,8 @@ function Index(props) {
{
percentData.map((i,k)=>{
return(
<span key={i.name}>
<i className="zero" style={{backgroundColor: `${i.color}`}}></i><span>{i.name}</span>
<span>
<i class="zero" style={{backgroundColor: `${i.color}`}}></i><span>{i.name}</span>
<span>{`${i.p}%`}</span>
</span>
)

BIN
src/images/login/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -1,11 +1,11 @@
import React, {Component} from "react";
import React, { Component } from "react";
import moment from 'moment';
import { getImageUrl } from 'educoder';
import '../courses/css/members.css';
import "../courses/common/formCommon.css";
import '../courses/css/Courses.css';
import beijintulogontwo from '../../../src/images/login/beijintulogontwo.png';
import educodernet from '../../../src/images/login/educodernet.png';
import educodernet from '../../../src/images/login/logo.png';
import LoginRegisterComponent from '../user/LoginRegisterComponent';
import FindPasswordComponent from '../user/FindPasswordComponent';
//educoder登入页面
@ -94,84 +94,39 @@ class EducoderLogin extends Component {
render() {
let {showbool,loginstatus,logini} = this.state;
let { showbool } = this.state;
const { settings } = this.props;
return (
<div style={newContainer} className=" clearfix" >
<div >
<div style={{
"display": "flex",
"justify-content": "center",
"align-items": "center",
"width": "100%"
}}>
<div style={{cursor:"pointer"}}>
{this.props.mygetHelmetapi === null ? ""
:
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.login_logo_url===null|| this.props.mygetHelmetapi.login_logo_url===undefined?
<img style={{cursor:"pointer"}} onClick={()=>this.gohome()} src={educodernet}/>
:
<img style={{cursor:"pointer"}} onClick={()=>this.gohome()} src={getImageUrl(this.props.mygetHelmetapi.login_logo_url)}/>
}
</div>
<div style={{"justify-content": "center","align-items": "center","width": "100%",textAlign:"center"}}>
<div style={{cursor:"pointer"}}>
{
settings && settings.login_logo_url ?
<img style={{cursor:"pointer"}} alt="" onClick={()=>this.gohome()} width="80px" src={getImageUrl(settings.login_logo_url)}/>
:
<img style={{cursor:"pointer"}} alt="" onClick={()=>this.gohome()} src={educodernet} width="80px"/>
}
</div>
{
showbool === 1 ?
<div style={{
display: "flex",
justifyContent: "center",
width: "100%",
marginTop: "25px",
}}>
<div>
<LoginRegisterComponent {...this.props} {...this.state}
Setshowbool={(e)=>this.Setshowbool(e)} ></LoginRegisterComponent>
</div>
<div style={{
display: "flex",
justifyContent: "center",
width: "100%",
marginTop: "25px",
}}>
<div>
<LoginRegisterComponent {...this.props} {...this.state} Setshowbool={(e)=>this.Setshowbool(e)} ></LoginRegisterComponent>
</div>
</div>
:
<div style={{
display: "flex",
justifyContent: "center",
width: "100%",
marginTop: "25px",
}}>
<div >
<FindPasswordComponent {...this.props} {...this.state}
Setshowbool={(e)=>this.Setshowbool(e)}></FindPasswordComponent>
</div>
</div>
<div style={{display: "flex",justifyContent: "center",width: "100%",marginTop: "25px",}}>
<div>
<FindPasswordComponent {...this.props} {...this.state} Setshowbool={(e)=>this.Setshowbool(e)}></FindPasswordComponent>
</div>
</div>
}
{this.props.mygetHelmetapi === null ? <div style={{
display: "flex",
justifyContent: "center",
width: "100%",
}}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>:
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.main_site===null|| this.props.mygetHelmetapi.main_site===undefined? <div style={{
display: "flex",
justifyContent: "center",
width: "100%",
}}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>:this.props.mygetHelmetapi.main_site===true?
<div style={{
display: "flex",
justifyContent: "center",
width: "100%",
}}>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>
:""
}
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>
</div>
)

View File

@ -321,8 +321,8 @@ class LoginDialog extends Component {
return flag;
}
componentDidMount() {
//true为PC端false为手机端
let flag = this.IsPC();
let flag = this.IsPC(); //true为PC端false为手机端
this.setState({
isphone: flag
})
@ -455,9 +455,10 @@ class LoginDialog extends Component {
}
render() {
let { login, isGoing, isGoingValue, disabled , Phonenumberisnotco , dialogBox, isRender, weixinlogin } = this.state;
let { settings } = this.props;
let { login, isGoing, isGoingValue, disabled, Phonenumberisnotco,
dialogBox, isRender, weixinlogin } = this.state;
let { settings } = this.props;
if (isRender === undefined) {
isRender = false
}

View File

@ -1068,11 +1068,6 @@ class NewMyShixunModel extends Component {
<style>
{
`
.newHeaders{
position: fixed;
top: 0px;
z-index: 999 !important;
}
.ant-drawer {
z-index: 800 !important;
}

View File

@ -28,12 +28,12 @@ body>.-task-title {
height:70px;
min-width: 1200px;
z-index: 1000;
background:rgba(255,255,255,1);
background:#001529;
position: fixed;
box-shadow: 0px 0px 14px rgb(0 0 0 / 10%);
}
.headerContent{
width:1200px;
padding:0px 25px;
margin:0px auto;
display: flex;
align-items: center;
@ -135,7 +135,6 @@ body>.-task-title {
height: 60px !important;
}
.HeaderSearch {
margin-top: 18px;
margin-right: 20px;
@ -328,4 +327,137 @@ body>.-task-title {
.progress-container {
flex: 1 0 0;
margin-left: 20px;
}
.newFooter > div{
padding: 90px 20px;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: center;
justify-content: center;
-ms-flex-align: start;
align-items: flex-start;
background: #242424;
min-width: 1200px;
}
.newFooter .module-list{
width: 200px;
text-align: left;
}
.newFooter .module-list>.title{
font-size: 16px;
color: #ddd;
margin-bottom: 20px;
font-weight: 400;
background-color: transparent;
border: none;
padding: 0px;
}
.newFooter .module-list a {
display: block;
color: #bbb;
line-height: 34px;
font-weight: 300;
font-size: 12px;
}
.newFooter .module-list a:hover {
color: #fff;
}
.newFooter .module-introduce{
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-align: center;
align-items: center;
width: 290px;
margin-top: -12px;
}
.newFooter .module-introduce p {
font-size: 12px;
color: #bbb;
line-height: 32px;
margin-top: 12px;
font-weight: 300;
text-align: justify;
}
.module-introduce ul {
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
padding: 0;
margin-top: 20px;
}
.module-introduce ul {
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
padding: 0;
margin-top: 20px;
}
.module-introduce ul li:first-child {
margin-right: 50px;
}
.module-introduce ul li {
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-pack: center;
justify-content: center;
-ms-flex-align: center;
align-items: center;
}
.module-introduce ul li>span {
font-size: 12px;
color: #bbb;
padding-top: 10px;
}
.module-introduce ol {
margin-top: 16px;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
padding: 0;
height: 108px;
width: 100%;
}
.module-introduce ol li {
height: 100%;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-pack: justify;
justify-content: space-between;
-ms-flex-align: center;
align-items: center;
}
.module-introduce ol li a {
font-size: 14px;
color: #bbb;
margin-top: 20px;
}
.module-introduce section {
width: 100%;
height: 115px;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-pack: justify;
justify-content: space-between;
-ms-flex-align: start;
align-items: flex-start;
font-size: 14px;
color: #bbb;
font-weight: 300;
}
.module-introduce .footer-line {
width: 310px;
height: 1px;
background-color: #3e4042;
margin: 32px 0;
}

View File

@ -25,7 +25,6 @@ export function TPMIndexHOC(WrappedComponent) {
dataquerys: {},
isloginCancel: undefined,
mygetHelmetapi: null,
giteaVisible:false,
email:undefined,
completeProfile:false,
showCP:false,
@ -68,6 +67,7 @@ export function TPMIndexHOC(WrappedComponent) {
///请求定制化的信息
this.getAppdata();
window.scrollTo(0,0);
}
@ -161,14 +161,6 @@ export function TPMIndexHOC(WrappedComponent) {
if (this.props.match.path === "/" && response.data.login) {
this.props.history.push(`/${response.data.login}`);
}
if(response.data && response.data.login){
if(response.data.need_edit_info){
this.setState({
giteaVisible:true,
email:response.data.email
})
}
}
}
}).catch((error) => {
console.log(error)
@ -192,23 +184,6 @@ export function TPMIndexHOC(WrappedComponent) {
return this.state.current_user && this.state.current_user.login != ''
}
onOk =(values)=>{
let url = `/users/sync_user_info.json`;
const { current_user } = this.state;
axios.post(url,{
login:current_user && current_user.login,
...values
}).then(result=>{
if(result && result.data && result.data.status === 0){
this.setState({
giteaVisible:false,
email:undefined
})
window.location.reload();
}
}).catch(error=>{})
}
showCompeleteDialog=()=>{
this.setState({
showCP:true
@ -247,12 +222,14 @@ export function TPMIndexHOC(WrappedComponent) {
>
<div className="newContainer newContainers">
<div style={{height:"70px"}}></div>
<div style={{minHeight:"60vh"}}>
{
current_user &&
<WrappedComponent initCommonState={(user) => this.initCommonState(user)}
{...this.props} {...this.state} {...common} >
</WrappedComponent>
}
</div>
</div>
</Spin>
<NewFooter {...this.state} {...this.props} />