编辑资助页面

This commit is contained in:
qyzh 2020-09-08 10:05:27 +08:00
parent 0f5712eb0e
commit 016c0bee00
7 changed files with 747 additions and 15 deletions

View File

@ -268,7 +268,7 @@ class App extends Component {
}></Route>
<Route exact path="/sponsor/:username"
render={
(props) => (<Sponsor {...this.props} {...props} {...this.state}></Sponsor>)
(props) => (<Sponsor {...this.props}{...this.state}></Sponsor>)
}>
</Route>
<Route exact path="/"

View File

@ -1,5 +1,6 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Spin } from "antd";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
@ -7,16 +8,172 @@ 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, amount: 5, description: "这能让我感到很开心"},
{id:2, amount: 10, description: "如果您更加慷慨的话就选择这个"},
{id:3, amount: 150, description: "这能为我带来相当多的额外收入"},
{id:4, amount: 250, description: "这能为我带来相当多的额外收入"},
{id:5, amount: 500, description: "这能为我带来相当多的额外收入"},
{id:6, amount: 1000, description: "这能为我带来相当多的额外收入"},
{id:7, amount: 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"},
];
class Sponsor extends Component {
constructor(props) {
super(props);
this.state = {
isSpin: false,
user: undefined,
description: undefined,
sponsors: undefined,
};
}
componentDidMount = () => {
this.fetchUser();
this.fetchSponsors();
};
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,
});
})
.catch((error) => {
console.log(error);
this.setState({
isSpin: false,
});
});
};
fetchSponsors = () => {
this.setState({
sponsors: tempSponsors,
});
}
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 isSpin = false;
const { user } = this.state;
const sponsorList = this.sponsorList();
// console.log("current", current_user)
// console.log("user", user)
return (
<p>This is sponsor page</p>
<div className="newMain clearfix">
<Spin spinning={isSpin}>
<div className="new-content-flex">
<div className="sponsor-page-left">
<div className="bgcF">
<div className="list-l-Menu text-center pd20 ">
<div className="text-center mt15 font-16 fwb"> 成为{user && user.username}的赞助者吧</div>
<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>
</div>
<div className="bgcF">
<div className="list-l-Menu pd20 ">
<span>自我介绍:
{user && current_user && user.login===current_user.login?
(<i className="iconfont icon-bianji3 font-15 mr5"></i>):""}
</span>
{user && user.description?
(<p>{user.description}</p>):(<p></p>)}
</div>
<div className="list-l-Menu pd20 ">
赞助者:
{sponsorList}
</div>
</div>
</div>
<div className="sponsor-page-right">
<div className="bgcF">
<SponsorTierItem
{...this.props}
{...this.state}
tiers={tempData}>
</SponsorTierItem>
</div>
</div>
</div>
</Spin>
</div>
);
}

View File

@ -0,0 +1,20 @@
.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;
}

View File

