资助激励功能合并 #2
|
|
@ -86,3 +86,4 @@ typings/
|
|||
|
||||
.DS_Store
|
||||
.idea/*
|
||||
.forgeplus-react.sublime-workspace
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,317 @@
|
|||
{
|
||||
"auto_complete":
|
||||
{
|
||||
"selected_items":
|
||||
[
|
||||
[
|
||||
"samp",
|
||||
"samp2_method"
|
||||
],
|
||||
[
|
||||
"modu",
|
||||
"module_method"
|
||||
],
|
||||
[
|
||||
"cu",
|
||||
"currentTerm"
|
||||
],
|
||||
[
|
||||
"req",
|
||||
"requestVote"
|
||||
],
|
||||
[
|
||||
"reque",
|
||||
"RequestVote"
|
||||
],
|
||||
[
|
||||
"App",
|
||||
"AppendEntries"
|
||||
],
|
||||
[
|
||||
"hea",
|
||||
"heartBeatInterval"
|
||||
],
|
||||
[
|
||||
"time",
|
||||
"timeOut"
|
||||
],
|
||||
[
|
||||
"ele",
|
||||
"electionTimeout"
|
||||
],
|
||||
[
|
||||
"R",
|
||||
"Raft"
|
||||
],
|
||||
[
|
||||
"vote",
|
||||
"votedFor"
|
||||
],
|
||||
[
|
||||
"Ra",
|
||||
"RaftState"
|
||||
],
|
||||
[
|
||||
"is",
|
||||
"isleader"
|
||||
]
|
||||
]
|
||||
},
|
||||
"buffers":
|
||||
[
|
||||
{
|
||||
"file": "src/redux/actions/actionTypes.js",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 5688,
|
||||
"encoding": "UTF-8",
|
||||
"line_ending": "Unix"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build_system": "",
|
||||
"build_system_choices":
|
||||
[
|
||||
],
|
||||
"build_varint": "",
|
||||
"command_palette":
|
||||
{
|
||||
"height": 0.0,
|
||||
"last_filter": "",
|
||||
"selected_items":
|
||||
[
|
||||
],
|
||||
"width": 0.0
|
||||
},
|
||||
"console":
|
||||
{
|
||||
"height": 171.0,
|
||||
"history":
|
||||
[
|
||||
"ls"
|
||||
]
|
||||
},
|
||||
"distraction_free":
|
||||
{
|
||||
"menu_visible": true,
|
||||
"show_minimap": false,
|
||||
"show_open_files": false,
|
||||
"show_tabs": false,
|
||||
"side_bar_visible": false,
|
||||
"status_bar_visible": false
|
||||
},
|
||||
"expanded_folders":
|
||||
[
|
||||
"/home/qyzh/new_trustie/forgeplus-react"
|
||||
],
|
||||
"file_history":
|
||||
[
|
||||
"/home/qyzh/OSS/forgeplus/app/models/user.rb",
|
||||
"/home/qyzh/OSS/forgeplus/db/structure.sql",
|
||||
"/home/qyzh/OSS/forgeplus/app/controllers/settings_controller.rb",
|
||||
"/home/qyzh/OSS/forgeplus/app/controllers/application_controller.rb",
|
||||
"/home/qyzh/OSS/Trustie/app/controllers/projects_controller.rb",
|
||||
"/home/qyzh/temp.sh",
|
||||
"/home/qyzh/OSS/Trustie/Gemfile",
|
||||
"/home/qyzh/.npm/_logs/2020-06-07T02_42_06_886Z-debug.log",
|
||||
"/home/qyzh/OSS/forgeplus/app/controllers/users_controller.rb",
|
||||
"/home/qyzh/OSS/forgeplus/app/controllers/accounts_controller.rb",
|
||||
"/home/qyzh/custom/conf/app.ini",
|
||||
"/home/qyzh/OSS/Trustie_old/Gemfile.lock",
|
||||
"/home/qyzh/OSS/Trustie/Gemfile.lock",
|
||||
"/home/qyzh/ruby_study/test.rb",
|
||||
"/home/qyzh/RubymineProjects/myblog/app/controller/users_controller.rb",
|
||||
"/home/qyzh/OSS/forgeplus/app/libs/limit_forbid_control.rb",
|
||||
"/home/qyzh/OSS/forgeplus/log/development.log",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/raft/raft.go",
|
||||
"/home/qyzh/OSS/forgeplus/config/application.rb",
|
||||
"/home/qyzh/RubymineProjects/demo/app/helpers/welcome_helper.rb",
|
||||
"/home/qyzh/RubymineProjects/demo/app/controllers/welcome_controller.rb",
|
||||
"/home/qyzh/RubymineProjects/demo/config/routes.rb",
|
||||
"/home/qyzh/RubymineProjects/demo/app/views/welcome/index.html.erb",
|
||||
"/home/qyzh/trustie/Gemfile",
|
||||
"/home/qyzh/trustie/Gemfile.lock",
|
||||
"/home/qyzh/ruby_study/test",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/labrpc/test_test.go",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/labrpc/labrpc.go",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/raft/test_test.go",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/raft/persister.go",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/raft/util.go",
|
||||
"/home/qyzh/NJU-DisSys-2017/src/raft/config.go"
|
||||
],
|
||||
"find":
|
||||
{
|
||||
"height": 29.0
|
||||
},
|
||||
"find_in_files":
|
||||
{
|
||||
"height": 0.0,
|
||||
"where_history":
|
||||
[
|
||||
]
|
||||
},
|
||||
"find_state":
|
||||
{
|
||||
"case_sensitive": true,
|
||||
"find_history":
|
||||
[
|
||||
"current_user",
|
||||
"user_set",
|
||||
"login",
|
||||
"platform",
|
||||
"Platform不包含于列表中",
|
||||
"find_by_",
|
||||
"find_by",
|
||||
"3.2.22",
|
||||
"bug",
|
||||
"persister",
|
||||
"currentTerm",
|
||||
"currentTern",
|
||||
"term",
|
||||
"your",
|
||||
"electionInterval",
|
||||
"your",
|
||||
"if",
|
||||
"your",
|
||||
"Persister",
|
||||
"make",
|
||||
"Your code here",
|
||||
"Call",
|
||||
"labrpc",
|
||||
"main"
|
||||
],
|
||||
"highlight": true,
|
||||
"in_selection": false,
|
||||
"preserve_case": false,
|
||||
"regex": false,
|
||||
"replace_history":
|
||||
[
|
||||
],
|
||||
"reverse": false,
|
||||
"show_context": true,
|
||||
"use_buffer2": true,
|
||||
"whole_word": false,
|
||||
"wrap": true
|
||||
},
|
||||
"groups":
|
||||
[
|
||||
{
|
||||
"selected": 0,
|
||||
"sheets":
|
||||
[
|
||||
{
|
||||
"buffer": 0,
|
||||
"file": "src/redux/actions/actionTypes.js",
|
||||
"semi_transient": false,
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 5688,
|
||||
"regions":
|
||||
{
|
||||
},
|
||||
"selection":
|
||||
[
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"syntax": "Packages/JavaScript/JavaScript.sublime-syntax",
|
||||
"tab_size": 2,
|
||||
"translate_tabs_to_spaces": true
|
||||
},
|
||||
"translation.x": 0.0,
|
||||
"translation.y": 0.0,
|
||||
"zoom_level": 1.0
|
||||
},
|
||||
"stack_index": 0,
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"incremental_find":
|
||||
{
|
||||
"height": 29.0
|
||||
},
|
||||
"input":
|
||||
{
|
||||
"height": 0.0
|
||||
},
|
||||
"layout":
|
||||
{
|
||||
"cells":
|
||||
[
|
||||
[
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cols":
|
||||
[
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"rows":
|
||||
[
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"menu_visible": true,
|
||||
"output.find_results":
|
||||
{
|
||||
"height": 0.0
|
||||
},
|
||||
"pinned_build_system": "",
|
||||
"project": "forgeplus-react.sublime-project",
|
||||
"replace":
|
||||
{
|
||||
"height": 54.0
|
||||
},
|
||||
"save_all_on_build": true,
|
||||
"select_file":
|
||||
{
|
||||
"height": 0.0,
|
||||
"last_filter": "",
|
||||
"selected_items":
|
||||
[
|
||||
],
|
||||
"width": 0.0
|
||||
},
|
||||
"select_project":
|
||||
{
|
||||
"height": 0.0,
|
||||
"last_filter": "",
|
||||
"selected_items":
|
||||
[
|
||||
],
|
||||
"width": 0.0
|
||||
},
|
||||
"select_symbol":
|
||||
{
|
||||
"height": 0.0,
|
||||
"last_filter": "",
|
||||
"selected_items":
|
||||
[
|
||||
],
|
||||
"width": 0.0
|
||||
},
|
||||
"selected_group": 0,
|
||||
"settings":
|
||||
{
|
||||
},
|
||||
"show_minimap": true,
|
||||
"show_open_files": false,
|
||||
"show_tabs": true,
|
||||
"side_bar_visible": true,
|
||||
"side_bar_width": 288.0,
|
||||
"status_bar_visible": true,
|
||||
"template_settings":
|
||||
{
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
|
|
@ -9,7 +9,7 @@
|
|||
"antd": "^3.26.15",
|
||||
"array-flatten": "^2.1.2",
|
||||
"autoprefixer": "7.1.6",
|
||||
"axios": "^0.18.1",
|
||||
"axios": "^0.21.1",
|
||||
"babel-eslint": "7.2.3",
|
||||
"babel-jest": "20.0.3",
|
||||
"babel-loader": "7.1.2",
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
"classnames": "^2.2.5",
|
||||
"clipboard": "^2.0.6",
|
||||
"code-prettify": "^0.1.0",
|
||||
"codemirror": "^5.53.0",
|
||||
"codemirror": "^5.61.0",
|
||||
"connected-react-router": "4.4.1",
|
||||
"css-loader": "^3.5.2",
|
||||
"dotenv": "4.0.0",
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
"jest": "20.0.4",
|
||||
"js-base64": "^2.5.2",
|
||||
"katex": "^0.11.1",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.6.8",
|
||||
"marked": "^1.0.0",
|
||||
"material-ui": "^1.0.0-beta.40",
|
||||
|
|
@ -74,6 +74,7 @@
|
|||
"rc-upload": "^2.9.4",
|
||||
"react": "^16.13.1",
|
||||
"react-beautiful-dnd": "^10.0.4",
|
||||
"react-charts": "^2.0.0-beta.7",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-codemirror2": "^6.0.1",
|
||||
"react-color": "^2.18.0",
|
||||
|
|
@ -93,6 +94,7 @@
|
|||
"react-router-dom": "^4.2.2",
|
||||
"react-split-pane": "^0.1.91",
|
||||
"react-url-query": "^1.5.0",
|
||||
"react-vis": "^1.11.7",
|
||||
"react-zmage": "^0.8.5-beta.31",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "2.3.0",
|
||||
|
|
@ -107,7 +109,7 @@
|
|||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"url-loader": "0.6.2",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"whatwg-fetch": "2.0.3",
|
||||
"wrap-md-editor": "^0.2.20"
|
||||
|
|
|
|||
23
src/App.js
23
src/App.js
|
|
@ -24,6 +24,7 @@ import { SnackbarHOC } from 'educoder'
|
|||
import { initAxiosInterceptors } from './AppConfig'
|
||||
import { Provider } from 'react-redux';
|
||||
import configureStore from './redux/stores/configureStore';
|
||||
import { load } from 'react-cookies';
|
||||
const store = configureStore();
|
||||
window.marked = marked;
|
||||
const theme = createMuiTheme({
|
||||
|
|
@ -70,6 +71,16 @@ const OrganizeIndex = Loadable({
|
|||
loader: () => import('./forge/Team/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
// Sponsor
|
||||
const Sponsor = Loadable({
|
||||
loader: () => import('./forge/sponsor/Sponsor'),
|
||||
loading: Loading,
|
||||
})
|
||||
// Sponsor Confirmation
|
||||
const SponsorConfirmation = Loadable({
|
||||
loader: () => import('./forge/sponsor/SponsorConfirmation'),
|
||||
loading: Loading,
|
||||
})
|
||||
const EducoderLogin = Loadable({
|
||||
loader: () => import('./modules/login/EducoderLogin'),
|
||||
loading: Loading,
|
||||
|
|
@ -260,7 +271,17 @@ class App extends Component {
|
|||
(props) => {
|
||||
return (<InfosIndex {...this.props} {...this.state} />)
|
||||
}
|
||||
}></Route>
|
||||
}></Route>
|
||||
<Route exact path="/sponsor_confirmation/:username/:tier_id"
|
||||
render={
|
||||
(props) => (<SponsorConfirmation {...this.props}{...this.state}></SponsorConfirmation>)
|
||||
}>
|
||||
</Route>
|
||||
<Route exact path="/sponsor/:username"
|
||||
render={
|
||||
(props) => (<Sponsor {...this.props}{...this.state}></Sponsor>)
|
||||
}>
|
||||
</Route>
|
||||
<Route exact path="/"
|
||||
render={
|
||||
(props) => (
|
||||
|
|
|
|||
|
|
@ -56,9 +56,10 @@ window._debugType = debugType;
|
|||
export function initAxiosInterceptors(props) {
|
||||
initOnlineOfflineListener()
|
||||
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
|
||||
var
|
||||
proxy = "http://localhost:3000";
|
||||
proxy = "https://testforgeplus.trustie.net";
|
||||
var
|
||||
// proxy = "http://172.27.144.138:3000/"
|
||||
proxy = "http://localhost:3000"
|
||||
// proxy = "https://testforgeplus.trustie.net"
|
||||
|
||||
const requestMap = {};
|
||||
window.setfalseInRequestMap = function (keyName) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
import React , { Component } from "react";
|
||||
import { Form , Input , Select,Divider,Button,Checkbox,Dropdown,Menu} from 'antd';
|
||||
import {Link} from 'react-router-dom';
|
||||
|
||||
import UploadComponent from '../Upload/Index';
|
||||
import '../Order/order.css';
|
||||
import './version.css';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
const Option = Select.Option;
|
||||
const TextArea = Input.TextArea;
|
||||
class NewVersion extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
branch_name:"",
|
||||
issue_tag_ids:"",
|
||||
fixed_version_id:"",
|
||||
issue_chosen:undefined,
|
||||
fileList:undefined,
|
||||
ischeck:undefined,
|
||||
pull:undefined,
|
||||
tag_name:'',
|
||||
data:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
this.getSelectList();
|
||||
}
|
||||
|
||||
getSelectList=()=>{
|
||||
const { projectsId,versionId} = this.props.match.params;
|
||||
const url = `/projects/${projectsId}/version_releases/${versionId}/edit.json`;
|
||||
axios.get(url).then((result)=>{
|
||||
if(result){
|
||||
this.setState({
|
||||
data:result.data,
|
||||
pull:result.data.target_commitish
|
||||
})
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//delete
|
||||
deleteversion=()=>{
|
||||
const { projectsId , versionId} = this.props.match.params;
|
||||
const url = `/projects/${projectsId}/version_releases/${versionId}.json`;
|
||||
axios.delete(url,{ data: {
|
||||
project_id: projectsId,
|
||||
id:versionId
|
||||
}
|
||||
}).then((result)=>{
|
||||
if(result){
|
||||
this.props.history.push(`/projects/${projectsId}/version`);
|
||||
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 创建
|
||||
handleSubmit=()=>{
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if(!err){
|
||||
const { projectsId,versionId} = this.props.match.params;
|
||||
const { pull,ischeck } = this.state;
|
||||
const url = `/projects/${projectsId}/version_releases/${versionId}.json`;
|
||||
// if(values.issue_type==="普通"){
|
||||
// values.issue_type="1"
|
||||
// }
|
||||
axios.put(url,{
|
||||
...values,
|
||||
tag_name:this.state.data&&this.state.data.tag_name,
|
||||
draft:false,
|
||||
prerelease:ischeck,
|
||||
target_commitish:pull
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
this.props.history.push(`/projects/${projectsId}/version`);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
RedieonChange=(e)=>{
|
||||
this.setState({
|
||||
ischeck:e.target.checked
|
||||
})
|
||||
}
|
||||
Preservation=()=>{
|
||||
alert(this.state.data.tag_name)
|
||||
}
|
||||
|
||||
renderMenu =(array,id)=>{
|
||||
return(
|
||||
<Menu>
|
||||
{
|
||||
array && array.length > 0 && array.map((item,key)=>{
|
||||
return(
|
||||
<Menu.Item key={item} onClick={()=>this.getOption(item)}>{item}</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
getOption=(name)=>{
|
||||
this.setState({
|
||||
pull:name
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
changmodelname=(e)=>{
|
||||
this.setState({
|
||||
tag_name:e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const { projectsId } = this.props.match.params;
|
||||
return(
|
||||
<div className="main">
|
||||
<Form>
|
||||
<h1 style={{marginLeft:15,marginTop:20}}>发布新版</h1>
|
||||
<h5 style={{marginLeft:15}}>版本发布组织项目的版本。</h5>
|
||||
<Divider/>
|
||||
<div style={{display:'flex',marginLeft:15}}>
|
||||
{this.state.data&&this.state.data.tag_name}@{this.state.data&&this.state.data.target_commitish}
|
||||
</div>
|
||||
<div style={{display:'flex'}}>
|
||||
<div className="versionmilepostleft">
|
||||
<h1>标题</h1>
|
||||
<div>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [{
|
||||
required: true, message: '请输入标题'
|
||||
}],
|
||||
initialValue:this.state.data&&this.state.data.name
|
||||
|
||||
})(
|
||||
<Input placeholder="标题"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<h1>内容</h1>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('body', {
|
||||
rules: [{
|
||||
required: true, message: '请输入描述内容'
|
||||
}],
|
||||
initialValue:this.state.data&&this.state.data.body
|
||||
})(
|
||||
<TextArea placeholder="添加一个可选的扩展描述。。。" style={{height:"300px"}}/>
|
||||
|
||||
)}
|
||||
</Form.Item>
|
||||
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider/>
|
||||
<div className="fr">
|
||||
<Checkbox onChange={this.RedieonChange}>标记为预行版</Checkbox>
|
||||
<p>标记此版本不适合生产使用</p>
|
||||
</div>
|
||||
<div className="clearfix mt15" style={{marginTop:5}} >
|
||||
<a className='topWrapper_btn_delete fr' onClick={()=>this.deleteversion()} style={{marginLeft:15}}>删除发布</a>
|
||||
<a className='topWrapper_btn fr' onClick={()=>this.handleSubmit()} style={{marginRight:15}}>编辑发布信息</a>
|
||||
<Link to={`/projects/${projectsId}/version`} style={{marginRight:30}} className='topWrapper_btn fr'>取消</Link>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const WrappedNewVersionForm = Form.create({ name: 'NewVersionForm' })(NewVersion);
|
||||
export default WrappedNewVersionForm;
|
||||
|
|
@ -0,0 +1,348 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Avatar, Tag, Button, Spin, Input, Form, message, Divider} from "antd";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
|
||||
import axios from "axios";
|
||||
import { getImageUrl } from "educoder";
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
|
||||
import SponsorTierItem from "./sponsor_tier_item";
|
||||
|
||||
import "../users/new_user.css";
|
||||
import "../css/index.scss";
|
||||
import '../users/Index.scss';
|
||||
import "./sponsor.css";
|
||||
|
||||
const tempData = [
|
||||
{id:1, tier: 5, description: "这能让我感到很开心"},
|
||||
{id:2, tier: 10, description: "如果您更加慷慨的话就选择这个"},
|
||||
{id:3, tier: 150, description: "这能为我带来相当多的额外收入"},
|
||||
{id:4, tier: 250, description: "这能为我带来相当多的额外收入"},
|
||||
{id:5, tier: 500, description: "这能为我带来相当多的额外收入"},
|
||||
{id:6, tier: 1000, description: "这能为我带来相当多的额外收入"},
|
||||
{id:7, tier: 5000, description: "这能为我带来相当多的额外收入"},
|
||||
];
|
||||
|
||||
const tempDesc = "我长期从事开源社区相关工作...目前已经开发了多个项目,如xxx, xxxx, ...\n我希望通过资助机制成为全职开源开发者,如果您对我的项目感兴趣,请资助我!"
|
||||
|
||||
const tempSponsors = [
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
{image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104"},
|
||||
];
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const TextArea = Input.TextArea;
|
||||
|
||||
const DescriptionForm = Form.create()(
|
||||
class extends Component{
|
||||
getItemsValue = ()=>{
|
||||
const val= this.props.form.getFieldsValue(); // 获取from表单的值
|
||||
return val;
|
||||
}
|
||||
render(){
|
||||
|
||||
const { form, initValue} = this.props;
|
||||
const { getFieldDecorator } = form; // 校验控件
|
||||
return(
|
||||
<Form >
|
||||
<FormItem>
|
||||
{getFieldDecorator(`description`,{
|
||||
rules: [],
|
||||
initialValue: initValue ? initValue : undefined
|
||||
})(
|
||||
// <Input placeholder="请输入"/>
|
||||
<TextArea rows={4} placeholder="请输入"></TextArea>
|
||||
)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
class Sponsor extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isSpin: false,
|
||||
user: undefined,
|
||||
description: undefined,
|
||||
sponsors: undefined,
|
||||
edit: false,
|
||||
tiers: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.fetchUser();
|
||||
this.fetchData();
|
||||
};
|
||||
|
||||
fetchUser = () => {
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
});
|
||||
const { current_user } = this.props;
|
||||
const { username } = this.props.match.params;
|
||||
|
||||
let url = `/users/${username || (current_user && current_user.login)}.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
// TODO: 在这里添加了对用户自我介绍的处理,前后端交互实现后需要删掉
|
||||
// result.data.description = tempDesc;
|
||||
this.setState({
|
||||
user: result.data,
|
||||
isSpin: false,
|
||||
}, () => {this.fetchSponsors()});
|
||||
// console.log(result.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
fetchSponsors = () => {
|
||||
// console.log("fetch sponsors");
|
||||
const user_id = this.state.user.user_id;
|
||||
|
||||
let url = `/sponsorships/sponsored.json`;
|
||||
|
||||
axios.get(url, {params: {id: user_id}})
|
||||
.then((result) => {
|
||||
// console.log(result);
|
||||
this.setState({
|
||||
sponsors: result.data.sponsorships,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
// this.setState({
|
||||
// sponsors: tempData,
|
||||
// displayList: tempData,
|
||||
// })
|
||||
// this.setState({
|
||||
// sponsors: tempSponsors,
|
||||
// });
|
||||
}
|
||||
|
||||
fetchData = () => {
|
||||
let url = `/sponsor_tiers.json`;
|
||||
const user_login = this.props.match.params.username;
|
||||
axios
|
||||
.get(url, {params:{login: user_login}})
|
||||
.then((result) => {
|
||||
// console.log(result.data);
|
||||
// console.log(tempData)
|
||||
this.setState({
|
||||
tiers: result.data
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
editDescription = () => {
|
||||
this.setState({
|
||||
edit: true,
|
||||
});
|
||||
}
|
||||
|
||||
cancelEdit = () => {
|
||||
this.setState({
|
||||
edit: false,
|
||||
})
|
||||
}
|
||||
|
||||
confirmEdit = () => {
|
||||
//TODO: 增加和后端交互
|
||||
let value = this.formRef.getItemsValue().description;
|
||||
// console.log(value);
|
||||
let user = this.state.user;
|
||||
let url = `/users/${user.user_id}/update_description.json`
|
||||
axios.put(url, {description: value})
|
||||
.then((result) => {
|
||||
user.description = value;
|
||||
this.setState({
|
||||
user: user,
|
||||
edit: false
|
||||
})
|
||||
this.props.showNotification("修改成功")
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
this.props.showNotification("修改失败")
|
||||
})
|
||||
|
||||
|
||||
// if (user){
|
||||
// user.description = value;
|
||||
// }
|
||||
// this.setState({
|
||||
// user: user,
|
||||
// edit: false,
|
||||
// });
|
||||
}
|
||||
|
||||
visitorTemplate = () => {
|
||||
const user = this.state.user;
|
||||
return (
|
||||
<div>
|
||||
{user && user.description?
|
||||
(<p>{user.description}</p>):(<p>暂无自我介绍</p>)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
manageTemplate = () => {
|
||||
const user = this.state.user;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<i className="iconfont icon-bianji3 font-15" onClick={() => this.editDescription()}></i>
|
||||
</div>
|
||||
{user && user.description? (<div>{user.description}</div>):(<div>暂无自我介绍</div>)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
editTemplate = () => {
|
||||
const user = this.state.user;
|
||||
return (
|
||||
<div>
|
||||
<DescriptionForm
|
||||
initValue={user && user.description}
|
||||
wrappedComponentRef={(form) => this.formRef = form}
|
||||
/>
|
||||
<Button onClick={() => this.confirmEdit()}>确认</Button>
|
||||
<Button onClick={() => this.cancelEdit()}>取消</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
sponsorList(){
|
||||
const {sponsors} = this.state;
|
||||
const sponsorList = (sponsors && sponsors.length>0 ? sponsors.map((item, key)=>{
|
||||
return (
|
||||
<Link to={`/users/${item.login}`} className="show-user-link">
|
||||
<img className="sponsor-page-sponsors" alt="" src={getImageUrl(`images/${item && item.image_url}`)} title={item.username}></img>
|
||||
</Link>);
|
||||
})
|
||||
:"")
|
||||
return (<p>{sponsorList}</p>);
|
||||
}
|
||||
|
||||
render(){
|
||||
const { current_user} = this.props;
|
||||
const { user, isSpin, tiers} = this.state;
|
||||
const sponsorList = this.sponsorList();
|
||||
// console.log(tiers);
|
||||
|
||||
var content = "";
|
||||
if (current_user && user && user.login !== current_user.login){
|
||||
content = this.visitorTemplate();
|
||||
}
|
||||
else if(current_user && user && user.login === current_user.login && this.state.edit){
|
||||
content = this.editTemplate();
|
||||
}
|
||||
else if(current_user && user && user.login === current_user.login && !this.state.edit){
|
||||
content = this.manageTemplate();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="new-content-flex">
|
||||
<div className="sponsor-page-left">
|
||||
<div className="list-l-Menu pd20 ">
|
||||
<div className="text-center mt15 font-16 fwb"> 成为{user && user.username}的赞助者吧</div>
|
||||
<div className="text-center"><Avatar
|
||||
size={110}
|
||||
src={getImageUrl(`images/${user && user.image_url}`)}
|
||||
/>
|
||||
{user && user.user_identity && (
|
||||
<div className="mt-n15 position-relative">
|
||||
<Tag color="#FF6E21" style={{marginRight:"0px"}}>{user && user.user_identity}</Tag>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Divider />
|
||||
{content}
|
||||
<Divider />
|
||||
<div>
|
||||
赞助者:
|
||||
{sponsorList}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bgcF">
|
||||
{/* <div className="list-l-Menu pd20 ">
|
||||
{content}
|
||||
</div>
|
||||
<div className="list-l-Menu pd20 ">
|
||||
赞助者:
|
||||
{sponsorList}
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="sponsor-page-right">
|
||||
<SponsorTierItem
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
tiers={tiers}>
|
||||
</SponsorTierItem>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Sponsor))))
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Avatar, Tag, Button, Spin, Input, Divider, Form, Radio, Alert, message, Modal} from "antd";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
|
||||
import axios from "axios";
|
||||
import { getImageUrl } from "educoder";
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
|
||||
import "../users/new_user.css";
|
||||
import "../css/index.scss";
|
||||
import '../users/Index.scss';
|
||||
import "./sponsor.css";
|
||||
import { submitUserCode } from "../../redux/actions/ojForUser";
|
||||
|
||||
const tempData = {amount:100, description: "如果您更加慷慨的话就选择这个"};
|
||||
const tempBalance = 999;
|
||||
const FormItem = Form.Item;
|
||||
const { confirm } = Modal;
|
||||
|
||||
const SponsorConfirmation = Form.create()(
|
||||
class extends Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isSpin: false,
|
||||
user: undefined,
|
||||
tier: undefined,
|
||||
single: false,
|
||||
balance: undefined,
|
||||
is_sponsoring: false,
|
||||
visible: false,
|
||||
sponsorship_id: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.fetchUser();
|
||||
this.fetchTierInformation();
|
||||
this.fetchBalance();
|
||||
// this.fetchData();
|
||||
};
|
||||
|
||||
//组件刚刚挂载时,TPMINDEXHOC还没从后端获取current_user,需要在获取后,再使用current_user的内容
|
||||
componentWillReceiveProps = () => {
|
||||
if (this.props.current_user)
|
||||
this.fetchBalance();
|
||||
}
|
||||
|
||||
fetchUser = () => {
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
});
|
||||
const { current_user } = this.props;
|
||||
const { username } = this.props.match.params;
|
||||
|
||||
let url = `/users/${username || (current_user && current_user.login)}.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
user: result.data,
|
||||
isSpin: false,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
fetchTierInformation = () => {
|
||||
const { current_user } = this.props;
|
||||
const { username, tier_id } = this.props.match.params;
|
||||
let url = `/sponsor_tiers/${tier_id}.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
tier: result.data.tier,
|
||||
is_sponsoring: result.data.is_sponsoring,
|
||||
sponsorship_id: result.data.sponsorship_id,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fetchBalance = () => {
|
||||
const { current_user } = this.props;
|
||||
let url = `/wallets/balance.json`;
|
||||
if (current_user){
|
||||
axios
|
||||
.get(url, {params: {id: current_user.user_id}})
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
balance: result.data.balance,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reSelect = () => {
|
||||
const {user} = this.state;
|
||||
this.setState({
|
||||
route_type: undefined
|
||||
})
|
||||
this.props.history.push(`/sponsor/${user && user.login}`)
|
||||
}
|
||||
|
||||
changeSingle = (e) => {
|
||||
|
||||
this.setState({
|
||||
single: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
updateSponsorship = () => {
|
||||
const value = this.props.form.getFieldsValue();
|
||||
const {tier, user, sponsorship_id} = this.state;
|
||||
const {current_user} = this.props;
|
||||
let url = `/sponsorships/${sponsorship_id}.json`;
|
||||
axios.put(url, {
|
||||
amount: tier.tier,
|
||||
visible: value.visible
|
||||
})
|
||||
.then((result) => {
|
||||
if (result && result.data.status == 1)
|
||||
this.props.showNotification(result.data.message);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
const value = this.props.form.getFieldsValue();
|
||||
const {tier, user} = this.state;
|
||||
const {current_user} = this.props;
|
||||
// console.log(value);
|
||||
let url = `/sponsorships.json`;
|
||||
axios.post(url, {
|
||||
amount: tier.tier,
|
||||
visible: value.visible,
|
||||
single: value.single,
|
||||
developer_id: user.user_id,
|
||||
})
|
||||
.then((result) => {
|
||||
// console.log(result);
|
||||
if (result && result.data.status == 1)
|
||||
this.props.showNotification(result.data.message);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
handleCancel = e => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
showModal = () => {
|
||||
this.setState({
|
||||
visible: true,
|
||||
});
|
||||
};
|
||||
|
||||
showConfirm = () => {
|
||||
const {user} = this.state;
|
||||
const fun = this.state.is_sponsoring?this.updateSponsorship:this.submit;
|
||||
let text = this.state.is_sponsoring?`确认要修改对 ${user && user.username} 的赞助吗?若修改金额,将在下次自动扣款生效。`
|
||||
:`确认要赞助 ${user && user.username} 吗?`;
|
||||
confirm({
|
||||
// title: '确认赞助',
|
||||
// icon: <ExclamationCircleOutlined />,
|
||||
content: text,
|
||||
onOk() {
|
||||
fun()
|
||||
},
|
||||
onCancel() {
|
||||
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
const {tier_id, username} = this.props.match.params;
|
||||
const {current_user, form} = this.props;
|
||||
const {user, isSpin, tier, balance, is_sponsoring, single} = this.state;
|
||||
const {getFieldDecorator} = form;
|
||||
|
||||
const current_username = current_user && current_user.username;
|
||||
const alert_text = this.state.single? `您选择了单次付费,本次扣除${tier && tier.tier}硬币`
|
||||
:`您选择了按月付费,每月20日将扣除${tier && tier.tier}硬币`;
|
||||
|
||||
// console.log("sponsoring", is_sponsoring);
|
||||
// console.log("tier: ", tier);
|
||||
// console.log("current user", current_user);
|
||||
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="new-content-flex">
|
||||
<div className="sponsor-confirmation-left">
|
||||
<div className="list-l-Menu pd20 ">
|
||||
<p>
|
||||
<Avatar
|
||||
size={50}
|
||||
src={getImageUrl(`images/${user && user.image_url}`)}
|
||||
/>
|
||||
<a href={`/sponsor/${user && user.login}`}>赞助{user && user.username}</a>/赞助等级确认
|
||||
</p>
|
||||
<p>
|
||||
赞助者为
|
||||
<Avatar
|
||||
size={50}
|
||||
src={getImageUrl(`images/${current_user && current_user.image_url}`)}
|
||||
/>
|
||||
{current_user && current_user.username}
|
||||
</p>
|
||||
<Divider></Divider>
|
||||
<p>所选赞助等级</p>
|
||||
<p>{tier && tier.tier}硬币</p>
|
||||
<p>{tier && tier.description}</p>
|
||||
<Button onClick={() => this.reSelect()}>重新选择</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="sponsor-confirmation-right">
|
||||
<div className="list-l-Menu pd20 ">
|
||||
<Form>
|
||||
<FormItem >
|
||||
{getFieldDecorator(`single`,{
|
||||
rules: [{
|
||||
required: true
|
||||
}],
|
||||
initialValue: single
|
||||
})(
|
||||
<Radio.Group onChange={(e) => this.changeSingle(e)} disabled={is_sponsoring}>
|
||||
<Radio style={radioStyle} value={true}>单次付费</Radio>
|
||||
<Radio style={radioStyle} value={false}>按月支付</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</FormItem>
|
||||
<p>本次支付金额{tier && tier.tier}硬币</p>
|
||||
<p>{this.state.single? "单次付费": "即日起-次月20日"}</p>
|
||||
<Divider></Divider>
|
||||
|
||||
<div>支付信息</div>
|
||||
<div>
|
||||
<div>
|
||||
<Avatar
|
||||
size={50}
|
||||
src={getImageUrl(`images/${current_user && current_user.image_url}`)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>{current_user && current_user.username}</div>
|
||||
<div>硬币余额{balance}</div>
|
||||
</div>
|
||||
</div>
|
||||
<Alert message={alert_text} type="warning"/>
|
||||
<Divider></Divider>
|
||||
<span>赞助关系可见性</span>
|
||||
<FormItem >
|
||||
{getFieldDecorator(`visible`,{
|
||||
rules: [{
|
||||
required: true
|
||||
}],
|
||||
initialValue: 1
|
||||
})(
|
||||
<Radio.Group >
|
||||
<Radio style={radioStyle} value={1}>所有人可见</Radio>
|
||||
<Radio style={radioStyle} value={0}>私密</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</FormItem>
|
||||
<Button type='primary' className="confirm-btn" onClick={() => this.showConfirm()}>赞助 {user && user.username}</Button>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(SponsorConfirmation))))
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
.sponsor-page-left{
|
||||
width: 65%;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sponsor-page-right{
|
||||
width: 35%;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sponsor-page-sponsors{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
margin-right: 11px;
|
||||
}
|
||||
|
||||
.sponsor-confirmation-left{
|
||||
width: 35%;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sponsor-confirmation-right{
|
||||
width: 65%;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sponsor-inline{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tier-Item:last-child{
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.tier-Item{
|
||||
border-bottom:1px solid rgba(238,238,238,1);
|
||||
padding:9px 12px;
|
||||
}
|
||||
|
||||
|
||||
.right{
|
||||
float: right
|
||||
}
|
||||
|
||||
.btn-border-5{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.description-edit{
|
||||
min-height:28px;
|
||||
border:true;
|
||||
}
|
||||
|
||||
.tier-title{
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mr10{
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.confirm-btn{
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.sponsor-item-btn{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Avatar, Tag, Button, Spin, Icon, Modal, Input, Form, message, Popconfirm, Divider, InputNumber} from "antd";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
// import { EditOutlined } from "@ant-design/icons";
|
||||
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
|
||||
import axios from "axios";
|
||||
import { getImageUrl } from "educoder";
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
|
||||
import "../users/new_user.css";
|
||||
import "../css/index.scss";
|
||||
import '../users/Index.scss';
|
||||
import "./sponsor.css";
|
||||
import "../Main/list.css";
|
||||
import Item from "antd/lib/list/Item";
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const EditTierForm = Form.create()(
|
||||
class extends Component{
|
||||
getItemsValue = ()=>{
|
||||
const val= this.props.form.getFieldsValue(); // 获取from表单的值
|
||||
return val;
|
||||
}
|
||||
render(){
|
||||
|
||||
const { form, initValue1, initValue2, initValueList } = this.props;
|
||||
const { getFieldDecorator } = form; // 校验控件
|
||||
return(
|
||||
<Form >
|
||||
<FormItem label={`金额`} >
|
||||
{getFieldDecorator(`tier`,{
|
||||
rules: [{
|
||||
message: '请输入数字!',
|
||||
pattern: /^[0-9]+$/,
|
||||
required: true
|
||||
}],
|
||||
initialValue: initValue1 ? initValue1 : undefined
|
||||
})(
|
||||
<InputNumber placeholder="请输入数字"/>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem label={`描述`} >
|
||||
{getFieldDecorator(`description`,{
|
||||
rules: [{
|
||||
message: '必填字段!',
|
||||
required: true,
|
||||
}, {
|
||||
max: 255,
|
||||
message: "长度不能超过255个字符"
|
||||
}],
|
||||
initialValue: initValue2 ? initValue2 : undefined
|
||||
})(
|
||||
<Input placeholder="请输入"/>
|
||||
)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
class SponsorTierItem extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
var edit = new Array();
|
||||
if (props.tiers){
|
||||
for(var i=0; i<props.tiers.length; i++) edit.push(false);
|
||||
}
|
||||
this.state = {
|
||||
tiers: props.tiers,
|
||||
new_tier: undefined,
|
||||
edit: edit,
|
||||
isSpin: false,
|
||||
}
|
||||
// this.state = {
|
||||
// tiers: undefined,
|
||||
// new_tier: undefined,
|
||||
// edit: undefined,
|
||||
// isSpin: false,
|
||||
// }
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
|
||||
}
|
||||
|
||||
// 如果服务器较慢,组件会先被挂载,此时父组件传来的props数据是空的,但是获得数据后,有新的props,需要更新。
|
||||
// 如果用户点击了修改自我描述等父组件的方法,父组件会重新渲染,这个方法又会被调用,有可能原有的编辑框会丢失。
|
||||
// 因此先判断一下父组件传过来的数据是否有变化。没有变化则不需要修改state
|
||||
componentWillReceiveProps = () => {
|
||||
if (this.props.tiers !== this.state.tiers){
|
||||
var edit = new Array();
|
||||
for(var i=0; i<this.props.tiers.length; i++) edit.push(false);
|
||||
this.setState({
|
||||
tiers: this.props.tiers,
|
||||
edit: edit,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fetchData = () => {
|
||||
let url = `/sponsor_tiers.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
console.log(result.data);
|
||||
// console.log(tempData);
|
||||
var edit = new Array();
|
||||
for(var i=0; i<result.data.length; i++) edit.push(false);
|
||||
this.setState({
|
||||
tiers: result.data,
|
||||
edit: edit,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
fetchUser = () => {
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
});
|
||||
const { current_user } = this.props;
|
||||
const { username } = this.props.match.params;
|
||||
|
||||
let url = `/users/${username || (current_user && current_user.login)}.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
user: result.data,
|
||||
isSpin: false,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
editTier = (item, key, e) => {
|
||||
var edit = this.state.edit;
|
||||
|
||||
var editing = false;
|
||||
for(var i=0; i<edit.length; i++)
|
||||
editing = editing || edit[i];
|
||||
|
||||
if(editing){
|
||||
this.props.showNotification("请先完成当前编辑");
|
||||
return;
|
||||
}
|
||||
else{
|
||||
edit[key] = true;
|
||||
this.setState({
|
||||
edit:edit
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
confirmEdit = async (item, key, e) => {
|
||||
let url;
|
||||
try {
|
||||
const values = await this.formRef.props.form.validateFields();
|
||||
// console.log('Success:', values);
|
||||
} catch (errorInfo) {
|
||||
this.props.showNotification('提交失败,数据不合法');
|
||||
return false;
|
||||
}
|
||||
let values = this.formRef.getItemsValue();
|
||||
// console.log(this.formRef);
|
||||
const {current_user} = this.props;
|
||||
if (this.state.new_tier == key){
|
||||
console.log("new tier");
|
||||
url = `/sponsor_tiers.json`;
|
||||
axios
|
||||
.post(url, {
|
||||
...values,
|
||||
user_id: current_user.user_id
|
||||
})
|
||||
.then((result) => {
|
||||
var {tiers, edit} = this.state;
|
||||
tiers[key] = result.data.tier;
|
||||
edit[key] = false;
|
||||
this.setState({
|
||||
tiers: tiers,
|
||||
edit: edit,
|
||||
new_tier: undefined
|
||||
})
|
||||
// message.success("新增成功");
|
||||
this.props.showNotification(`新增成功!`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.props.showNotification("新增失败");
|
||||
})
|
||||
}
|
||||
else{
|
||||
url = `/sponsor_tiers/${item.id}.json`
|
||||
axios
|
||||
.put(url, {
|
||||
...values,
|
||||
})
|
||||
.then((result) => {
|
||||
var {tiers, edit} = this.state;
|
||||
tiers[key] = result.data.tier;
|
||||
edit[key] = false;
|
||||
this.setState({
|
||||
tiers: tiers,
|
||||
edit: edit,
|
||||
new_tier: undefined
|
||||
})
|
||||
// message.success("修改成功");
|
||||
this.props.showNotification(`修改成功!`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.props.showNotification("修改失败");
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// TODO: 在此处加入对后端的修改请求
|
||||
|
||||
// TODO: 修改的请求实现
|
||||
}
|
||||
|
||||
cancelEdit = (item, key, e) => {
|
||||
let {tiers, edit, new_tier} = this.state;
|
||||
if (new_tier){
|
||||
tiers.pop();
|
||||
edit.pop();
|
||||
}
|
||||
else {
|
||||
edit[key] = false;
|
||||
}
|
||||
this.setState({
|
||||
tiers: tiers,
|
||||
edit: edit,
|
||||
new_tier: undefined
|
||||
})
|
||||
}
|
||||
|
||||
newTier = () => {
|
||||
if (this.state.new_tier !== undefined){
|
||||
this.props.showNotification("请先完成当前编辑")
|
||||
return;
|
||||
}
|
||||
|
||||
let {tiers, edit} = this.state;
|
||||
tiers.push({tier: 1, description: ""})
|
||||
edit.push(true);
|
||||
this.setState({
|
||||
tiers: tiers,
|
||||
edit: edit,
|
||||
new_tier: tiers.length - 1,
|
||||
})
|
||||
}
|
||||
|
||||
deleteTier = (item, key, e) => {
|
||||
// TODO: 此处向后端发送请求删除
|
||||
let {tiers, edit} = this.state;
|
||||
|
||||
let url = `/sponsor_tiers/${item.id}.json`;
|
||||
|
||||
axios
|
||||
.delete(url)
|
||||
.then((result) => {
|
||||
tiers.splice(key, 1)
|
||||
edit.splice(key, 1)
|
||||
this.setState({
|
||||
tiers: tiers,
|
||||
edit: edit,
|
||||
})
|
||||
this.props.showNotification("删除成功");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.props.showNotification("删除失败");
|
||||
})
|
||||
}
|
||||
|
||||
toConformation = (item, key, e) => {
|
||||
const {user} = this.props;
|
||||
this.setState({
|
||||
route_type: undefined
|
||||
})
|
||||
this.props.history.push(`/sponsor_confirmation/${user && user.login}/${item.id}`)
|
||||
}
|
||||
|
||||
visitorTemplate = (item, key) => {
|
||||
return (
|
||||
<ul className="tier-Item">
|
||||
|
||||
<div className="tier-title">
|
||||
{item.tier} 硬币
|
||||
<Button className="right btn-border-5" onClick={(e) => this.toConformation(item, key, e)}>选择</Button>
|
||||
</div>
|
||||
<div>
|
||||
{item.description}
|
||||
</div>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
manageTemplate = (item, key) => {
|
||||
return (
|
||||
<div className="tier-Item">
|
||||
<div>
|
||||
<span className="tier-title">{item.tier} 硬币</span>
|
||||
|
||||
<Popconfirm
|
||||
title="确认删除?"
|
||||
onConfirm={e => this.deleteTier(item, key, e)}
|
||||
// onCancel={cancel}
|
||||
okText="是"
|
||||
cancelText="否"
|
||||
>
|
||||
<i className="iconfont icon-shanchu font-15 right"></i>
|
||||
</Popconfirm>
|
||||
|
||||
<i className="iconfont icon-bianji3 font-15 mr10 right" onClick={e => this.editTier(item, key, e)}></i>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
{item.description}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
editTemplate = (item, key) => {
|
||||
return (
|
||||
<div className="tier-Item">
|
||||
<EditTierForm
|
||||
initValue1={item.tier}
|
||||
initValue2={item.description}
|
||||
wrappedComponentRef={(form) => this.formRef = form}
|
||||
/>
|
||||
<Button onClick={e => this.confirmEdit(item, key, e)}>确定</Button>
|
||||
<Button onClick={e => this.cancelEdit(item, key, e)}>取消</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {tiers} = this.state;
|
||||
const { current_user} = this.props;
|
||||
const {user} = this.props;
|
||||
|
||||
// console.log("item state tiers:", tiers);
|
||||
// console.log("item props tiers:", this.props.tiers);
|
||||
|
||||
const renderList = (
|
||||
tiers && tiers.length > 0 ? tiers.map((item, key) => {
|
||||
const tier = this.state.edit[key]? (<Input></Input>):item.tier;
|
||||
const description = this.state.edit[key]? (<Input></Input>):item.description;
|
||||
|
||||
var content = "";
|
||||
if (current_user && user && user.login !== current_user.login){
|
||||
content = this.visitorTemplate(item, key);
|
||||
}
|
||||
else if(current_user && user && user.login === current_user.login && this.state.edit[key]){
|
||||
content = this.editTemplate(item, key);
|
||||
}
|
||||
else if(current_user && user && user.login === current_user.login && !this.state.edit[key]){
|
||||
content = this.manageTemplate(item, key);
|
||||
}
|
||||
|
||||
// return (
|
||||
// <ul className="list-l-Menu">
|
||||
|
||||
// <div className="font-15 mr5">
|
||||
// 金额:{amount}
|
||||
// {current_user && user && user.login === current_user.login ?
|
||||
// // (<Icon type="edit" onClick={item => this.editTier(item)}/>
|
||||
// (<i className="iconfont icon-bianji3 font-15 mr5" onClick={e => this.editTier(item, key, e)}></i>):
|
||||
// <Button >选择</Button>}
|
||||
// </div>
|
||||
// <div className="font-15 mr5">
|
||||
// 描述:{description}
|
||||
// {current_user && user && user.login === current_user.login ?
|
||||
// (<i className="iconfont icon-shanchu font-15"></i>):""}
|
||||
// </div>
|
||||
// </ul>
|
||||
|
||||
// )
|
||||
return content;
|
||||
}) : ""
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<div className="list-l-Menu">
|
||||
<p className="tier-Item tier-title">选择您的赞助等级</p>
|
||||
{/* <Divider/> */}
|
||||
{renderList}
|
||||
</div>
|
||||
{current_user && user && user.login === current_user.login ?
|
||||
( <Button type="primary" onClick={() => this.newTier()}>新增赞助等级</Button>):
|
||||
""
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default SponsorTierItem;
|
||||
|
|
@ -45,6 +45,19 @@ const UndoEvents = Loadable({
|
|||
loader: () => import("./undo_events"),
|
||||
loading: Loading,
|
||||
})
|
||||
const Wallet = Loadable({
|
||||
loader: () => import("./sponsor/wallet"),
|
||||
loading: Loading,
|
||||
});
|
||||
const SponsorManagement = Loadable({
|
||||
loader: () => import("./sponsor/SponsorManagement"),
|
||||
loading: Loading,
|
||||
});
|
||||
const SponsorDataCharts = Loadable({
|
||||
loader: () => import("./sponsor/communityData"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
class Infos extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -52,7 +65,10 @@ class Infos extends Component {
|
|||
isSpin: false,
|
||||
user: undefined,
|
||||
project_type: undefined,
|
||||
route_type: undefined
|
||||
route_type: undefined,
|
||||
c: undefined,
|
||||
sponsor_management: undefined,
|
||||
choose_chart: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +103,10 @@ class Infos extends Component {
|
|||
change_project_type = (type) => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
project_type: type ,
|
||||
project_type: type,
|
||||
choose_wallet: false,
|
||||
sponsor_management: undefined,
|
||||
choose_chart: undefined,
|
||||
route_type: undefined
|
||||
})
|
||||
let url = `/users/${user && user.login}`
|
||||
|
|
@ -129,10 +148,63 @@ class Infos extends Component {
|
|||
this.props.history.push(`/users/${user && user.login}/organizes`)
|
||||
}
|
||||
|
||||
sponsor_link = () => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
route_type: undefined
|
||||
})
|
||||
this.props.history.push(`/sponsor/${user && user.login}`)
|
||||
}
|
||||
|
||||
sponsor_management_link = () => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
route_type: undefined,
|
||||
sponsor_management: true,
|
||||
project_type: undefined,
|
||||
choose_wallet: undefined,
|
||||
choose_chart: undefined,
|
||||
})
|
||||
this.props.history.push(`/users/${user && user.login}/sponsor_management`)
|
||||
}
|
||||
|
||||
wallet_link = () => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
project_type: undefined,
|
||||
choose_wallet: true,
|
||||
route_type: undefined,
|
||||
sponsor_management: undefined,
|
||||
choose_chart: undefined,
|
||||
})
|
||||
this.props.history.push(`/users/${user && user.login}/wallet`)
|
||||
}
|
||||
|
||||
sponsor_setting_link = () => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
route_type: undefined
|
||||
})
|
||||
this.props.history.push(`/users/${user && user.login}/sponsor_setting`)
|
||||
}
|
||||
|
||||
sponsor_statistic = () => {
|
||||
const {user} = this.state
|
||||
this.setState({
|
||||
project_type: undefined,
|
||||
choose_wallet: undefined,
|
||||
route_type: undefined,
|
||||
sponsor_management: undefined,
|
||||
choose_chart: true
|
||||
})
|
||||
this.props.history.push(`/users/${user && user.login}/sponsor_community_data`)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { current_user, mygetHelmetapi } = this.props;
|
||||
const { user, isSpin, project_type, route_type } = this.state;
|
||||
const { user, isSpin, project_type, route_type, choose_wallet, choose_chart, sponsor_management } = this.state;
|
||||
// console.log("current", current_user)
|
||||
// console.log("user", user)
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Spin spinning={isSpin}>
|
||||
|
|
@ -155,10 +227,10 @@ class Infos extends Component {
|
|||
|
||||
<div>
|
||||
{user && current_user && user.login === current_user.login && (
|
||||
<div className="user-info-star-button ">
|
||||
<div className="user-info-star-button">
|
||||
<Button
|
||||
block
|
||||
className="text-button-grey"
|
||||
className="text-button-grey mr5"
|
||||
href={`${
|
||||
mygetHelmetapi &&mygetHelmetapi.new_course&&
|
||||
mygetHelmetapi.new_course.edit_account
|
||||
|
|
@ -166,10 +238,19 @@ class Infos extends Component {
|
|||
target="_blank"
|
||||
>
|
||||
{" "}
|
||||
<i className="iconfont icon-shezhi4 font-15 mr5"></i>
|
||||
<i className="iconfont icon-shezhi4 font-15"></i>
|
||||
修改资料
|
||||
</Button>
|
||||
<Button
|
||||
block
|
||||
className="text-button-grey"
|
||||
href={`/sponsor/${user && user.login}`}
|
||||
>
|
||||
赞助信息修改
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
{current_user && user && user.login !== current_user.login && (
|
||||
<div className="user-info-star-button ">
|
||||
|
|
@ -180,6 +261,13 @@ class Infos extends Component {
|
|||
fontClass={"font-14 ml5"}
|
||||
starText={"关注TA"}
|
||||
/>
|
||||
<Button
|
||||
block
|
||||
className="text-button-grey ml-5"
|
||||
href={`/sponsor/${user && user.login}`}
|
||||
>
|
||||
赞助
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -291,7 +379,56 @@ class Infos extends Component {
|
|||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div> */}
|
||||
</div> */}
|
||||
{current_user && user && user.login == current_user.login && (
|
||||
|
||||
<div className="bgcF">
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle">
|
||||
<i className="iconfont icon-bianzu1 font-15 mr5"></i>
|
||||
赞助管理
|
||||
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
|
||||
</li>
|
||||
<li className={choose_wallet ? "active" : ""} onClick={() => this.wallet_link()}>
|
||||
<p>
|
||||
<span className="font-16">我的钱包</span>
|
||||
<span className="color-blue">
|
||||
{/* {user && user.common_projects_count} */}
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li className={sponsor_management ? "active" : ""} onClick={() => this.sponsor_management_link()}>
|
||||
<p>
|
||||
<span className="font-16">赞助管理</span>
|
||||
<span className="color-blue">
|
||||
{/* {user && user.sync_mirror_projects_count} */}
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{current_user && user && user.login == current_user.login && current_user.admin &&(
|
||||
|
||||
<div className="bgcF">
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle">
|
||||
<i className="iconfont icon-dashujucunchu font-15 mr5"></i>
|
||||
社区统计信息
|
||||
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
|
||||
</li>
|
||||
<li className={choose_chart ? "active" : ""} onClick={() => this.sponsor_statistic()}>
|
||||
<p>
|
||||
<span className="font-16">赞助信息统计</span>
|
||||
<span className="color-blue">
|
||||
{/* {user && user.common_projects_count} */}
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="list-right">
|
||||
{user && (
|
||||
|
|
@ -309,6 +446,24 @@ class Infos extends Component {
|
|||
return <UndoEvents {...this.props} {...this.state} />;
|
||||
}}
|
||||
></Route>
|
||||
<Route
|
||||
path="/users/:username/wallet"
|
||||
render={(props) => {
|
||||
return <Wallet {...this.props} {...this.state} />;
|
||||
}}
|
||||
></Route>
|
||||
<Route
|
||||
path="/users/:username/sponsor_management"
|
||||
render={(props) => {
|
||||
return <SponsorManagement {...this.props} {...this.state} />;
|
||||
}}
|
||||
></Route>
|
||||
<Route
|
||||
path="/users/:username/sponsor_community_data"
|
||||
render={(props) => {
|
||||
return <SponsorDataCharts {...this.props} {...this.state} is_sponsor={true}/>;
|
||||
}}
|
||||
></Route>
|
||||
<Route
|
||||
path="/users/:username/fan_users"
|
||||
render={() => {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,15 @@
|
|||
.mt-n15{margin-top: -15px;}
|
||||
.position-relative{position: relative;}
|
||||
.mr-5{margin-right: 5px;}
|
||||
.mt-5{margin-top: 5px;}
|
||||
.ml-5{margin-left: 5px;}
|
||||
a.text-button-grey{
|
||||
color: rgba(0, 0, 0, 0.65)
|
||||
}
|
||||
.user-info-star-button{margin: 20px 50px 0 50px}
|
||||
.user-info-star-button{
|
||||
display: flex;
|
||||
margin: 20px 20px 0 20px
|
||||
}
|
||||
.list-l-p{
|
||||
width: 100%;
|
||||
display: -ms-flexbox;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import '../../css/index.scss'
|
||||
import '../../Main/list.css';
|
||||
|
||||
class CoinChangeItem extends Component {
|
||||
TurnToDetail = (login, url) => {
|
||||
this.props.history.push({
|
||||
pathname: url,
|
||||
state: login
|
||||
})
|
||||
}
|
||||
render() {
|
||||
const { coinChanges, current_user } = this.props;
|
||||
const renderList = (
|
||||
coinChanges && coinChanges.length > 0 ? coinChanges.map((item, key) => {
|
||||
let url = current_user && item.to_user_login == current_user.login? `/users/${item.from_user_login}`:`/users/${item.to_user_login}`;
|
||||
return (
|
||||
<div className="p-r-Item" key={key}>
|
||||
<div className="p-r-Infos">
|
||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>金额:{current_user && item.to_user_login == current_user.login? "收入":"支出"}{item.amount}硬币</p>
|
||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>变动原因:{item.reason}</p>
|
||||
{/* <p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>备注:{item.description}</p> */}
|
||||
|
||||
<div className="p-r-about">
|
||||
<span className="p-r-detail">
|
||||
<span><label>时间:</label>{item.date}</span>
|
||||
{current_user && item.to_user_login == current_user.login?
|
||||
(<span><label>金额来源:</label><a href={url}>{item.from_user}</a></span>):
|
||||
(<span><label>金额去向:</label><a href={url}>{item.to_user}</a></span>)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}) : ""
|
||||
)
|
||||
return (
|
||||
<div className="project-list minH-670">
|
||||
{renderList}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CoinChangeItem;
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Menu, Input, Spin, Pagination, Popover, Button, Divider } from "antd";
|
||||
import SponsorBarCharts from "./charts/sponsorBarChart";
|
||||
import SponsorPieCharts from "./charts/sponsorPieChart";
|
||||
|
||||
import axios from "axios";
|
||||
import CoinChangeItem from "./CoinChangeItem";
|
||||
import Nodata from "../../Nodata";
|
||||
import img_array from "../../Images/array.png";
|
||||
import SponsorList from "./sponsor_list";
|
||||
import "../../sponsor/sponsor.css";
|
||||
|
||||
// import "../new_user.css";
|
||||
// const Search = Input.Search;
|
||||
|
||||
// const tempData = [
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: true, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "-", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: true, sponsor: true, login:"alpc104", start_time: "2020-08-01", stop_time: "-", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "-", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: true, login:"alpc104", start_time: "2020-08-01", stop_time: "-", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "-", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: true, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// {image_url: "avatars/User/b", username: "万山川", user_id: 1369, visible: false, sponsor: false, login:"alpc104", start_time: "2020-08-01", stop_time: "2020-09-05", amount: 100},
|
||||
// ];
|
||||
|
||||
|
||||
class SponsorManagement extends Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
page: 1,
|
||||
limit: 15,
|
||||
sort_by: undefined,
|
||||
totalCount: undefined,
|
||||
isSpin: false,
|
||||
total: undefined,
|
||||
category: "sponsoring",
|
||||
is_sponsor: false,
|
||||
sponsors: undefined,
|
||||
displayList: undefined,
|
||||
chartsData: {income:[], outcome:[]},
|
||||
};
|
||||
}
|
||||
|
||||
changeCategory = (cate) => {
|
||||
this.setState({
|
||||
category: cate.target.value,
|
||||
page: 1,
|
||||
}, ()=>{
|
||||
if(this.state.category === "chart")
|
||||
this.get_chart_data();
|
||||
else
|
||||
this.get_sponsors();
|
||||
});
|
||||
// if(cate.target.value === "chart"){
|
||||
// this.setState({
|
||||
// category: cate.target.value,
|
||||
// page: 1,
|
||||
// });
|
||||
// }
|
||||
// else{
|
||||
// this.setState({
|
||||
// category: cate.target.value,
|
||||
// page: 1,
|
||||
// }, ()=>{this.get_sponsors();});
|
||||
// }
|
||||
};
|
||||
|
||||
componentDidMount = () => {
|
||||
this.get_sponsors();
|
||||
}
|
||||
|
||||
get_chart_data = () => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
|
||||
let url = `/wallets/balance_chart.json`;
|
||||
const {current_user} = this.props;
|
||||
let user_id = current_user && current_user.user_id;
|
||||
if (current_user){
|
||||
axios.get(url, {
|
||||
params: {
|
||||
id: user_id,
|
||||
sponsor: true,
|
||||
}})
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
chartsData: result.data,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
get_sponsors = ()=>{
|
||||
const user_id = this.props.current_user.user_id;
|
||||
|
||||
let url = this.state.is_sponsor? `sponsoring`:`sponsored`;
|
||||
url = this.state.category === "stopped"? `stopped_` + url: url;
|
||||
url = `/sponsorships/` + url + `.json`;
|
||||
|
||||
const {page, limit} = this.state;
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
axios.get(url, {
|
||||
params: {
|
||||
id: user_id,
|
||||
page: page,
|
||||
limit: limit,
|
||||
}})
|
||||
.then((result) => {
|
||||
// console.log(result);
|
||||
this.setState({
|
||||
displayList: result.data.sponsorships,
|
||||
total: result.data.count,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
// this.setState({
|
||||
// sponsors: tempData,
|
||||
// displayList: tempData,
|
||||
// })
|
||||
}
|
||||
|
||||
//切换页数
|
||||
changePage = (page) => {
|
||||
this.setState({
|
||||
page: page
|
||||
}, ()=>{this.get_sponsors()})
|
||||
};
|
||||
|
||||
// 排序
|
||||
ChangeSoryBy = (e) => {
|
||||
console.log(e.key)
|
||||
};
|
||||
|
||||
changeSearchValue = (e) => {
|
||||
this.setState({
|
||||
search: e.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
menu =()=> (
|
||||
<Menu onClick={this.ChangeSoryBy}>
|
||||
<Menu.Item key="time_order">时间从近到远排序</Menu.Item>
|
||||
<Menu.Item key="reverse_time_order">时间从远到近排序</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
category_button=(category)=>{
|
||||
const { current_user, user } = this.props;
|
||||
const button_lists =
|
||||
user && current_user && user.login === current_user.login
|
||||
? [
|
||||
{ type: "sponsoring", name: "赞助中" },
|
||||
{ type: "stopped", name: "已终止" },
|
||||
{ type: "chart", name: "统计图表" },
|
||||
]
|
||||
:
|
||||
[];
|
||||
|
||||
let list = button_lists.map((item, key) => {
|
||||
return (
|
||||
<span key={key} className="pr15">
|
||||
<Button
|
||||
type={
|
||||
(category && category === item.type) || (!category && !item.type)
|
||||
? "primary"
|
||||
: "default"
|
||||
}
|
||||
ghost={
|
||||
(category && category === item.type) || (!category && !item.type)
|
||||
}
|
||||
value={item.type}
|
||||
onClick={this.changeCategory}
|
||||
>
|
||||
{item.name}
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
})
|
||||
return list;
|
||||
}
|
||||
|
||||
changeStatus=(check_is_sponsor, e)=>{
|
||||
// const {is_sponsor} = this.state
|
||||
// const new_is_sponsor = is_sponsor === check_is_sponsor ? undefined : check_is_sponsor
|
||||
// this.state.is_sponsor = check_is_sponsor;
|
||||
this.setState({
|
||||
is_sponsor: check_is_sponsor,
|
||||
page: 1,
|
||||
}, ()=>{
|
||||
if(this.state.category === "chart")
|
||||
this.get_chart_data();
|
||||
else
|
||||
this.get_sponsors();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { current_user, user } = this.props;
|
||||
const { category , is_sponsor, sponsors, displayList, chartsData} = this.state;
|
||||
const {isSpin, total, search, limit, page }= this.state;
|
||||
// console.log(displayList);
|
||||
const sponsorList = displayList && displayList.length > 0 ?
|
||||
<SponsorList
|
||||
{...this.props}
|
||||
userClass={"w-33"}
|
||||
current_user={current_user}
|
||||
users={displayList}
|
||||
rerender={this.get_sponsors}
|
||||
history={this.props.history}
|
||||
></SponsorList>
|
||||
:
|
||||
<Nodata _html={`暂时没有数据`} />
|
||||
|
||||
const chartComponent = <div>
|
||||
<p>七天内赞助{this.state.is_sponsor?"支出":"收入"}图</p>
|
||||
<SponsorBarCharts is_sponsor={this.state.is_sponsor} data={chartsData}></SponsorBarCharts>
|
||||
{/* <p>七天内赞助{this.state.is_sponsor?"支出":"收入"}图</p>
|
||||
<SponsorPieCharts is_sponsor={this.state.is_sponsor}></SponsorPieCharts> */}
|
||||
</div>
|
||||
|
||||
const displayComponent = category==="chart"?chartComponent
|
||||
:
|
||||
sponsorList;
|
||||
|
||||
return (
|
||||
// <div className="list-right boxShandow radius-2" style={{padding:0}}>
|
||||
<Spin spinning={isSpin}>
|
||||
{/* <div className="list-r-operation"> */}
|
||||
{/* <Search
|
||||
placeholder="输入关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={this.get_sponsors}
|
||||
className="list-r-Search"
|
||||
value={search}
|
||||
onChange={this.changeSearchValue}
|
||||
/> */}
|
||||
{/* <div>
|
||||
|
||||
<Popover content={this.menu()} trigger={["click"]} placement="bottom">
|
||||
<a className="ant-dropdown-link">
|
||||
<span className="color-blue font-16">
|
||||
排序 <img src={img_array} alt="" width="10px" />
|
||||
</span>
|
||||
</a>
|
||||
</Popover>
|
||||
</div> */}
|
||||
{/* </div> */}
|
||||
<div className="infosType">
|
||||
<div>{this.category_button(category)}</div>
|
||||
{
|
||||
user && current_user && user.login === current_user.login ?
|
||||
<div className="infoStatus">
|
||||
<span className={is_sponsor === true ? "active" : "" } onClick={(e)=>this.changeStatus(true, e)}>我赞助的</span>
|
||||
{
|
||||
!is_sponsor ? (<Divider type={"vertical"} className="statusDivider" ></Divider>):""
|
||||
}
|
||||
<span className={is_sponsor === false ? "active" : "" } onClick={(e)=>this.changeStatus(false, e)}>赞助我的</span>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
{user && current_user && user.login === current_user.login?
|
||||
displayComponent:<Nodata _html={`暂时没有项目`} />
|
||||
}
|
||||
{
|
||||
total && total > limit && category!="chart"?
|
||||
<div className="edu-txt-center pt30 mb30 border-top-grey">
|
||||
<Pagination
|
||||
simple
|
||||
defaultCurrent={page}
|
||||
total={total}
|
||||
pageSize={limit}
|
||||
onChange={this.changePage}
|
||||
></Pagination>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
</Spin>
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SponsorManagement;
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import React, { Component } from 'react';
|
||||
import {XYPlot, VerticalBarSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, Crosshair, DiscreteColorLegend} from 'react-vis';
|
||||
// import DiscreteColorLegend from 'legends/discrete-color-legend';
|
||||
import "./style.scss";
|
||||
|
||||
// const ONE_DAY = 86400000;
|
||||
// const d = new Date().getTime()-ONE_DAY*7;
|
||||
|
||||
// const data = [
|
||||
// {x: new Date(d+ONE_DAY).toLocaleDateString(), y: 8},
|
||||
// {x: new Date(d+ONE_DAY*2).toLocaleDateString(), y: 5},
|
||||
// {x: new Date(d+ONE_DAY*3).toLocaleDateString(), y: 4},
|
||||
// {x: new Date(d+ONE_DAY*4).toLocaleDateString(), y: 9},
|
||||
// {x: new Date(d+ONE_DAY*5).toLocaleDateString(), y: 2},
|
||||
// {x: new Date(d+ONE_DAY*6).toLocaleDateString(), y: 7},
|
||||
// {x: new Date(d+ONE_DAY*7).toLocaleDateString(), y: 2},
|
||||
// ];
|
||||
|
||||
// const data2 = [
|
||||
// {x: new Date(d+ONE_DAY).toLocaleDateString(), y: 2},
|
||||
// {x: new Date(d+ONE_DAY*2).toLocaleDateString(), y: 3},
|
||||
// {x: new Date(d+ONE_DAY*3).toLocaleDateString(), y: 1},
|
||||
// {x: new Date(d+ONE_DAY*4).toLocaleDateString(), y: 5},
|
||||
// {x: new Date(d+ONE_DAY*5).toLocaleDateString(), y: 4},
|
||||
// {x: new Date(d+ONE_DAY*6).toLocaleDateString(), y: 0},
|
||||
// {x: new Date(d+ONE_DAY*7).toLocaleDateString(), y: 2},
|
||||
// ];
|
||||
|
||||
const ITEMS = [
|
||||
{title: '收入', strokeWidth: 13},
|
||||
{title: '支出', strokeWidth: 13}
|
||||
];
|
||||
|
||||
class CoinChangeCharts extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
crosshairValues: []
|
||||
};
|
||||
// console.log(this.props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {chartsData} = this.props;
|
||||
if(chartsData == undefined){
|
||||
return (<div className="App"></div>);
|
||||
}
|
||||
var max = 0;
|
||||
for(var i=0; i<chartsData.income.length; i++){
|
||||
max = Math.max(max, chartsData.income[i].y, chartsData.outcome[i].y);
|
||||
}
|
||||
return (
|
||||
<div className="App">
|
||||
<DiscreteColorLegend height={80} width={1300} items={ITEMS} />
|
||||
<XYPlot xType="ordinal" height={400} width= {700} yDomain={[-0.5, max]}>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<YAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<VerticalBarSeries data={chartsData.income} />
|
||||
<VerticalBarSeries data={chartsData.outcome} />
|
||||
|
||||
</XYPlot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CoinChangeCharts;
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import React, { Component } from 'react';
|
||||
import {XYPlot, VerticalBarSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, Crosshair, DiscreteColorLegend} from 'react-vis';
|
||||
// import DiscreteColorLegend from 'legends/discrete-color-legend';
|
||||
import "./style.scss";
|
||||
|
||||
const ONE_DAY = 86400000;
|
||||
const d = new Date().getTime()-ONE_DAY*7;
|
||||
|
||||
const data = [
|
||||
{x: new Date(d+ONE_DAY).toLocaleDateString(), y: 6},
|
||||
{x: new Date(d+ONE_DAY*2).toLocaleDateString(), y: 3},
|
||||
{x: new Date(d+ONE_DAY*3).toLocaleDateString(), y: 2},
|
||||
{x: new Date(d+ONE_DAY*4).toLocaleDateString(), y: 7},
|
||||
{x: new Date(d+ONE_DAY*5).toLocaleDateString(), y: 0},
|
||||
{x: new Date(d+ONE_DAY*6).toLocaleDateString(), y: 5},
|
||||
{x: new Date(d+ONE_DAY*7).toLocaleDateString(), y: 0},
|
||||
];
|
||||
|
||||
const data2 = [
|
||||
{x: new Date(d+ONE_DAY).toLocaleDateString(), y: 3},
|
||||
{x: new Date(d+ONE_DAY*2).toLocaleDateString(), y: 4},
|
||||
{x: new Date(d+ONE_DAY*3).toLocaleDateString(), y: 2},
|
||||
{x: new Date(d+ONE_DAY*4).toLocaleDateString(), y: 6},
|
||||
{x: new Date(d+ONE_DAY*5).toLocaleDateString(), y: 5},
|
||||
{x: new Date(d+ONE_DAY*6).toLocaleDateString(), y: 1},
|
||||
{x: new Date(d+ONE_DAY*7).toLocaleDateString(), y: 3},
|
||||
];
|
||||
|
||||
const ITEMS = [
|
||||
{title: '收入', strokeWidth: 13},
|
||||
{title: '支出', strokeWidth: 13}
|
||||
];
|
||||
|
||||
class SponsorBarCharts extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
crosshairValues: []
|
||||
};
|
||||
console.log(this.props)
|
||||
}
|
||||
|
||||
componentWillReceiveProps = () => {
|
||||
this.setState({
|
||||
crosshairValues: []
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const chartsData = this.props.is_sponsor?this.props.data.outcome:this.props.data.income;
|
||||
var max = 0;
|
||||
for(var i=0; i<chartsData.length; i++){
|
||||
max = Math.max(max, chartsData[i].y);
|
||||
}
|
||||
return (
|
||||
<div className="App">
|
||||
{/* <DiscreteColorLegend height={20} width={1300} items={ITEMS} /> */}
|
||||
<XYPlot animation={true} xType="ordinal" height={400} width= {700} yDomain={[-0.5, max]}>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<YAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
} }/>
|
||||
<VerticalBarSeries data={chartsData} />
|
||||
|
||||
</XYPlot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SponsorBarCharts;
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import React, { Component } from 'react';
|
||||
import {FlexibleXYPlot, RadialChart, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, Crosshair, DiscreteColorLegend} from 'react-vis';
|
||||
// import DiscreteColorLegend from 'legends/discrete-color-legend';
|
||||
import "./style.scss";
|
||||
|
||||
const data = [
|
||||
{label: "张三", angle: 1},
|
||||
{label: "李四", angle: 2},
|
||||
{label: "王五", angle: 5},
|
||||
{label: "赵六", angle: 3},
|
||||
];
|
||||
|
||||
const data2 = [
|
||||
{label: "张三", angle: 2},
|
||||
{label: "林磊", angle: 1},
|
||||
{label: "赵辉", angle: 4},
|
||||
];
|
||||
|
||||
const ITEMS = [
|
||||
{title: '收入', color: 'powderblue', strokeWidth: 13},
|
||||
{title: '支出', color: 'powderblue', strokeWidth: 13}
|
||||
];
|
||||
|
||||
class SponsorPieCharts extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
crosshairValues: []
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps = () => {
|
||||
this.setState({
|
||||
crosshairValues: []
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const DATA = this.props.is_sponsor?data2:data;
|
||||
// const DATA = [{angle: 1}, {angle: 5}, {angle: 2}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* <DiscreteColorLegend height={20} width={1300} items={ITEMS} /> */}
|
||||
{/* <FlexibleXYPlot height={400} width= {700}> */}
|
||||
{/* <VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<YAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
} }/> */}
|
||||
<RadialChart
|
||||
innerRadius={70}
|
||||
radius={140}
|
||||
showLabels={true}
|
||||
data={DATA} height={400} width= {400}/>
|
||||
|
||||
{/* </FlexibleXYPlot> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SponsorPieCharts;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
@import "react-vis/dist/styles/plot.scss";
|
||||
@import "react-vis/dist/styles/examples.scss";
|
||||
@import "react-vis/dist/styles/legends.scss";
|
||||
@import "react-vis/dist/styles/radial-chart.scss";
|
||||
@import "react-vis/dist/styles/treemap.scss";
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
import React, { Component } from 'react';
|
||||
import {XYPlot, VerticalBarSeries, LineSeries, VerticalGridLines, HorizontalGridLines, XAxis, YAxis, Crosshair, DiscreteColorLegend} from 'react-vis';
|
||||
// import DiscreteColorLegend from 'legends/discrete-color-legend';
|
||||
import "./charts/style.scss";
|
||||
import "../../Main/list.css";
|
||||
import "../../UsersList/list.css";
|
||||
import "../../sponsor/sponsor.css";
|
||||
import "../new_user.css"
|
||||
import axios from "axios";
|
||||
import { isSupported } from 'clipboard';
|
||||
|
||||
const ITEMS = [
|
||||
{title: '资助者数量', strokeWidth: 13},
|
||||
{title: '受资助人数', strokeWidth: 13},
|
||||
];
|
||||
|
||||
class SponsorDataCharts extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
crosshairValues: [],
|
||||
sponsor: [],
|
||||
sponsored: [],
|
||||
nums: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.get_chart_data();
|
||||
}
|
||||
|
||||
get_chart_data = () => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
|
||||
let url = `/sponsorships/community_data.json`;
|
||||
axios.get(url)
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
sponsor: result.data.sponsor,
|
||||
sponsored: result.data.sponsored,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
|
||||
url = `/wallets/community_data.json`;
|
||||
axios.get(url)
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
nums: result.data,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
componentWillReceiveProps = () => {
|
||||
this.setState({
|
||||
crosshairValues: []
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
// const DATA = this.props.is_sponsor?data2:data;
|
||||
const {sponsor, sponsored, nums} = this.state;
|
||||
var max1 = 0;
|
||||
for(var i=0; i<sponsor.length; i++){
|
||||
max1 = Math.max(max1, sponsor[i].y, sponsored[i].y);
|
||||
}
|
||||
var max2 = 0;
|
||||
for(var i=0; i<nums.length; i++){
|
||||
max2 = Math.max(max2, nums[i].y);
|
||||
}
|
||||
return (
|
||||
<div className="App">
|
||||
<p className="color-grey-3 font-18 task-hide ">平台资助者/受资助人数</p>
|
||||
<DiscreteColorLegend height={80} width={1300} items={ITEMS} />
|
||||
<XYPlot
|
||||
animation={true} xType="ordinal" height={400} width= {700}
|
||||
yDomain={[-0.5, max1]}
|
||||
>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<YAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<LineSeries data={sponsor} />
|
||||
<LineSeries data={sponsored} />
|
||||
</XYPlot>
|
||||
<p className="color-grey-3 font-18 task-hide ">平台资助交易数量</p>
|
||||
<XYPlot
|
||||
animation={true} xType="ordinal" height={400} width= {700}
|
||||
yDomain={[-0.5, max2]}
|
||||
>
|
||||
<VerticalGridLines />
|
||||
<HorizontalGridLines />
|
||||
<XAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<YAxis style={{
|
||||
line: {stroke: '#ADDDE1'},
|
||||
ticks: {stroke: '#ADDDE1'},
|
||||
text: {stroke: 'none', fill: '#6b6b76', fontWeight: 600}
|
||||
}}/>
|
||||
<VerticalBarSeries data={nums} />
|
||||
</XYPlot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SponsorDataCharts;
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import React, { Component } from "react";
|
||||
import { getImageUrl } from "educoder";
|
||||
import FocusButton from "../../UsersList/focus_button";
|
||||
import { Button, message, Popconfirm } from "antd";
|
||||
import "../../Main/list.css";
|
||||
import "../../UsersList/list.css";
|
||||
import "../../sponsor/sponsor.css";
|
||||
import "../new_user.css"
|
||||
import axios from "axios";
|
||||
import { Link } from "react-router-dom";
|
||||
class SponsorList extends Component {
|
||||
|
||||
stop_sponsorship = (item, key, e)=>{
|
||||
|
||||
// console.log("before: ", this.state.users);
|
||||
let url = `/sponsorships/${item.id}.json`;
|
||||
axios.delete(url)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
// this.props.showNotification("终止成功")
|
||||
if(result && result.data.status == 1){
|
||||
this.props.showNotification(result.data.message);
|
||||
this.props.rerender();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.props.showNotification("失败");
|
||||
})
|
||||
}
|
||||
|
||||
to_sponsor_page = (item, key, e) => {
|
||||
this.props.history.push(`/sponsor/${item.login}`);
|
||||
}
|
||||
|
||||
renderList = (users, userClass, current_user) => {
|
||||
|
||||
if (users && users.length > 0) {
|
||||
return users.map((item, key) => {
|
||||
// console.log(item);
|
||||
return (
|
||||
<div className="p-r-Item" key={key}>
|
||||
{/* <div className="mr10">
|
||||
<a
|
||||
href={`/users/${item.login}`}
|
||||
className="show-user-link"
|
||||
>
|
||||
<img className="p-r-photo"
|
||||
src={getImageUrl(`images/${item.image_url}`)}
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
</div> */}
|
||||
<Link to={`/users/${item.login}`} className="show-user-link">
|
||||
<img className="p-r-photo" src={getImageUrl(`images/${item.image_url}`)} alt="" />
|
||||
</Link>
|
||||
<div className="p-r-Infos">
|
||||
<a className="p-r-name hide-1 color-grey-3 font-18 task-hide " href={`/users/${item.login}`}>{item && item.username}</a>
|
||||
<div className="mr10">
|
||||
<span className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>金额:{item.amount}硬币</span>
|
||||
<span className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>累计金额:{item.accumulate}硬币</span>
|
||||
</div>
|
||||
|
||||
<div className="p-r-about">
|
||||
<span className="p-r-detail">
|
||||
<span><label>赞助时间:</label>{item.start_time} - {item.stop_time? item.stop_time:"现在"}</span>
|
||||
<span><label>{item.visible? "公开":"私有"}</label></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sponsor-item-btn">
|
||||
{item.stop_time? "":(
|
||||
<Popconfirm
|
||||
title="确认终止?"
|
||||
onConfirm={e => this.stop_sponsorship(item, key, e)}
|
||||
// onCancel={cancel}
|
||||
okText="是"
|
||||
cancelText="否"
|
||||
>
|
||||
<Button >终止赞助关系</Button>
|
||||
</Popconfirm>
|
||||
)}
|
||||
{!item.stop_time && item.sponsor_id==current_user.user_id? (
|
||||
<Button className="mt5" onClick={e => this.to_sponsor_page(item, key, e)}>修改赞助</Button>
|
||||
):""}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
} else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { users, userClass, current_user } = this.props;
|
||||
return (
|
||||
<div className="project-list minH-670">{this.renderList(users, userClass, current_user)}</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SponsorList;
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Menu, Input, Spin, Pagination, Popover, Button, Divider } from "antd";
|
||||
|
||||
import axios from "axios";
|
||||
import CoinChangeItem from "./CoinChangeItem";
|
||||
import Nodata from "../../Nodata";
|
||||
import img_array from "../../Images/array.png";
|
||||
import CoinChangeCharts from "./charts/coinChangeCharts";
|
||||
const Search = Input.Search;
|
||||
|
||||
const tempData = [
|
||||
{amount: -3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: 3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: -3, description: "des", reasons: "no reason", to_user: "串", date: "2016年1月5日"},
|
||||
{amount: 3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: -3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: 3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: -3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: 3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"},
|
||||
{amount: -3, description: "des", reasons: "no reason", to_user: "串串", date: "2016年1月5日"}
|
||||
];
|
||||
|
||||
class Wallet extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sort_by: "desc",
|
||||
isSpin: false,
|
||||
coinChangeList: undefined,
|
||||
displayList: undefined,
|
||||
total: undefined,
|
||||
category: "all",
|
||||
balance: 50,
|
||||
saerch: undefined,
|
||||
chartsData: {income:[], outcome:[]},
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.get_coin_changes();
|
||||
};
|
||||
|
||||
componentDidUpdate = () => {
|
||||
// this.get_coin_changes()
|
||||
};
|
||||
|
||||
componentWillReceiveProps = () => {
|
||||
if (this.props.current_user)
|
||||
this.get_coin_changes();
|
||||
}
|
||||
|
||||
get_chart_data = () => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
|
||||
let url = `/wallets/balance_chart.json`;
|
||||
const {current_user} = this.props;
|
||||
let user_id = current_user && current_user.user_id;
|
||||
if (current_user){
|
||||
axios.get(url, {
|
||||
params: {
|
||||
id: user_id,
|
||||
}})
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
chartsData: result.data,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
get_coin_changes = () => {
|
||||
this.setState({
|
||||
isSpin: true
|
||||
})
|
||||
|
||||
let url = `/wallets/coin_changes.json`;
|
||||
const {category, sort_by, page, limit} = this.state;
|
||||
const {current_user} = this.props;
|
||||
let user_id = current_user && current_user.user_id;
|
||||
if (current_user){
|
||||
axios.get(url, {
|
||||
params: {
|
||||
id: user_id,
|
||||
category: category,
|
||||
sort_direction: sort_by,
|
||||
page: page,
|
||||
limit: limit,
|
||||
}})
|
||||
.then((result) => {
|
||||
// console.log(result);
|
||||
this.setState({
|
||||
coinChangeList: result.data.coin_changes,
|
||||
displayList: result.data.coin_changes,
|
||||
total: result.data.count,
|
||||
balance: result.data.balance,
|
||||
isSpin: false,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
changeCategory = (cate) => {
|
||||
if(cate.target.value == "charts"){
|
||||
// console.log("charts");
|
||||
this.setState({
|
||||
category: cate.target.value,
|
||||
page: 1,
|
||||
}, ()=> {this.get_chart_data();});
|
||||
return ;
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
category: cate.target.value,
|
||||
page: 1,
|
||||
}, ()=> {this.get_coin_changes();});
|
||||
}
|
||||
};
|
||||
|
||||
//切换页数
|
||||
changePage = (page) => {
|
||||
this.setState({
|
||||
page: page
|
||||
}, ()=>{this.get_coin_changes();})
|
||||
};
|
||||
|
||||
// 排序
|
||||
ChangeSoryBy = (e) => {
|
||||
this.setState({
|
||||
sort_by: e.key,
|
||||
page: 1,
|
||||
}, ()=>{this.get_coin_changes();})
|
||||
// this.get_coin_changes();
|
||||
console.log(e.key);
|
||||
};
|
||||
|
||||
changeSearchValue = (e) => {
|
||||
this.setState({
|
||||
search: e.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
menu =()=> (
|
||||
<Menu onClick={this.ChangeSoryBy}>
|
||||
<Menu.Item key="desc">时间从近到远排序</Menu.Item>
|
||||
<Menu.Item key="asc">时间从远到近排序</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
category_button=(category)=>{
|
||||
const { current_user, user } = this.props;
|
||||
const button_lists =
|
||||
user && current_user && user.login === current_user.login
|
||||
? [
|
||||
{ type: "all", name: "所有" },
|
||||
{ type: "income", name: "收入" },
|
||||
{ type: "outcome", name: "支出" },
|
||||
{ type: "charts", name: "查看统计" },
|
||||
]
|
||||
:
|
||||
[];
|
||||
|
||||
let list = button_lists.map((item, key) => {
|
||||
return (
|
||||
<span key={key} className="pr15">
|
||||
<Button
|
||||
type={
|
||||
(category && category === item.type) || (!category && !item.type)
|
||||
? "primary"
|
||||
: "default"
|
||||
}
|
||||
ghost={
|
||||
(category && category === item.type) || (!category && !item.type)
|
||||
}
|
||||
value={item.type}
|
||||
onClick={this.changeCategory}
|
||||
>
|
||||
{item.name}
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
})
|
||||
return list;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { current_user, user } = this.props;
|
||||
const { category , sort_by, chartsData } = this.state;
|
||||
const { displayList, coinChangeList, isSpin, total, search, limit, page, balance} = this.state;
|
||||
|
||||
const coinChangeItem = displayList && displayList.length > 0 ?
|
||||
<CoinChangeItem
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
coinChanges={displayList}
|
||||
></CoinChangeItem>:
|
||||
<Nodata _html={`暂时没有项目`} />;
|
||||
|
||||
const displayComponent =
|
||||
category === "charts"? <CoinChangeCharts chartsData={chartsData}></CoinChangeCharts>
|
||||
:
|
||||
coinChangeItem;
|
||||
|
||||
return (
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="list-r-operation">
|
||||
{/* <Search
|
||||
placeholder="输入关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={this.get_coin_changes}
|
||||
className="list-r-Search"
|
||||
value={search}
|
||||
onChange={this.changeSearchValue}
|
||||
/> */}
|
||||
<div>
|
||||
|
||||
<Popover content={this.menu()} trigger={["click"]} placement="bottom">
|
||||
<a className="ant-dropdown-link">
|
||||
<span className="color-blue font-16">
|
||||
排序 <img src={img_array} alt="" width="10px" />
|
||||
</span>
|
||||
</a>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<div className="infosType">余额:{balance}</div>
|
||||
<div className="infosType">
|
||||
<div>{this.category_button(category)}</div>
|
||||
|
||||
</div>
|
||||
{user && current_user && user.login === current_user.login?
|
||||
displayComponent
|
||||
:
|
||||
<Nodata _html={`暂时没有项目`} />
|
||||
}
|
||||
{
|
||||
total && total > limit && category != "charts"?
|
||||
<div className="edu-txt-center pt30 mb30 border-top-grey">
|
||||
<Pagination
|
||||
simple
|
||||
defaultCurrent={page}
|
||||
total={total}
|
||||
pageSize={limit}
|
||||
onChange={this.changePage}
|
||||
></Pagination>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
</Spin>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default Wallet;
|
||||
|
|
@ -475,10 +475,12 @@ class LoginRegisterComponent extends Component {
|
|||
|
||||
if (this.state.codes === undefined || this.state.codes == ""||this.state.codes.length===0) {
|
||||
// this.openNotification(`请输入验证码`,2);
|
||||
this.setState({
|
||||
Phonenumberisnotcosyzm:"验证码不能为空",
|
||||
})
|
||||
return
|
||||
/*****
|
||||
// this.setState({
|
||||
// Phonenumberisnotcosyzm:"验证码不能为空",
|
||||
// })
|
||||
// return
|
||||
******/
|
||||
} else if (this.state.passwords === undefined || this.state.passwords == "" ||this.state.passwords.length===0) {
|
||||
this.setState({
|
||||
Phonenumberisnotcosymmm:"密码不能为空",
|
||||
|
|
@ -503,16 +505,18 @@ class LoginRegisterComponent extends Component {
|
|||
if(this.props.weixinlogin){
|
||||
url= '/weapps/register.json';
|
||||
}else{
|
||||
url = "/accounts/register.json";
|
||||
url = "/accounts/remote_register.json";
|
||||
}
|
||||
|
||||
axios.post(url, {
|
||||
login: this.state.logins,
|
||||
// login: this.state.logins,
|
||||
email: this.state.logins,
|
||||
password: this.state.passwords,
|
||||
code: this.state.codes,
|
||||
username: this.state.codes,
|
||||
platform: "forge"
|
||||
}).then((result) => {
|
||||
if(result){
|
||||
if(result.data.status===-2){
|
||||
if(result.data.status!=0){
|
||||
if(result.data.message==="验证码不正确"){
|
||||
this.setState({
|
||||
Phonenumberisnotcosyzm:"验证码不正确",
|
||||
|
|
@ -1181,12 +1185,12 @@ class LoginRegisterComponent extends Component {
|
|||
onfocus="this.removeAttribute('readonly')" style={{
|
||||
width:'210px',
|
||||
height:'38px',
|
||||
}} placeholder="请输入验证码"
|
||||
}} placeholder="请输入用户名"
|
||||
onChange={this.codesonChange}
|
||||
value={codes}
|
||||
>
|
||||
</Input>
|
||||
{
|
||||
{/* {
|
||||
getverificationcodes === undefined ?
|
||||
<Button className=" ml5 font-14" disabled style={{"width": "120px","text-align":"center", "height": "45px",}}
|
||||
size={"large"}>重新发送{seconds}s</Button>
|
||||
|
|
@ -1196,7 +1200,7 @@ class LoginRegisterComponent extends Component {
|
|||
:
|
||||
<Button className=" ml5 font-14 " type="primary" style={{"width": "120px","text-align":"center", "height": "45px",}}
|
||||
onClick={() => this.getverificationcode()} size={"large"}>重新发送</Button>
|
||||
}
|
||||
} */}
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue