杨树林 5 years ago
commit 55a874e262

File diff suppressed because one or more lines are too long

@ -7,6 +7,11 @@ let _url_origin = getUrl2()
// let _url_origin = `http://47.96.87.25:48080`;
if (!window.Cropper) {
$.ajaxSetup({
cache: true
});
$('head').append($('<link rel="stylesheet" type="text/css" />')
.attr('href', `${_url_origin}/react/public/js/cropper/cropper.min.css`));
@ -61,7 +66,14 @@ function save_avatar(){
// });
// }
}
/**
props 说明
imageId 源图片标签的id
previewId crop后预览dom的id
imageSrc 源图片src
width 数字格式
height 数字格式
*/
class Cropper extends Component {
state = {
};
@ -70,26 +82,31 @@ class Cropper extends Component {
}
componentDidMount() {
setTimeout(() => {
const image = document.getElementById('image');
const cropper = new window.Cropper(image, {
aspectRatio: 1,
crop(event) {
// console.log(event.detail.x);
// console.log(event.detail.y);
// console.log(event.detail.width);
// console.log(event.detail.height);
// console.log(event.detail.rotate);
// console.log(event.detail.scaleX);
// console.log(event.detail.scaleY);
},
this.options = {
aspectRatio: 1,
crop(event) {
// console.log(event.detail.x);
// console.log(event.detail.y);
// console.log(event.detail.width);
// console.log(event.detail.height);
// console.log(event.detail.rotate);
// console.log(event.detail.scaleX);
// console.log(event.detail.scaleY);
},
preview: '.img-preview',
});
}, 3000)
preview: this.props.previewId ? `#${this.props.previewId}` : '.img-preview',
}
setTimeout(() => {
const image = document.getElementById(this.props.imageId || '__image');
this.cropper = new window.Cropper(image, this.options);
}, 1000)
}
renew = (image) => {
this.cropper && this.cropper.destroy();
this.cropper = new window.Cropper(image, this.options);
}
render() {
const { width, height, previewId, imageSrc } = this.props;
@ -98,8 +115,8 @@ class Cropper extends Component {
{/* This rule is very important, please do not ignore this! */}
<style>{`
.wrapper {
width: ${ width || '500px'};
height: ${ height || '500px'};
width: ${ (width+'px') || '500px'};
height: ${ (height+'px') || '500px'};
}
img {
max-width: 100%;
@ -113,7 +130,7 @@ class Cropper extends Component {
`}</style>
<div className="wrapper">
{/* http://localhost:3007/images/footNavLogo.png 图片转了后不对 */}
<img id="image" src={`${imageSrc || "/images/testPicture.jpg"}`}></img>
<img id={this.props.imageId || "__image"} src={`${imageSrc || "/images/testPicture.jpg"}`}></img>
</div>
{/* background: 'aquamarine',
'border-radius': '128px'
@ -124,7 +141,7 @@ class Cropper extends Component {
{/* <img id="showImg" src="http://localhost:3007/images/testPicture.jpg"></img> */}
{/* <div id="canvasWrap"></div> */}
<button onClick={save_avatar.bind(this)}>save </button>
{/* <button onClick={save_avatar.bind(this)}>save </button> */}
</div>
);
}

@ -1,7 +1,9 @@
import React, { Component } from 'react';
import {Link} from 'react-router-dom'
const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack"}
const map={"blue":"blueFull","greyBack":"greyBack","grey":"greyWidthFixed","green":"greenBack",
'colorBlue': 'colorBlue', // 蓝字白底
}
class ActionBtn extends Component {
constructor(props) {
super(props);

@ -28,6 +28,7 @@ export { EDU_ADMIN, EDU_BUSINESS, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CER
, EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL} from './Const'
export { ModalHOC } from './components/ModalHOC'
export { default as Cropper } from './components/Cropper'
export { default as ConditionToolTip } from './components/ConditionToolTip'
export { default as DragValidator } from './components/DragValidator'

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@ -176,8 +176,8 @@ class Fileslists extends Component{
let list=result.data.data;
this.setState({
total_count:list.total_count,
public_count:list.public_count,
private_count:list.private_count,
publish_count:list.publish_count,
unpublish_count:list.unpublish_count,
files:list.files,
filesId:list.id,
name:list.name,
@ -625,13 +625,12 @@ class Fileslists extends Component{
})
}
render(){
let { searchValue,
checkBoxValues,
checkAllValue,
total_count,
public_count,
private_count,
publish_count,
unpublish_count,
files,
sorttype,
Modalstype,
@ -766,8 +765,8 @@ class Fileslists extends Component{
secondRowLeft={
<div style={{"display":"inline-block", "marginTop": "22px"}}>
<span> {total_count} 个资源</span>
<span style={{"marginLeft":"16px"}}>已发布{public_count}</span>
<span style={{"marginLeft":"16px"}}>未发布{private_count}</span>
<span style={{"marginLeft":"16px"}}>已发布{publish_count}</span>
<span style={{"marginLeft":"16px"}}>未发布{unpublish_count}</span>
</div>
}
onPressEnter={this.onPressEnter}

@ -616,12 +616,12 @@ a.white-btn.use_scope-btn:hover{
border-radius: 10px;
}
.Navmodal .ant-modal-content .ant-modal-header{
border-radius: 10px 10px 0 0;
/*border-radius: 10px 10px 0 0;*/
}
.ant-modal-content{
-webkit-box-shadow: 0 4px 12px transparent !important;
box-shadow: 0 4px 12px transparent !important;
border-radius: 10px !important;
/*border-radius: 10px !important;*/
}
.Navmodal .ant-modal-body{
@ -677,6 +677,11 @@ a.white-btn.use_scope-btn:hover{
color: #fff!important;
}
.colorBlue {
background-color: #fff;
color: #4CACFF;
border: 1px solid #4CACFF;
}
.greyBack{
/* 不要固定宽度 */
/* width: 64px; */

@ -74,11 +74,6 @@ class GraduateTopicItem extends Component{
<a className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.name}</a>:
<a onClick={() => this.toDetailPage(`${discussMessage.id}`)} className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.name}</a>
}
{
isAdmin?<a onClick={()=>this.toDetailPage(`${discussMessage.id}`)} className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.name}</a>:""
}
{
isStudent?<a onClick={() => this.toDetailPage(`${discussMessage.id}`)}
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.name}</a>:""

@ -324,8 +324,12 @@ class Poll extends Component{
}
// 题库选用成功后,立即发布,刷新页面
useBankSuccess=(checkValue,value)=>{
// let{type,StudentList_value,page}=this.state
// this.InitList(type,StudentList_value,page);
this.setState({
isSpin:true
})
let{type,StudentList_value,page}=this.state
this.InitList(type,StudentList_value,page);
this.setState({
checkBoxValues:[]
})

@ -84,12 +84,12 @@ class PollDetailIndex extends Component{
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span>问卷详情</span>
</p>
<p className="clearfix mb20">
<span className="color-grey-3 font-24 fl task-hide break-word" style={{maxWidth:"900px",lineHeight:"30px"}} title={`${pollDetail && pollDetail.polls_name}`}>{pollDetail && pollDetail.polls_name}</span>
<span className="mt3 fl">
<p className="clearfix mb20 lineh-25">
<span className="color-grey-3 font-24 fl task-hide break-word" style={{maxWidth:"900px",lineHeight:"25px"}} title={`${pollDetail && pollDetail.polls_name}`}>{pollDetail && pollDetail.polls_name}</span>
<span className="mt3 fl" style={{height:"25px"}}>
<CoursesListType typelist={[`${map[pollDetail && pollDetail.polls_status]}`]} typesylename={""} />
</span>
<WordsBtn className="fr font-16 mt5" style="grey" onClick={()=>this.props.history.goBack()}>返回</WordsBtn>
<WordsBtn className="fr font-16 mt2" style="grey" onClick={()=>this.props.history.goBack()}>返回</WordsBtn>
</p>
<div>
<div className="clearfix edu-back-white pl30 pr30 bor-bottom-greyE">

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import Cropper from '../../common/components/Cropper'
import ChangeHeaderPicModal from '../user/account/ChangeHeaderPicModal'
class TestCrop extends Component {
state = {
};
@ -14,6 +14,8 @@ class TestCrop extends Component {
const props = this.props;
return (
<div>
<button onClick={() => { this.refs['changeHeaderPicModal'].setVisible(true)}}>open</button>
<ChangeHeaderPicModal ref="changeHeaderPicModal"></ChangeHeaderPicModal>
<Cropper></Cropper>
</div>
);

@ -156,7 +156,35 @@ class Challenges extends Component {
}
}
startgameid=(id)=>{
let url = "/shixuns/" + id + "/shixun_exec.json";
axios.get(url).then((response) => {
if (response.data.status === -2) {
this.setState({
shixunsreplace:true,
hidestartshixunsreplacevalue:response.data.message+".json"
})
} else if (response.data.status === -1) {
console.log(response)
}else if(response.data.status===-3){
this.setState({
shixunsmessage:response.data.message,
startshixunCombattype:true,
})
} else {
window.location.href = "/tasks/" + response.data.game_identifier;
// window.location.href = path
// let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path);
}
}).catch((error) => {
});
}
hidestartshixunsreplace=(url)=>{
this.setState({
@ -167,7 +195,7 @@ class Challenges extends Component {
// let path="/shixuns/"+response.data.shixun_identifier+"/challenges";
// this.props.history.push(path);
message.success('重置成功,正在进入实训!');
this.startshixunCombat(response.data.shixun_identifier);
this.startgameid(response.data.shixun_identifier);
this.setState({
shixunsreplace:false,
isSpin:false,
@ -179,11 +207,7 @@ class Challenges extends Component {
).catch((error) => {
});
this.setState({
startbtn:false,
shixunsreplace:false,
isSpin:false
})
}
//编辑实训题目选择题
@ -455,48 +479,43 @@ class Challenges extends Component {
{/*判断比较复杂 有排第一不能是灰色按钮*/}
{item.status === 2 ?
<a className="edu-default-btn edu-blueline-btn fr Finish_button mtf3"
onClick={() => this.startshixunCombat(false,undefined, item.challenge_id)}
<a className={"edu-default-btn edu-blueline-btn fr Finish_button mtf3"}
onClick={()=>this.startshixunCombat(false,undefined, item.challenge_id)}
// onClick={() => this.startshixunCombat(false)}
title={"查看挑战关卡"}
>已完成</a> : ""
}
{
ChallengesDataList.allow_skip === true && item.status === 1?
<a className="edu-default-btn edu-blueback-btn fr Finish_button"
<a className={"edu-default-btn edu-blueback-btn fr Finish_button"}
title={"直接挑战"}
style={{marginTop: '-2px'}}
onClick={() => this.startshixunCombat(false,undefined, item.challenge_id)}
onClick={()=>this.startshixunCombat(false,undefined, item.challenge_id)}
// onClick={() => this.startshixunCombat(false)}
>直接挑战</a> : ""
}
{
ChallengesDataList.allow_skip === false ? item.status === 1?
<Tooltip placement="bottom" title={"直接挑战"}>
<a className={"edu-default-btn edu-blueback-btn fr Finish_button"}
onClick={()=>this.startshixunCombat(false,undefined, item.challenge_id)}
style={{marginTop: '-2px'}}>直接挑战</a>
</Tooltip>:"":""
{
ChallengesDataList.allow_skip === false ? item.status === 1 && newstatus === 2 ?
<Tooltip placement="bottom" title={item.open_game!=""?"直接挑战":"请先完成前序关卡"}>
<a className={item.open_game!=""?"edu-default-btn edu-blueback-btn fr Finish_button":"edu-default-btn edu-greyback-btn fr Finish_button"}
onClick={item.open_game!=""?()=>this.startshixunCombat(false,undefined, item.challenge_id):""}
style={{marginTop: '-2px'}}>直接挑战</a>
</Tooltip>
: item.status === 1 && newstatus === 1 ?
<Tooltip placement="bottom" title={this.props.identity<5?"直接挑战":"请先完成前序关卡"}>
<a className={this.props.identity<5&&item.open_game!=""?"edu-default-btn edu-blueback-btn fr Finish_button":"edu-default-btn edu-greyback-btn fr Finish_button"}
onClick={this.props.identity<5&&item.open_game!=""?()=>this.startshixunCombat(false,undefined, item.challenge_id):""}
style={{marginTop: '-2px'}}>直接挑战</a>
</Tooltip> : "" : ""
}
}
{
item.status === 0 ?
<Tooltip placement="bottom" title={this.props.identity<5&&item.open_game!=""?"直接挑战":"请先完成前序关卡"}>
<a className={this.props.identity<5&&item.open_game!=""?"edu-default-btn edu-blueback-btn fr Finish_button":"edu-default-btn edu-greyback-btn fr Finish_button"}
onClick={this.props.identity<5&&item.open_game!=""?()=>this.startshixunCombat(false,undefined, item.challenge_id):""}
<Tooltip placement="bottom" title={"请先完成前序关卡"}>
<a className={"edu-default-btn edu-greyback-btn fr Finish_button"}
// onClick={this.props.identity<5&&item.open_game!=""?()=>this.startshixunCombat(false,undefined, item.challenge_id):""}
style={{marginTop: '-2px'}}>直接挑战</a>
</Tooltip>: ""
</Tooltip>:""
}
@ -574,3 +593,19 @@ class Challenges extends Component {
}
export default Challenges;
// {
// ChallengesDataList.allow_skip === false ? item.status === 1 && newstatus === 2 ?
// <Tooltip placement="bottom" title={"直接挑战"}>
// <a className={"edu-default-btn edu-blueback-btn fr Finish_button"}
// onClick={()=>this.startshixunCombat(false,undefined, item.challenge_id)}
// style={{marginTop: '-2px'}}>直接挑战</a>
// </Tooltip>
//
// : item.status === 1 && newstatus === 1 ?
// <Tooltip placement="bottom" title={"直接挑战"}>
// <a className={"edu-default-btn edu-blueback-btn fr Finish_button"}
// onClick={()=>this.startshixunCombat(false,undefined, item.challenge_id)}
// style={{marginTop: '-2px'}}>直接挑战</a>
// </Tooltip> : "" : ""
//
// }

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import {CNotificationHOC} from '../courses/common/CNotificationHOC'
import Loading from '../../Loading';
import Loadable from 'react-loadable';
@ -10,6 +10,7 @@ import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { SnackbarHOC, getImageUrl } from 'educoder';
import AccountNav from './account/AccountNav'
import axios from 'axios'
const AccountBasic= Loadable({
loader: () => import('./account/AccountBasic'),
@ -30,16 +31,52 @@ const AccountSecure= Loadable({
})
class AccountPage extends Component {
constructor (props) {
super(props)
this.state = {
basicInfo:undefined
}
}
componentDidUpdate =(prevState)=>{
if(this.props.current_user && this.props.current_user != prevState.current_user){
this.getBasicInfo(this.props.current_user.login);
}
}
componentDidMount = () =>{
if(this.props.current_user){
this.getBasicInfo(this.props.current_user.login);
}
}
getBasicInfo=(login)=>{
let url=`/users/accounts/${login}.json`;
axios.get(url).then((result)=>{
if(result.data){
this.setState({
basicInfo:result.data
})
if(result.data && result.data.base_info_completed == false){
this.props.history.push(`/account/basic/edit`);
}
}
}).catch((error)=>{
console.log(error);
})
}
render() {
const common = {}
let { basicInfo }=this.state;
const common = { basicInfo, getBasicInfo : this.getBasicInfo }
return (
<div className="newMain clearfix accountPage">
<div className="newMain clearfix">
<div className="educontent df pt20">
<style>{`
.accountPage {
display: flex;
}
`}</style>
<AccountNav {...this.props}></AccountNav>
<AccountNav {...this.props} {...common}></AccountNav>
<Switch {...this.props}>
<Route exact path="/account/basic"
@ -71,10 +108,10 @@ class AccountPage extends Component {
}
></Route>
</Switch>
</div>
</div>
);
}
}
export default SnackbarHOC() ( TPMIndexHOC ( AccountPage ));
export default CNotificationHOC()(SnackbarHOC() ( TPMIndexHOC ( AccountPage )));

@ -2,22 +2,24 @@ import React, { Component } from 'react';
import { SnackbarHOC, getImageUrl, City } from 'educoder';
import { Form, Button, Input, Radio, Select, Tooltip, Icon } from 'antd'
import './common.css'
const RadioGroup = Radio.Group;
const Option = Select.Option
const radioOptions = [
{ label: '男', value: 'Apple' },
{ label: '女', value: 'Pear' },
{ label: '男', value: 'boy' },
{ label: '女', value: 'girl' },
];
class AccountBasicEdit extends Component {
handleSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
constructor(props){
super(props);
}
})
}
render() {
const { getFieldDecorator } = this.props.form;
const {basicInfo} =this.props
const showRealName = false;
return (
<div className="basicFormWrap">
@ -29,14 +31,6 @@ class AccountBasicEdit extends Component {
.formItemInline .ant-form-item-control-wrapper {
display: inline-block;
}
.basicForm {
background: #fff;
padding: 30px;
width: 930px;
margin: 20px;
margin-bottom: 10px;
}
.basicForm .title {
font-size: 16px;
padding-left: 30px;
@ -68,21 +62,21 @@ class AccountBasicEdit extends Component {
label="昵称"
className="display formItemInline"
>
hushasha
{basicInfo && basicInfo.nickname}
</Form.Item>
<Form.Item
label="姓名"
className="display formItemInline"
>
*
{basicInfo && basicInfo.name}
</Form.Item>
<Form.Item
label="性别"
className="display formItemInline"
>
{basicInfo && basicInfo.gender == 0?"男":""}
</Form.Item>
@ -90,28 +84,28 @@ class AccountBasicEdit extends Component {
label="所在地"
className="display formItemInline"
>
湖南省 长沙市
{basicInfo && basicInfo.location} {basicInfo && basicInfo.location_city}
</Form.Item>
<Form.Item
label="职业"
className="display formItemInline"
>
专业人士
{basicInfo && basicInfo.technical_title}
</Form.Item>
<Form.Item
label="学校/单位"
className="display formItemInline mb0"
>
中国移动长沙分公司
{basicInfo && basicInfo.school_name}
</Form.Item>
<Form.Item
label="院系/部门"
className="display formItemInline mb0"
>
市场部
{basicInfo && basicInfo.department_name}
</Form.Item>
</Form>
</div>

@ -4,65 +4,320 @@ import { SnackbarHOC, getImageUrl, City } from 'educoder';
import { Form, Button, Input, Radio, Select, Tooltip, Icon } from 'antd'
import ApplyForAddOrgModal from '../modal/ApplyForAddOrgModal'
import ApplyForAddChildOrgModal from '../modal/ApplyForAddChildOrgModal'
import axios from 'axios'
const RadioGroup = Radio.Group;
const Option = Select.Option
const radioOptions = [
{ label: '男', value: 'Apple' },
{ label: '女', value: 'Pear' },
];
const Option = Select.Option;
const map={"teacher":"教师", "student":"学生", "professional":"专业人士"}
class AccountBasic extends Component {
constructor(props){
super(props);
this.state={
nameLength:0,
showRealName:true,
schoolList:undefined,
filterSchoolList:undefined,
school:undefined,
departments:undefined,
filterDepartments:undefined,
departmentsName:undefined,
identity:"teacher",
school_id:undefined,
department_id:undefined
}
}
componentDidUpdate =(prevProps)=>{
if(this.props.basicInfo && prevProps.basicInfo == undefined){
this.setValue(this.props.basicInfo);
this.getSchoolList(this.props.basicInfo);
}
}
componentDidMount = () =>{
if(this.props.basicInfo){
this.setValue(this.props.basicInfo);
this.getSchoolList(this.props.basicInfo);
}
}
setValue=(basicInfo)=>{
if(basicInfo){
//if(basicInfo.nickname){
this.setState({
nameLength:basicInfo.nickname?basicInfo.nickname.length:0,
showRealName:basicInfo.show_realname,
identity:basicInfo.identity
})
//}
this.props.form.setFieldsValue({
nickname:basicInfo.nickname,
name:!basicInfo.show_realname ? this.hideRealName(basicInfo.name) : basicInfo.name,
student_No:basicInfo.student_id,
sex:String(basicInfo.gender),
job:map[basicInfo.identity],
org:basicInfo.school_name,
org2:basicInfo.department_name,
job1:basicInfo && basicInfo.identity=="teacher" ? basicInfo.technical_title:"教授",
job2:basicInfo && basicInfo.identity=="professional" ? basicInfo.technical_title:"企业管理者",
city:[basicInfo.location,basicInfo.location_city]
})
}
}
// 获取学校、单位
getSchoolList=(basicInfo)=>{
let url=`/schools/for_option.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
schoolList:result.data.schools
})
if(basicInfo && basicInfo.school_name){
this.setState({
school:basicInfo.school_name,
filterSchoolList:this.state.schoolList.filter(function(item){
return item.name.indexOf(basicInfo.school_name)>-1;
})
})
this.getDepartments(basicInfo.school_name,false);
}
}
}).catch((error)=>{
console.log(error);
})
}
// 输入昵称时change剩余的字数
changeNickName=(e)=>{
let num= 10 - parseInt(e.target.value.length);
this.setState({
nameLength:num < 0 ? 0 : num
})
}
handleSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log(values);
let {basicInfo}=this.props;
if(!err){
let url=`/users/accounts/${basicInfo.id}.json`
axios.put((url),{
nickname:values.nickname,
name:values.name,
show_realname:this.state.showRealName,
gender:parseInt(values.sex),
location:values.city[0],
location_city:values.city[1],
identity:values.job=="教师"?"teacher":values.job=="学生"?"student":"professional",
technical_title:values.job1 || values.job2,
student_id:values.job=="学生" ? values.student_No : null,
school_id:this.state.school_id,
department_id:this.state.department_id
}).then((result)=>{
if(result){
this.props.getBasicInfo();
}
}).catch((error)=>{
console.log(error);
})
}
})
}
// 隐藏或显示真实姓名
showOrHide=(flag,name)=>{
this.setState({
showRealName:flag==true?false:true
})
if(flag==true){
this.hideRealName(name);
}else{
this.props.form.setFieldsValue({
name
})
}
}
// 将名字隐藏起来
hideRealName=(name)=>{
let len=parseInt(name.length)-1;
let str="";
for(var i = 0; i < len; i++){ str += "*"; }
name = name.substr(0,1)+str;
this.props.form.setFieldsValue({
name
})
}
// 过滤学校
filterList=(e)=>{
let arr=[];
if(e){
arr= this.state.schoolList.filter(function(item){
return item.name.indexOf(e)>-1;
});
this.props.form.setFieldsValue({
org:e
})
this.setState({
school:e,
filterSchoolList:arr
})
}
// else{
// let {school}=this.state;
// arr= this.state.schoolList.filter(function(item){
// return item.name.indexOf(school)>-1;
// });
// }
}
//搜索部门
searchDepartment=(e)=>{
this.props.form.setFieldsValue({
org2:e
})
let arr = this.state.departments.filter(function(item){
return item.name.indexOf(e) > -1
})
this.setState({
filterDepartments:arr,
departmentsName:e
})
}
// 选择部门、学院
changeDepartment=(e)=>{
let arr=this.state.departments.filter(function(item){
return item.name == e;
});
this.setState({
departmentsName:e,
department_id:arr[0].id
})
}
// 选择学校(获取对应学校的学院、部门)
changeList=(e)=>{
this.getDepartments(e,true);
}
getDepartments=(e,flag)=>{
let arr=this.state.schoolList.filter(function(item){
return item.name == e;
});
// 保存选择的学校id
this.setState({
school_id:arr[0].id,
school:e,
})
let url=`/schools/${arr[0].id}/departments/for_option.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
departments:result.data.departments,
filterDepartments:result.data.departments
})
// 切换学校后,部门默认选择第一个
if(result.data.departments && result.data.departments.length>0 && flag==true){
this.props.form.setFieldsValue({
org2:result.data.departments[0].name
})
}
}
}).catch((error)=>{
console.log(error);
})
}
// 切换职称
changeJob=(e)=>{
this.setState({
identity:e
})
let {basicInfo}=this.props;
if(basicInfo){
this.props.form.setFieldsValue({
job1:basicInfo && basicInfo.identity=="teacher" ? basicInfo.technical_title:"教授",
job2:basicInfo && basicInfo.identity=="professional" ? basicInfo.technical_title:"企业管理者",
})
}
}
showApplyForAddOrgModal = () => {
this.applyForAddOrgForm.setVisible(true)
}
showApplyForAddChildOrgModal = () => {
this.applyForAddChildOrgForm.setVisible(true)
let{school,schoolList}=this.state;
let arr=schoolList.filter(function(item){
return item.name == school;
});
if(arr.length > 0){
this.applyForAddChildOrgForm.setVisible(true)
}else{
this.props.showNotification("请先选择正确的单位或者学校!");
}
}
applyForAddChildOrgForm
render() {
let{
nameLength,
showRealName,
filterSchoolList,
filterDepartments,
school,
school_id,
departmentsName,
identity
}=this.state;
const { getFieldDecorator } = this.props.form;
const showRealName = false;
let{basicInfo}=this.props
return (
<div className="basicFormWrap">
<ApplyForAddOrgModal ref="applyForAddOrgModal" wrappedComponentRef={(form) => this.applyForAddOrgForm = form} ></ApplyForAddOrgModal>
<ApplyForAddChildOrgModal ref="applyForAddChildOrgModal" wrappedComponentRef={(form) => this.applyForAddChildOrgForm = form} ></ApplyForAddChildOrgModal>
<ApplyForAddOrgModal ref="applyForAddOrgModal" wrappedComponentRef={(form) => this.applyForAddOrgForm = form} schoolName={school}
{...this.props}></ApplyForAddOrgModal>
<ApplyForAddChildOrgModal ref="applyForAddChildOrgModal" schoolName={school} schoolId={school_id} departmentName={departmentsName}
{...this.props} wrappedComponentRef={(form) => this.applyForAddChildOrgForm = form} ></ApplyForAddChildOrgModal>
<div className="basicForm">
<style>{`
.formItemInline {
display: flex;
margin-bottom: 20px;
position:relative;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-20px;
left:0px;
width:100%;
}
.formItemInline .ant-form-item-control-wrapper {
display: inline-block;
}
.basicForm {
background: #fff;
padding: 30px;
width: 930px;
margin: 20px;
.resetSexStyle .ant-form-item-label,.resetSexStyle .ant-form-item-control-wrapper .ant-form-item-control{
height:25px;
line-height:25px;
}
.basicForm .title {
font-size: 16px;
padding-left: 30px;
margin-bottom: 10px;
}
.basicForm .title {
font-size: 16px;
padding-left: 30px;
margin-bottom: 10px;
}
.basicForm input, .basicForm .ant-input-affix-wrapper, .basicForm .ant-select {
width: 400px;
font-size: 14px;
}
.basicForm .saveBtn {
width: 120px;
margin-left: 100px;
}
.basicForm input, .basicForm .ant-input-affix-wrapper, .basicForm .ant-select {
width: 400px;
font-size: 14px;
}
.basicForm .saveBtn {
width: 120px;
margin-left: 100px;
}
.basicForm .ant-input-lg {
height: 32px;
}
@ -70,9 +325,15 @@ class AccountBasic extends Component {
width: 100px;
padding-right: 10px;
}
.basicForm .ant-form-item-label label {
color: #979797
}
.basicForm .ant-form-item-label label {
color: #979797
}
.basicForm .ant-cascader-picker-label{
font-size:14px;
}
.resetCityStyle .ant-form-item-control{
width:190px;
}
`}</style>
<div className="title">基本信息</div>
@ -88,13 +349,15 @@ class AccountBasic extends Component {
message: '请输入您的昵称',
}],
})(
<Input placeholder="请输入您的昵称10个字以内"></Input>
<Input placeholder="请输入您的昵称10个字以内" onInput={this.changeNickName} maxLength="10" suffix ={
<span className="color-grey-6 font-13">{String(nameLength)}/10</span>
}></Input>
)}
</Form.Item>
<Form.Item
label="姓名"
className="mt15 formItemInline"
className="formItemInline"
>
{getFieldDecorator('name', {
rules: [{
@ -103,10 +366,8 @@ class AccountBasic extends Component {
message: '请输入您的姓名',
}],
})(
<Input placeholder="请输入您的姓名" suffix={
<Tooltip title="">
<Icon type="info-circle" style={{ color: 'rgba(0,0,0,.45)' }} />
</Tooltip>
<Input placeholder="请输入您的姓名" disabled={!showRealName} suffix={
<i className={showRealName?"iconfont icon-xianshi font-18 color-blue":"iconfont icon-yincang font-18 color-blue"} onClick={()=>this.showOrHide(showRealName,basicInfo.name)}></i>
}></Input>
)}
<span>{ showRealName ? '(显示:平台将显示您的真实姓名)' : '(隐藏:平台将显示你的昵称)' }</span>
@ -114,55 +375,124 @@ class AccountBasic extends Component {
<Form.Item
label="性别"
className="mt15 formItemInline"
className="formItemInline resetSexStyle"
>
{getFieldDecorator('sex', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '',
message: '请选择性别',
}],
})(
<RadioGroup options={radioOptions} />
<RadioGroup>
<Radio value="0"></Radio>
<Radio value="1"></Radio>
</RadioGroup>
)}
</Form.Item>
<Form.Item
label="所在地"
className="mt15 formItemInline"
className="formItemInline resetCityStyle"
>
{getFieldDecorator('city', {
rules: [{
// initialValue: this.state.cityDefaultValue,
type: 'array',
required: true,
message: '请先选择所在地',
}],
})(
<City ></City>
)}
</Form.Item>
<Form.Item
label="职业"
className="mt15 formItemInline"
>
{getFieldDecorator('job', {
rules: [{
// initialValue: this.state.cityDefaultValue,
type: 'array',
required: true,
message: '请先选择职业',
}],
})(
<City ></City>
<City></City>
)}
</Form.Item>
<div className="clearfix">
<Form.Item
label="职业"
className="formItemInline fl"
>
{getFieldDecorator('job', {
rules: [{
initialValue:"teacher",
required: true,
message: '请先选择职业',
}],
})(
<Select style={{width:"190px",marginRight:"20px"}} onChange={this.changeJob}>
<Option value="teacher">教师</Option>
<Option value="student">学生</Option>
<Option value="professional">专业人士</Option>
</Select>
)}
</Form.Item>
{
identity && identity=="student" &&
<Form.Item
label=""
className="formItemInline fl"
// style={{display:identity && identity=="student" ? "block":"none"}}
>
{getFieldDecorator('student_No', {
rules: [{
required: true,
message: '请先输入学号',
}],
})(
<Input type="text" placeholder="请输入学号" style={{width:"190px"}}></Input>
)}
</Form.Item>
}
{
identity && identity=="teacher" &&
<Form.Item
label=""
className="formItemInline fl"
// style={{display:identity && identity=="teacher" ? "block":"none"}}
>
{getFieldDecorator('job1', {
rules: [{
initialValue:"教授",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}}>
<Option value="教授">教授</Option>
<Option value="副教授">副教授</Option>
<Option value="讲师">讲师</Option>
<Option value="助教">助教</Option>
</Select>
)}
</Form.Item>
}
{
identity && identity=="professional" &&
<Form.Item
label=""
className="formItemInline fl mb0"
// style={{display:identity && identity=="professional" ? "block":"none"}}
>
{getFieldDecorator('job2', {
rules: [{
initialValue:"企业管理者",
required: true,
message: '请先选择职称',
}],
})(
<Select style={{width:"190px"}}>
<Option value="企业管理者">企业管理者</Option>
<Option value="部门管理者">部门管理者</Option>
<Option value="高级工程师">高级工程师</Option>
<Option value="工程师">工程师</Option>
<Option value="助理工程师">助理工程师</Option>
</Select>
)}
</Form.Item>
}
</div>
<Form.Item
label="学校/单位"
className="mt15 formItemInline mb0"
className="formItemInline mb0"
>
{getFieldDecorator('org', {
rules: [{
@ -172,20 +502,26 @@ class AccountBasic extends Component {
message: '请先选择学校/单位',
}],
})(
<Select width={400}>
<Option value="1">国防科技大学</Option>
<Option value="2">国防科技大学1</Option>
<Select width={400} showSearch onSearch={this.filterList} onChange={this.changeList}>
{
filterSchoolList && filterSchoolList.map((item,key)=>{
return(<Option value={item.name} key={item.id}>{item.name}</Option>)
})
}
</Select>
)}
</Form.Item>
<div style={{marginLeft: '100px'}}>
<span style={{color: '#CDCDCD'}}>未找到包含Test的高校</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddOrgModal}>申请新增</span>
<div style={{marginLeft: '100px',height:"20px",lineHeight:"20px"}}>
{!filterSchoolList || (filterSchoolList && filterSchoolList.length==0 )&&
<span>
<span style={{color: '#CDCDCD'}}>未找到包含{school}的高校</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddOrgModal}>申请新增</span>
</span>
}
</div>
<Form.Item
label="院系/部门"
className="mt15 formItemInline mb0"
className="formItemInline mb0"
>
{getFieldDecorator('org2', {
rules: [{
@ -195,16 +531,26 @@ class AccountBasic extends Component {
message: '请先选择院系/部门',
}],
})(
<Select width={400}>
<Option value="1">计算机学院</Option>
<Option value="2">数学学院</Option>
<Select width={400} showSearch onSearch={this.searchDepartment} onChange={this.changeDepartment}>
{
filterDepartments && filterDepartments.map((item,key)=>{
return(
<Option value={item.name}>{item.name}</Option>
)
})
}
</Select>
)}
</Form.Item>
<div style={{marginLeft: '100px'}}>
<span style={{color: '#CDCDCD'}}>未找到包含Test的院系/部门</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddChildOrgModal}>申请新增</span>
</div>
<div style={{marginLeft: '100px',height:"20px",lineHeight:"20px"}}>
{
!filterDepartments || (filterDepartments && filterDepartments.length==0 )&&
<span>
<span style={{color: '#CDCDCD'}}>未找到包含{departmentsName}的院系/部门</span>
<span style={{color: '#4CACFF', cursor: 'pointer'}} onClick={this.showApplyForAddChildOrgModal}>申请新增</span>
</span>
}
</div>
{/* htmlType="submit" */}
{/* <Form.Item>

@ -3,26 +3,33 @@ import React, { Component } from 'react';
import { WordsBtn, getImageUrl } from 'educoder';
import RealNameCertificationModal from '../modal/RealNameCertificationModal'
import '../../courses/css/Courses.css'
import {CNotificationHOC} from '../../courses/common/CNotificationHOC'
class AccountCertification extends Component {
showRealNameCertificationModal = () => {
constructor(props){
super(props);
this.state={
certification:1
}
}
showRealNameCertificationModal = (index) => {
this.setState({
certification:index
})
this.realNameCertificationModal.setVisible(true)
}
render() {
let {certification}=this.state
let {basicInfo} = this.props;
return (
<div className="basicFormWrap">
<RealNameCertificationModal ref="realNameCertificationModal"
wrappedComponentRef={(form) => this.realNameCertificationModal = form}
<RealNameCertificationModal ref="realNameCertificationModal" {...this.props}
wrappedComponentRef={(form) => this.realNameCertificationModal = form} certification={certification}
></RealNameCertificationModal>
<div className="basicForm">
<style>{`
.basicForm {
background: #fff;
padding: 30px;
width: 930px;
margin: 20px;
margin-bottom: 10px;
}
.basicForm .title {
font-size: 16px;
padding-left: 30px;
@ -39,7 +46,7 @@ class AccountCertification extends Component {
margin-left: 46px;
}
.flexRow .description {
margin-left: 10px;
margin-left: 30px;
flex: 1;
color: #CDCDCD;
}
@ -47,33 +54,32 @@ class AccountCertification extends Component {
width: 100px;
color: #28AC7F;
}
.borderBottom {
border-bottom: 1px solid #4CACFF;
}
`}</style>
<div className="title">认证信息</div>
<div className="flexTable">
<div className="flexRow">
<div className="flexRow lineh-20 mb20">
<div className="name">实名认证</div>
<div className="description">有些课程需要实名认证才能加入哟还能获得500金币的奖励~ </div>
<div className="status">
{/* showRealNameCertificationModal */}
<WordsBtn style="blue" className="borderBottom"
onClick={this.showRealNameCertificationModal}
>立即认证</WordsBtn>
@
<span>已认证</span>
{
basicInfo && basicInfo.authentication =="uncertified" ?
<WordsBtn style="blue" className="borderBottom" onClick={()=>this.showRealNameCertificationModal(1)} >立即认证</WordsBtn>:
basicInfo && basicInfo.authentication =="applying" ? <span style={{color: '#FF6800'}}>待审核</span>:
<span><i className="iconfont icon-wancheng color-green font-16 mr3"></i></span>
}
</div>
</div>
<div className="flexRow">
<div className="flexRow lineh-20">
<div className="name">职业认证</div>
<div className="description">教师认证完毕之后可创建课堂发布实训免金币查看所有实训答案.. </div>
<div className="status">
@
<WordsBtn style="blue" className="borderBottom">立即认证</WordsBtn>
<span style={{color: '#FF6800'}}>待审核</span>
{
basicInfo && basicInfo.professional_certification =="uncertified" ?
<WordsBtn style="blue" className="borderBottom" onClick={()=>this.showRealNameCertificationModal(2)} >立即认证</WordsBtn>:
basicInfo && basicInfo.professional_certification =="applying" ? <span style={{color: '#FF6800'}}>待审核</span>:
<span><i className="iconfont icon-wancheng color-green font-16 mr3"></i></span>
}
</div>
</div>
</div>

@ -1,12 +1,15 @@
import React, { Component } from 'react';
import { SnackbarHOC, getImageUrl } from 'educoder';
import ChangeHeaderPicModal from './ChangeHeaderPicModal'
class AccountNav extends Component {
editImg = () => {
this.refs['picModal'].setVisible(true)
}
render() {
// newMain clearfix
return (
<div className="headphoto mt14">
<ChangeHeaderPicModal {...this.props} ref="picModal"></ChangeHeaderPicModal>
<style>{`
/*
.headphoto {
@ -44,7 +47,7 @@ class AccountNav extends Component {
display: block;
}
`}</style>
<img alt="头像" id="user_avatar_show" nhname="avatar_image" src="https://www.educoder.net/images/avatars/User/b?1532489442"></img>
<img alt="头像" id="user_avatar_show" nhname="avatar_image" src={`${getImageUrl("images/"+this.props.src)}`}></img>
<p className="headphoto-black" onClick={this.editImg} >修改头像</p>
</div>
);

@ -13,87 +13,45 @@ class AccountNav extends Component {
this.props.history.push(`/account/secure`)
}
render() {
let { basicInfo } = this.props
console.log(this.props);
const path = window.location.pathname
const isBasic = path.indexOf('basic') != -1 || path == "/account"
const isCertification = path.indexOf('certification') != -1
const isSecure = path.indexOf('secure') != -1
return (
<div className="accountNav">
<style>{`
.accountNav {
width: 290px;
box-shadow: 0px 4px 9px 0px rgba(11,62,120,0.21);
border-radius: 2px;
padding-top: 8px;
padding-bottom: 32px;
margin: 20px;
}
.accountInfo {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.accountInfo .name {
color: #05101A;
font-size: 24px;
height: 36px;
}
.accountInfo .role {
color: #666666;
font-size: 14px;
}
.accountManagement {
}
.accountManagement .title {
color: #05101A;
font-size: 18px;
font-weight: bold;
padding: 10px 28px;
margin-top: 6px;
}
.accountManagement .navItem {
font-size: 16px;
padding: 6px 0px;
padding-left: 30px;
border-left: 2px solid #fff;
cursor: pointer;
}
.accountManagement .navItem i{
margin-top: -4px;
display: inline-block;
margin-right: 3px;
}
.accountManagement .navItem i.status{
margin-top: 1px;
margin-right: 24px;
}
.accountManagement .navItem.active {
border-left: 2px solid #4CACFF;
background: #E6F3FF;
}
`}</style>
<div className="accountNav fl">
<div className="accountInfo">
<AccountImg></AccountImg>
<span className="name">莎莎</span>
<span className="role">管理员</span>
<AccountImg src={basicInfo && basicInfo.avatar_url}></AccountImg>
<span className="name">{basicInfo && basicInfo.name}</span>
<span className="role">{basicInfo && basicInfo.technical_title}</span>
</div>
<div className="accountManagement">
<div className="title">账号管理</div>
<ul>
<li className={`navItem ${isBasic ? 'active' : ''}`} onClick={this.toBasic}>
<i className="iconfont icon-dianzan color-grey-9 font-16"></i>
<i className="iconfont icon-jibenxinxi color-grey-9 font-16"></i>
基本信息
<i className="status fr iconfont icon-dianzan color-grey-9 font-16"></i>
{
basicInfo && (basicInfo.authentication == 'uncertified' || basicInfo.authentication == 'applying') &&
<i className="status fr iconfont icon-tishi color-red font-16"></i>
}
{
basicInfo && basicInfo.authentication == 'certified' &&
<i className="status fr iconfont icon-wancheng color-green-light font-16"></i>
}
</li>
<li className={`navItem ${isCertification ? 'active' : ''}`} onClick={this.toCertification}>
<i className="iconfont icon-dianzan color-grey-9 font-16"></i>
<i className="iconfont icon-renzhengxinxi color-grey-9 font-16"></i>
{
basicInfo && basicInfo.professional_certification == 'certified' && basicInfo.authentication == 'certified' ?
<i className="status fr iconfont icon-wancheng color-green-light font-16"></i>:
<i className="status fr iconfont icon-tishi color-red font-16"></i>
}
</li>
<li className={`navItem ${isSecure ? 'active' : ''}`} onClick={this.toSecure}>
<i className="iconfont icon-dianzan color-grey-9 font-16"></i>
<i className="iconfont icon-anquanshezhi color-grey-9 font-16"></i>
</li>
</ul>
</div>

@ -5,9 +5,24 @@ import { Form, Button, Input } from 'antd'
import '../../courses/css/Courses.css'
import './common.css'
import axios from 'axios'
const PHONE = 'PHONE'
const EMAIL = 'EMAIL'
const PASSWORD = 'PASSWORD'
function regPhoneAndEmail(value){
if(value.indexOf("@")>-1){
// 加密邮箱
let beforeStr=value.split("@")[0];
let afterStr=value.split("@")[1];
return beforeStr.substr(0,3)+"**"+beforeStr.substr(beforeStr.length-1,1)+"@"+afterStr;
}else{
// 加密手机号码
return value.substr(0,3)+"****"+value.substr(7,4);
}
}
class AccountSecure extends Component {
constructor (props) {
super(props)
@ -15,10 +30,41 @@ class AccountSecure extends Component {
updating: ''
}
}
// 获取验证码
getCode=(index)=>{
let url=`/account/get_verification_code.json`
if(index == 3){
//绑定手机号码
let values=this.props.form.getFieldsValue();
console.log(values);
}
}
onPhoneSubmit = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
let {login}=this.props.current_user;
let reg=/^1\d{10}$/;
if(reg.test(values.phone)){
let url=`/users/accounts/${login}/phone_bind.json`
axios.post((url),{
phone:values.phone,
code:values.phoneValidateCode
}).then((result)=>{
if(result){
this.props.showNotification("手机号码绑定成功!");
this.setState({
updating:''
})
this.props.getBasicInfo();
}
}).catch((error)=>{
console.log(error);
})
}else{
this.props.showNotification("请输入有效的11位手机号码");
}
}
})
}
@ -36,7 +82,16 @@ class AccountSecure extends Component {
}
})
}
//取消编辑
hideUpdating=()=>{
this.setState({
updating:""
})
}
render() {
let {basicInfo}=this.props;
const { getFieldDecorator } = this.props.form;
const { updating } = this.state
return (
@ -70,7 +125,6 @@ class AccountSecure extends Component {
text-align: right;
}
.flexTable .flexTable {
padding-bottom: 24px;
border-bottom: 1px solid #EBEBEB;
}
@ -94,6 +148,12 @@ class AccountSecure extends Component {
.settingForm .ant-form-item-label {
width: 204px;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-17px;
left:0px;
width:100%;
}
`}</style>
<div className="title">安全设置</div>
<Form>
@ -101,25 +161,30 @@ class AccountSecure extends Component {
<div className="flexTable">
<div className="flexRow">
<div className="name">手机</div>
{/* #EA320E
仅自己可见可用于手机号码登录EduCoder
*/}
<div className="description">
<span style={{color: '#EA320E'}}>未绑定</span>
{
basicInfo && basicInfo.phone ?
<span>{ regPhoneAndEmail(basicInfo.phone) }</span>
:
<span style={{color: '#EA320E'}}>未绑定</span>
}
绑定手机号码将获得500金币的奖励哟手机号码仅自己可见~
</div>
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: PHONE})}
>立即绑定</WordsBtn>
</div>
{
updating != PHONE &&
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: PHONE})}
>{basicInfo && basicInfo.phone ? "更换" : "立即绑定" }</WordsBtn>
</div>
}
</div>
{ updating == PHONE &&
<React.Fragment>
<Form.Item
label="你的手机号"
className="mt15 formItemInline hideRequireTag mb0"
className="formItemInline hideRequireTag mb20"
>
{getFieldDecorator('phone', {
rules: [{
@ -134,7 +199,7 @@ class AccountSecure extends Component {
<Form.Item
label="手机验证码"
className="mt15 formItemInline hideRequireTag"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('phoneValidateCode', {
rules: [{
@ -145,12 +210,12 @@ class AccountSecure extends Component {
})(
<Input placeholder="请输入手机获取的验证码" className="validateInput"></Input>
)}
<Button type="primary">获取验证码</Button>
<Button type="primary" onClick={()=>this.getCode(3)}>获取验证码</Button>
</Form.Item>
<div style={{ marginLeft: '118px' }}>
<div className="mb20" style={{ marginLeft: '118px' }}>
<Button type="primary" onClick={this.onPhoneSubmit}>确定</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}}>取消</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}} onClick={this.hideUpdating}>取消</Button>
</div>
</React.Fragment> }
</div>
@ -159,21 +224,29 @@ class AccountSecure extends Component {
<div className="flexRow">
<div className="name">邮箱</div>
<div className="description">
<span>kuc***w@126.com</span>
{
basicInfo && basicInfo.mail ?
<span>{ regPhoneAndEmail(basicInfo.mail) }</span>
:
<span style={{color: '#EA320E'}}>未绑定</span>
}
邮箱账号仅自己可见可用于邮箱账号登录EduCoder
</div>
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: EMAIL})}
>更换</WordsBtn>
</div>
{
updating != EMAIL &&
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: EMAIL})}
>{basicInfo && basicInfo.mail ?"更换":"立即绑定"}</WordsBtn>
</div>
}
</div>
{ updating == EMAIL &&
<React.Fragment>
<Form.Item
label="邮箱地址"
className="mt15 formItemInline hideRequireTag mb0"
className="formItemInline hideRequireTag mb20"
>
{getFieldDecorator('phone', {
rules: [{
@ -188,7 +261,7 @@ class AccountSecure extends Component {
<Form.Item
label="邮箱验证码"
className="mt15 formItemInline hideRequireTag"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('phoneValidateCode', {
rules: [{
@ -202,9 +275,9 @@ class AccountSecure extends Component {
<Button type="primary">获取验证码</Button>
</Form.Item>
<div style={{ marginLeft: '118px' }}>
<Button type="primary">确定</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}}>取消</Button>
<div className="mb20" style={{ marginLeft: '118px' }}>
<Button type="primary" onClick={this.onEmailSubmit}>确定</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}} onClick={this.hideUpdating}>取消</Button>
</div>
</React.Fragment> }
@ -218,18 +291,21 @@ class AccountSecure extends Component {
<span>**********</span>
用于保护账户信息和登录安全
</div>
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: PASSWORD})}
>修改</WordsBtn>
</div>
{
updating != PASSWORD &&
<div className="status">
<WordsBtn style="blue" className="borderBottom"
onClick={() => this.setState({updating: PASSWORD})}
>修改</WordsBtn>
</div>
}
</div>
{ updating == PASSWORD &&
<React.Fragment>
<Form.Item
label="旧密码"
className="mt15 formItemInline hideRequireTag mb0"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('p_old', {
rules: [{
@ -244,7 +320,7 @@ class AccountSecure extends Component {
<Form.Item
label="新密码"
className="mt15 formItemInline hideRequireTag mb0"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('p_new', {
rules: [{
@ -259,7 +335,7 @@ class AccountSecure extends Component {
<Form.Item
label="再次输入"
className="mt15 formItemInline hideRequireTag"
className="mb20 formItemInline hideRequireTag"
>
{getFieldDecorator('p_again', {
rules: [{
@ -272,9 +348,9 @@ class AccountSecure extends Component {
)}
</Form.Item>
<div style={{ marginLeft: '118px' }}>
<div className="mb20" style={{ marginLeft: '118px' }}>
<Button type="primary" onClick={this.onPasswordSubmit}>确定</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}}>取消</Button>
<Button type="primary grayBtn" style={{ marginLeft: '20px'}} onClick={this.hideUpdating}>取消</Button>
</div>
</React.Fragment> }
</div>

@ -0,0 +1,166 @@
import React, { Component } from "react";
import { Modal } from "antd";
import axios from 'axios'
import ModalWrapper from "../../courses/common/ModalWrapper"
import { Cropper } from 'educoder'
const imageId = 'changeHeaderPic'
const previewId = 'changeHeader_imagePreview'
let uploadedImageType;
let uploadedImageName;
let uploadedImageURL;
class ChangeHeaderPicModal extends Component{
constructor(props){
super(props);
this.state={
}
}
init = () => {
var inputImage = document.getElementById('inputImage');
const that = this;
inputImage.onchange = function () {
var files = this.files;
var file;
// cropper &&
if (files && files.length) {
file = files[0];
if (/^image\/\w+/.test(file.type)) {
uploadedImageType = file.type;
uploadedImageName = file.name;
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
const image = document.getElementById( imageId );
image.src = uploadedImageURL = URL.createObjectURL(file);
that.refs['cropper'].renew(image)
// cropper.destroy();
// cropper = new Cropper(image, options);
inputImage.value = null;
} else {
this.props.showNotification && this.props.showNotification("请选择一个图片格式的文件")
// window.alert('Please choose an image file.');
}
}
};
}
componentDidMount() {
}
setVisible = (visible) => {
this.refs['modalWrapper'].setVisible(visible)
if (visible) {
setTimeout(() => {
this.init()
}, 300)
}
}
onSendOk = () => {
}
onOk = () => {
var img_lg = document.getElementById(previewId);
// 截图小的显示框内的内容
window.html2canvas(img_lg).then((canvas) => {
var dataUrl = canvas.toDataURL("image/jpeg");
console.log(dataUrl)
const url = `/users/accounts/${this.props.userLogin || 'kosasa'}/avatar.json`
axios.put(url, {
image: dataUrl
})
.then((response) => {
// {"status":0,"message":"success","avatar_url":"avatars/User/15739"}
if (response.data.status == 0) {
this.props.showNotification && this.props.showNotification("修改头像成功")
this.setVisible(false)
}
})
.catch(function (error) {
console.log(error);
});
});
}
render(){
const { course_lists } = this.state
const { moduleName } = this.props
return(
<ModalWrapper
ref="modalWrapper"
title={`上传头像`}
{...this.props }
onOk={this.onOk}
okText="保存"
width={552}
className="changeHeaderModal"
>
<style>{`
#changeHeader_imagePreview {
overflow: hidden;
background-color: #fff;
border-radius: 50%;
text-align: center;
width: 120px;
height: 120px;
}
.previewWrap {
flex-direction: column;
justify-content: space-between;
height: 320px;
align-items: center;
margin-left: 36px;
}
.changeHeaderModal .tip {
color: #9B9B9B;
}
.previewWrap .tip {
text-align: center;
margin-top: 2px;
}
#uploadBtn {
color: #4CACFF;
border: 1px solid #4CACFF;
padding: 2px 18px;
cursor: pointer;
}
`}</style>
<div className="df">
<div>
<Cropper
ref="cropper"
imageId={imageId}
previewId="changeHeader_imagePreview"
width={320} height={320}
></Cropper>
<span className="tip">仅支持JPGGIFPNG且文件小于2M</span>
</div>
<div
className="df previewWrap" style ={{flexDirection: 'column'}}
>
<div>
<div id="changeHeader_imagePreview"></div>
<div className="tip">头像预览</div>
</div>
<label id="uploadBtn" for="inputImage">
<input type="file" class="sr-only" id="inputImage" name="file" accept="image/*"></input>
重新上传
</label>
</div>
</div>
</ModalWrapper>
)
}
}
export default ChangeHeaderPicModal;

@ -1,9 +1,10 @@
.basicForm {
background: #fff;
padding: 30px;
width: 930px;
margin: 20px;
margin-bottom: 10px;
box-sizing: border-box;
width: 100%;
min-height: 390px;
}
.basicForm .title {
font-size: 16px;
@ -17,7 +18,10 @@
.flexRow {
display: flex;
}
.color-green-light{
color: #45E660!important;
}
.mb15{margin-bottom: 15px!important;}
/* BUTTOn */
.ant-btn {
border-radius: 2px;
@ -27,7 +31,7 @@ button.ant-btn.ant-btn-primary.grayBtn {
border-color: #CBCBCB;
}
.borderBottom {
border-bottom: 2px solid #4CACFF;
border-bottom: 1px solid #4CACFF;
}
/* form ---------------- START */
@ -41,11 +45,72 @@ button.ant-btn.ant-btn-primary.grayBtn {
display: none;
}
.basicFormWrap{
flex:1;
width: 0;
}
/* .basicForm .ant-form-item-label {
width: 100px;
padding-right: 10px;
}
.basicForm .ant-form-item-label label {
color: #979797
} */
} */
/* 左侧 */
.accountNav {
width: 290px;
box-shadow: 0px 4px 9px 0px rgba(11,62,120,0.21);
border-radius: 2px;
padding-top: 8px;
padding-bottom: 30px;
margin-bottom:30px;
margin-right:20px;
max-height:430px;
}
.accountInfo {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.accountInfo .name {
color: #05101A;
font-size: 24px;
height: 36px;
}
.accountInfo .role {
color: #666666;
font-size: 14px;
}
.accountManagement .title {
color: #05101A;
font-size: 18px;
font-weight: 400;
padding: 10px 28px;
margin-top: 6px;
}
.accountManagement .navItem {
font-size: 16px;
padding: 6px 0px;
padding-left: 30px;
border-left: 2px solid #fff;
cursor: pointer;
color:#4D4D4D;
}
.accountManagement .navItem i{
margin-top: -4px;
display: inline-block;
margin-right: 7px;
}
.accountManagement .navItem i.status{
margin-top: 1px;
margin-right: 24px;
}
.accountManagement .navItem.active {
border-left: 2px solid #4CACFF;
background: #E6F3FF;
}
.accountManagement .navItem.active i:first-child{
color:#4CACFF!important;
}

@ -15,16 +15,47 @@ class ApplyForAddChildOrgModal extends Component{
}
}
componentDidMount() {
componentDidUpdate=(prevState)=>{
if(this.props.departmentName && prevState.departmentName != this.props.departmentName){
this.setValue(this.props.departmentName)
}
}
componentDidMount=()=>{
if(this.props.departmentName){
this.setValue(this.props.departmentName)
}
}
setValue=(name)=>{
this.props.form.setFieldsValue({
depart:name
})
}
setVisible = (visible) => {
this.refs.modalWrapper.setVisible(visible)
}
onSendOk = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
console.log(values);
if(!err){
let{schoolId,departmentName}=this.props
let url=`/add_department_applies.json`;
axios.post(url,{
name:departmentName,
school_id:schoolId,
remarks:values.desc
}).then((result)=>{
if(result){
this.props.showNotification("新增院系/部门成功!");
this.setVisible(false);
}
}).catch((error)=>{
console.log(error);
})
}
})
}
onOk = () => {
@ -43,17 +74,17 @@ class ApplyForAddChildOrgModal extends Component{
{...this.props }
onOk={this.onOk}
okText="保存"
className="modalForm"
className="applyForModal"
>
<style>{`
.modalForm .ant-form-item-label {
.applyForModal .ant-form-item-label {
width: 100px;
padding-right: 10px;
}
.modalForm .ant-form-item-label label {
.applyForModal .ant-form-item-label label {
color: #979797
}
.formItemInline .ant-form-item-control-wrapper {
.applyForModal .formItemInline .ant-form-item-control-wrapper {
width: 390px;
}
`}</style>
@ -62,21 +93,21 @@ class ApplyForAddChildOrgModal extends Component{
label="单位名称:"
className="mt15 formItemInline hideRequireTag"
>
国防科学技术大学
{this.props.schoolName}
</Form.Item>
<Form.Item
label="部门名称:"
className="mt15 formItemInline"
>
{getFieldDecorator('re', {
{getFieldDecorator('depart', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入部门名称',
}],
})(
<Input ></Input>
<Input placeholder="请输入部门或者学院名称" ></Input>
)}
</Form.Item>

@ -15,20 +15,49 @@ class ApplyForAddOrgModal extends Component{
}
}
componentDidMount() {
componentDidUpdate=(prevState)=>{
if(this.props.schoolName && prevState.schoolName != this.props.schoolName){
this.props.form.setFieldsValue({
schoolName:this.props.schoolName
})
}
}
componentDidMount=()=>{
if(this.props.schoolName){
this.props.form.setFieldsValue({
schoolName:this.props.schoolName
})
}
}
setVisible = (visible) => {
this.refs.modalWrapper.setVisible(visible)
}
onSendOk = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
console.log(values);
if(!err){
let url=`/add_school_applies.json`;
axios.post(url,{
schoolName:values.name,
province:values.city[0],
city:values.city[1],
address:values.address,
remarks:values.remarks
}).then((result)=>{
if(result){
this.props.showNotification("新增学校/单位成功!");
this.setVisible(false);
}
}).catch((error)=>{
console.log(error);
})
}
})
}
onOk = () => {
const { course_lists, checkBoxValues } = this.state
this.onSendOk()
}
@ -43,26 +72,36 @@ class ApplyForAddOrgModal extends Component{
{...this.props }
onOk={this.onOk}
okText="保存"
className="modalForm"
className="applyForModal"
>
<style>{`
.modalForm .ant-form-item-label {
.applyForModal .ant-form-item-label {
width: 100px;
padding-right: 10px;
}
.modalForm .ant-form-item-label label {
.applyForModal .ant-form-item-label label {
color: #979797
}
.formItemInline .ant-form-item-control-wrapper {
.applyForModal .formItemInline .ant-form-item-control-wrapper{
width: 390px;
}
.applyForModal .formItemInline .ant-form-item-control .ant-cascader-picker,.applyForModal .formItemInline .ant-cascader-picker-large .ant-input{
width: 100%;
height:32px!important;
}
.applyForModal .formItemInline .ant-input-lg{
font-size:14px!important;
}
.explain .ant-form-explain{
top:36px;
}
`}</style>
<Form>
<Form onSubmit={this.onOk}>
<Form.Item
label="单位全称:"
className="mt15 formItemInline hideRequireTag"
className="mt15 formItemInline explain"
>
{getFieldDecorator('orgName', {
{getFieldDecorator('schoolName', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
@ -71,17 +110,18 @@ class ApplyForAddOrgModal extends Component{
})(
<Input placeholder="学校或工作单位" className="validateInput"></Input>
)}
<div>
<div style={{ height: '22px'}}>
<span>示例</span>
<i className="iconfont icon-dianzan color-grey-9 font-16"></i>
<span> 国防科学技术大学</span>
</div>
<div style={{ height: '22px'}}>
<span>   </span>
<i className="iconfont icon-dianzan color-grey-9 font-16"></i>
<span> 国防科学技术大学四方坪校区</span>
</div>
<div className="df mt18">
<li style={{lineHeight:"22px"}}>示例</li>
<ul style={{lineHeight:"22px"}}>
<li>
<i className="iconfont icon-chenggong color-green-light font-14 ml2 mr5 fl"></i>
<span> 国防科学技术大学</span>
</li>
<li>
<i className="iconfont icon-htmal5icon19 font-18 fl mr4" style={{color:"#FF9348"}}></i>
<span> 国防科学技术大学开福校区</span>
</li>
</ul>
</div>
</Form.Item>
@ -89,12 +129,8 @@ class ApplyForAddOrgModal extends Component{
label="地区:"
className="mt15 formItemInline hideRequireTag"
>
{getFieldDecorator('re', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请选择地区',
}],
{getFieldDecorator('city', {
rules: [],
})(
<City ></City>
)}
@ -104,12 +140,8 @@ class ApplyForAddOrgModal extends Component{
label="详细地址:"
className="mt15 formItemInline hideRequireTag"
>
{getFieldDecorator('addr', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请填写完整的地址信息',
}],
{getFieldDecorator('address', {
rules: [],
})(
<Input placeholder="请填写完整的地址信息" className="validateInput"></Input>
)}
@ -119,7 +151,7 @@ class ApplyForAddOrgModal extends Component{
label="说明:"
className="mt15 formItemInline hideRequireTag"
>
{getFieldDecorator('desc', {
{getFieldDecorator('remarks', {
})(
<TextArea placeholder="再次说明特别情况(选填)" className="validateInput"></TextArea>
)}

@ -2,9 +2,12 @@ import React, { Component } from "react";
import { message, Icon, Input, Form, Upload} from "antd";
import axios from 'axios'
import ModalWrapper from "../../courses/common/ModalWrapper"
import { City, getUploadActionUrl } from 'educoder'
import { City, getUploadActionUrl,getImageUrl } from 'educoder'
import '../account/common.css'
import authImg from '../../../images/account/auth.png'
import jobImg from '../../../images/account/job.png'
const { TextArea } = Input;
const Dragger = Upload.Dragger;
function getBase64(img, callback) {
@ -39,8 +42,17 @@ class RealNameCertificationModal extends Component{
}
onSendOk = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
console.log(values);
if(!err){
let{imageUrl2}=this.state;
if(imageUrl2){
}else{
this.props.showNotification("请先上传照片!");
}
}
})
}
onOk = () => {
@ -96,16 +108,21 @@ class RealNameCertificationModal extends Component{
className: 'idPic-uploader',
onChange: this.handleChange2,
};
let {certification}=this.props;
return(
<ModalWrapper
ref="modalWrapper"
title={`实名认证`}
title={
certification && certification==1?
<span><i className="iconfont icon-shenfenrenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span>:
<span><i className="iconfont icon-zhiyerenzheng font-18 color-blue mr5" style={{fontWeight:"normal"}}></i></span>
}
{...this.props }
onOk={this.onOk}
okText="保存"
className="modalForm"
className="applyForModal certificationModal"
bottomRender={
certification && certification == 1?
<div className="bottomRender">
<p>认证须知</p>
<p>
@ -121,29 +138,45 @@ class RealNameCertificationModal extends Component{
</p><p>
6.如存在恶意乱填写姓名证件号及上传与实名认证证件无关图片者一经发现将冻结EduCoder账号
</p>
</div>:
<div className="bottomRender">
<p>认证须知</p>
<p>
1.根据职业上传相应的证件照教师教师证专业人士员工证学生学生证请确保证件照内容完整并且清晰可见严禁PS
</p><p>
2.我们将在你提交职业证信息后的24小时不包含节假日内完成审核审核结果将会以系统消息的形式发送给你
</p><p>
3.职业认证审核完成后无法删除请谨慎填写职业变更请选择重新认证
</p><p>
4.职业认证审核完成后系统将自动发放500个金币作为奖励
</p><p>
5.我们会确保你所提供的信息均处于严格的保密状态不会泄露
</p><p>
6.如存在恶意乱填写姓名学号及上传与职业证件无关图片者一经发现将冻结EduCoder账号
</p>
</div>
}
>
}
>
<style>{`
.modalForm .ant-form-item-label {
.applyForModal .ant-form-item{
margin-bottom:15px;
}
.applyForModal .ant-form-item-label {
width: 100px;
padding-right: 10px;
}
.modalForm .ant-form-item-label label {
.applyForModal .ant-form-item-label label {
color: #979797
}
.formItemInline .ant-form-item-control-wrapper {
width: 390px;
.certificationModal .ant-modal-body{
padding:20px;
}
.certificationModal .formItemInline .ant-form-item-control-wrapper {
width: 448px;
}
span.idPic-uploader {
display: inline-block;
padding: 20px;
padding-bottom: 0px;
width: 160px;
height: 110px;
margin: 0 16px;
margin-right:20px;
height:110px;
}
.idPic-uploader > .ant-upload {
width: 160px;
@ -152,78 +185,80 @@ class RealNameCertificationModal extends Component{
.idPic-uploader .ant-upload.ant-upload-drag p.ant-upload-drag-icon {
margin-bottom: 0px;
}
.idPic-uploader .ant-upload.ant-upload-drag p.ant-upload-text {
.idPic-uploader .ant-upload.ant-upload-drag p.ant-upload-drag-icon i{
font-size:42px!important;
color:#4B667F
}
.idPic-uploader .ant-upload.ant-upload-drag p.ant-upload-text a{
font-size: 12px;
color:#4B667F;
border-bottom:1px solid #4B667F
}
.idPic-uploader .ant-upload.ant-upload-drag {
padding: 0px
padding: 0px;
border:1px solid rgba(218,218,218,1)!important;
}
.idPic-uploader img {
max-height: 110px;
width: 160px;
width:100%
}
.first_uploader {
margin-left: 42px;
}
.certificationModal .marginauto{
margin-top:20px!important;
}
.bottomRender {
padding: 19px;
background: rgb(245,245,245);
margin-top: 30px;
margin-top: 20px;
color: #656565;
}
span.idPic-uploader.demoImg {
display: flex;
flex-direction: column;
width:160px;
background:rgba(240,240,240,1);
border:1px solid rgba(218,218,218,1);
border-radius:4px;
padding:0px 5px;
justify-content: center;
align-items: center;
display: -webkit-flex;
}
.formItemInline .ant-form-explain{
position:absolute;
bottom:-20px;
left:0px;
width:100%;
}
`}</style>
<Form>
<Form.Item
label="证件号:"
className="mt15 formItemInline"
>
{getFieldDecorator('re', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入证件号',
}],
})(
<Input placeholder="请输入证件号" ></Input>
)}
</Form.Item>
{/* */}
<Form onSubmit={this.handleSubmit}>
{
certification && certification ==1 &&
<Form.Item
label="证件号:"
className="formItemInline"
>
{getFieldDecorator('credentials', {
rules: [{
// initialValue: this.state.cityDefaultValue,
required: true,
message: '请输入证件号',
}],
})(
<Input placeholder="请输入证件号" ></Input>
)}
</Form.Item>
}
<div style={{ marginLeft: '18px' }}>
<div>
<span style={{color: '#999999'}}>身份证人像面上传</span>
<span style={{color: '#999999'}}>{ certification && certification == 1 ? "身份证(人像面)上传":"职业证照片上传" }</span>
<span style={{color: '#FF6800'}}>png/jpg/bmp格式不超过2MB</span>
</div>
<div
style={{ display: 'flex', justifyContent: 'center', width: '94%', height: '140px' }}
>
<div className="df mt20" style={{ justifyContent: 'center' }} >
<span className="idPic-uploader demoImg">
<img src={"https://www.educoder.net/images/avatars/User/b?1532489442"} alt="avatar" style={{ maxHeight: '110px'}}/>
<span style={{color: '#999999'}}>示例图片</span>
<img src={`${certification == 1 ? authImg : jobImg}`} alt="avatar" style={{ maxHeight: '110px'}}/>
</span>
{/* <Dragger {...uploadProps} >
{imageUrl ?
<a href={imageUrl} target="_blank">
<img src={imageUrl} alt="avatar" style={{ maxHeight: '110px'}}/>
</a> :
<React.Fragment>
<p className="ant-upload-drag-icon">
<Icon type="inbox" />
</p>
<p className="ant-upload-text">点击或拖拽上传图片</p>
</React.Fragment>
}
</Dragger> */}
<Dragger {...uploadProps2}>
{imageUrl2 ?
<a href={imageUrl2} target="_blank">
@ -231,14 +266,20 @@ class RealNameCertificationModal extends Component{
</a> :
<React.Fragment>
<p className="ant-upload-drag-icon">
<Icon type="inbox" />
<i className="iconfont icon-cuban2shangchuanyunduan" style={{color:"#4B667F",font:"42px"}}></i>
</p>
<p className="ant-upload-text">点击或拖拽上传图片</p>
<p className="ant-upload-text mt20"><a>点击或拖拽上传图片</a></p>
{/* <p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files</p> */}
</React.Fragment>
}
</Dragger>
</div>
<div className="df mt10 color-grey-9" style={{ justifyContent: 'center' }} >
<span className="fl mr20 edu-txt-center" style={{width:"160px"}}>示例图片</span>
<span className="fl edu-txt-center mr20" style={{width:"160px"}}>
<a href="javascript:void(0)" className="color-orange" style={{borderBottom:"1px solid #ff6800"}}>查看大图</a>
</span>
</div>
</div>

@ -6,7 +6,7 @@ import Loadable from 'react-loadable';
import Loading from '../../../Loading';
import NoneData from '../../courses/coursesPublic/NoneData'
import axios from 'axios';
import {getImageUrl} from 'educoder';
import {getImageUrl,setImagesUrl} from 'educoder';
import { TPMIndexHOC } from '../../tpm/TPMIndexHOC';
import { CNotificationHOC } from '../../courses/common/CNotificationHOC'
import "./usersInfo.css"
@ -159,7 +159,7 @@ class InfosPath extends Component{
return(
<div className="square-Item" onClick={()=>this.turnToCourses(`/paths/${item.id}`)}>
{
item.tag && <div className="tag-green"><span className="tag-name">{item.tag}</span><img src={getImageUrl("/images/educoder/tag2.png")}/></div>
item.tag && <div className="tag-green"><span className="tag-name">{item.tag}</span><img src={setImagesUrl("images/educoder/tag2.png")} className="fl"/></div>
}
<a href="javascript:void(0)" className="square-img"><img alt="Subject12" src={getImageUrl(`${item.image_url}`)}/></a>
<div className="square-main">

Loading…
Cancel
Save