@ -0,0 +1,260 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Spin, Icon, Modal, Input, Form} 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 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(`amount`,{
rules: [{
message: '必填字段!',
required: true
}],
initialValue: initValue1 ? initValue1 : undefined
})(
<Input placeholder="请输入"/>
)}
</FormItem>
<FormItem label={`描述`} >
{getFieldDecorator(`name`,{
rules: [{
message: '必填字段!',
required: true
}],
initialValue: initValue2 ? initValue2 : undefined
})(
<Input placeholder="请输入"/>
)}
</FormItem>
</Form>
)
}
});
class SponsorTierItem extends Component{
constructor(props) {
super(props)
var edit = new Array();
for(var i=0; i<props.tiers.length; i++) edit.push(false);
this.state = {
tiers: props.tiers,
new_tier: false,
visible: false,
edit: edit,
}
}
componentDidMount = () => {
// console.log(this.props.tiers)
}
editTier = (item, key, e) => {
var edit = this.state.edit;
edit[key] = true;
this.setState({
edit:edit
})
}
confirmEdit = (item, key, e) => {
console.log("key", key, "item", item)
let values = this.formRef.getItemsValue();
console.log("values:", values)
// TODO: 在此处加入对后端的修改请求
var edit = this.state.edit;
edit[key] = false;
this.setState({
edit:edit
})
}
canelEdit = (item, key, e) => {
var edit = this.state.edit;
edit[key] = false;
this.setState({
edit:edit
})
}
showModal = () => {
let {tiers, edit} = this.state;
// this.setState({
// visible: true
// })
}
hideModal = () => {
this.setState({
visible: false
})
}
createTier = () => {
this.setState({
visible: false
})
}
newTierModal = () => {
return (
<Modal
title="新增赞助等级"
visible={this.state.visible}
onCancel={this.hideModal}
onOk={this.createTier}>
<p>12312312</p>
</Modal>
);
}
visitorTemplate = (item, key) => {
return (
<ul className="list-l-Menu">
<div className="font-15 mr5">
金额{item.amount}
<Button >选择</Button>
</div>
<div className="font-15 mr5">
描述{item.description}
</div>
</ul>
);
}
manageTemplate = (item, key) => {
return (
<ul className="list-l-Menu">
<div className="font-15 mr5">
金额{item.amount}
<i className="iconfont icon-bianji3 font-15 mr5" onClick={e => this.editTier(item, key, e)}></i>
</div>
<div className="font-15 mr5">
描述{item.description}
<i className="iconfont icon-shanchu font-15"></i>
</div>
</ul>
);
}
editTemplate = (item, key) => {
return (
<ul className="list-l-Menu">
<EditTierForm
initValue1={item.amount}
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>
</ul>
);
// return (
// <ul className="list-l-Menu">
// <div className="font-15 mr5">
// 金额:<Input value={item.amount}></Input>
// </div>
// <div className="font-15 mr5">
// 描述:<Input value={item.description}></Input>
// <Button onClick={e => this.confirmEdit(item, key, e)}>确定</Button>
// <Button onClick={e => this.cancelEdit(item, key, e)}>取消</Button>
// </div>
// </ul>
// );
}
render() {
const {tiers} = this.state;
const { current_user, user} = this.props;
const renderList = (
tiers && tiers.length > 0 ? tiers.map((item, key) => {
const amount = this.state.edit[key]? (<Input></Input>):item.amount;
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>{renderList}</div>
{current_user && user && user.login === current_user.login ?
( <Button type="primary" onClick={() => this.showModal()}>新增赞助等级</Button>):
""
}
{this.newTierModal()}
</div>
)
}
}
export default SponsorTierItem;

View File

@ -36,6 +36,10 @@ const UndoEvents = Loadable({
loader: () => import("./undo_events"),
loading: Loading,
})
const Wallet = Loadable({
loader: () => import("./sponsor/wallet"),
loading: Loading,
});
class Infos extends Component {
constructor(props) {
super(props);
@ -43,7 +47,8 @@ class Infos extends Component {
isSpin: false,
user: undefined,
project_type: undefined,
route_type: undefined
route_type: undefined,
choose_wallet: undefined
};
}
@ -79,6 +84,7 @@ class Infos extends Component {
const {user} = this.state
this.setState({
project_type: type ,
choose_wallet: false,
route_type: undefined
})
let url = `/users/${user && user.login}`
@ -119,10 +125,30 @@ class Infos extends Component {
this.props.history.push(`/sponsor/${user && user.login}`)
}
wallet_link = () => {
const {user} = this.state
this.setState({
project_type: undefined,
choose_wallet: true,
route_type: 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`)
}
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 } = this.state;
// console.log("current", current_user)
// console.log("user", user)
return (
<div className="newMain clearfix">
<Spin spinning={isSpin}>
@ -159,7 +185,10 @@ class Infos extends Component {
<i className="iconfont icon-shezhi4 font-15 mr5"></i>
修改资料
</Button>
</div>
)}
{current_user && user && user.login !== current_user.login && (
<div className="user-info-star-button ">
@ -170,6 +199,13 @@ class Infos extends Component {
fontClass={"font-14 ml5"}
starText={"关注TA"}
/>
<Button
block
className="text-button-grey"
href={`/sponsor/${user && user.login}`}
>
赞助
</Button>
</div>
)}
</div>
@ -254,19 +290,32 @@ class Infos extends Component {
</p>
</div>
</div> */}
{current_user && user && current_user.id === user.id && (
{current_user && user && user.login == current_user.login && (
<div className="bgcF">
<div className="list-l-Menu">
<p className="list-l-p pd20" onClick={() => this.sponsor_link()} >
<span className="font-16 color-grey-3">
{/* <i className="iconfont icon-itsm-liuchengguanli font-15 mr5"></i> */}
Sponsor
<ul className="list-l-Menu">
<li className="MenuTitle">
<i className="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>
{/* <span className="color-blue font-16">
{user && user.undo_events}
</span> */}
</p>
</div>
</li>
<li className="" onClick={() => this.sponsor_link()}>
<p>
<span className="font-16">赞助管理</span>
<span className="color-blue">
{/* {user && user.sync_mirror_projects_count} */}
</span>
</p>
</li>
</ul>
</div>
)}
</div>
@ -286,6 +335,12 @@ 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/fan_users"
render={() => {

View File

@ -0,0 +1,43 @@
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 } = this.props;
const renderList = (
coinChanges && coinChanges.length > 0 ? coinChanges.map((item, key) => {
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" }}>金额{item.amount>0? "收入":"支出"}{Math.abs(item.amount)}硬币</p>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>变动原因{item.reasons}</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>
<span><label>{item.amount>0? "金额来源":"金额去向"}</label><a href='/users/SylorHuang'>{item.to_user}</a></span>
{/* {item.amount>0 ? <span><label>金额来源:</label>{item.to_user}</span>: <span><label>金额去向:</label>{item.to_user}</span>} */}
</span>
</div>
</div>
</div>
)
}) : ""
)
return (
<div className="project-list minH-670">
{renderList}
</div>
)
}
}
export default CoinChangeItem;

View File

@ -0,0 +1,197 @@
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";
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: 15,
sort_by: undefined,
totalCount: undefined,
isSpin: false,
coinChangeList: undefined,
displayList: undefined,
total: undefined,
category: undefined,
is_public: undefined
};
}
componentDidMount = () => {
this.get_coin_changes();
};
componentDidUpdate = () => {
// this.get_coin_changes()
};
get_coin_changes = () => {
this.setState({
coinChangeList: tempData,
displayList: tempData,
total: tempData.count,
isSpin: false,
});
};
changeCategory = (cate) => {
let resultList = this.state.coinChangeList;
switch (cate.target.value){
case "income":
resultList = resultList.filter(function(item,index,array){
return item.amount > 0;
});
break;
case "outcome":
resultList = resultList.filter(function(item,index,array){
return item.amount < 0;
});
break;
}
this.setState({
displayList: resultList,
});
};
//切换页数
changePage = (page) => {
this.state.page = page;
this.get_coin_changes();
};
// 排序
ChangeSoryBy = (e) => {
// this.state.sort_by = e.key;
// this.get_coin_changes();
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: "all", name: "所有" },
{ type: "income", name: "收入" },
{ type: "outcome", 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 , is_public } = this.state;
const { displayList, coinChangeList, isSpin, total, search, limit, page } = this.state;
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">
<div>{this.category_button(category)}</div>
</div>
{displayList && displayList.length > 0 ?
<CoinChangeItem
{...this.props}
{...this.state}
coinChanges={displayList}
></CoinChangeItem>
:
<Nodata _html={`暂时没有项目`} />
}
{
total && total > limit ?
<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;