From 381ad7135b946c3f3ce25dd948bbf956a8c98c2a Mon Sep 17 00:00:00 2001 From: qyzh Date: Thu, 10 Sep 2020 10:12:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=8F=91=E8=B5=9E=E5=8A=A9=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 11 + src/forge/sponsor/Sponsor.js | 119 +++++++++- src/forge/sponsor/SponsorConfirmation.js | 221 +++++++++++++++++++ src/forge/sponsor/sponsor.css | 18 ++ src/forge/sponsor/sponsor_tier_item.js | 126 +++++++---- src/forge/users/Infos.js | 28 ++- src/forge/users/sponsor/SponsorManagement.js | 190 ++++++++++++++++ src/forge/users/sponsor/sponsor_list.js | 62 ++++++ 8 files changed, 725 insertions(+), 50 deletions(-) create mode 100644 src/forge/sponsor/SponsorConfirmation.js create mode 100644 src/forge/users/sponsor/SponsorManagement.js create mode 100644 src/forge/users/sponsor/sponsor_list.js diff --git a/src/App.js b/src/App.js index 78ec2883..bb1f211c 100644 --- a/src/App.js +++ b/src/App.js @@ -30,6 +30,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({ @@ -81,6 +82,11 @@ const Sponsor = Loadable({ loader: () => import('./forge/sponsor/Sponsor'), loading: Loading, }) +// Sponsor Confirmation +const SponsorConfirmation = Loadable({ + loader: () => import('./forge/sponsor/SponsorConfirmation'), + loading: Loading, +}) class App extends Component { constructor(props) { @@ -266,6 +272,11 @@ class App extends Component { return () } }> + () + }> + () diff --git a/src/forge/sponsor/Sponsor.js b/src/forge/sponsor/Sponsor.js index 657c3bd1..5beba696 100644 --- a/src/forge/sponsor/Sponsor.js +++ b/src/forge/sponsor/Sponsor.js @@ -1,6 +1,6 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Avatar, Tag, Button, Spin } from "antd"; +import { Avatar, Tag, Button, Spin, Input, Form} from "antd"; import { Route, Switch } from "react-router-dom"; import { withRouter } from "react-router"; @@ -58,6 +58,36 @@ const tempSponsors = [ {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( +
+ + {getFieldDecorator(`description`,{ + rules: [], + initialValue: initValue ? initValue : undefined + })( + // + + )} + +
+ ) + } +} +); + class Sponsor extends Component { constructor(props) { @@ -67,6 +97,7 @@ class Sponsor extends Component { user: undefined, description: undefined, sponsors: undefined, + edit: false, }; } @@ -107,6 +138,71 @@ class Sponsor extends Component { }); } + 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; + if (user){ + user.description = value; + } + this.setState({ + user: user, + edit: false, + }); + } + + visitorTemplate = () => { + const user = this.state.user; + return ( +
+ 自我介绍: + {user && user.description? + (

{user.description}

):(

暂无自我介绍

)} +
+ ); + } + + manageTemplate = () => { + const user = this.state.user; + return ( +
+ + 自我介绍: + this.editDescription()}> + + {user && user.description? (

{user.description}

):(

暂无自我介绍

)} +
+ ); + } + + editTemplate = () => { + const user = this.state.user; + return ( +
+ 自我介绍: + this.formRef = form} + /> + + +
+ ); + } + sponsorList(){ const {sponsors} = this.state; const sponsorList = (sponsors && sponsors.length>0 ? sponsors.map((item, key)=>{ @@ -121,12 +217,22 @@ class Sponsor extends Component { render(){ const { current_user} = this.props; - const isSpin = false; - const { user } = this.state; + const { user, isSpin } = this.state; const sponsorList = this.sponsorList(); // console.log("current", current_user) // console.log("user", user) + 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 (
@@ -149,12 +255,7 @@ class Sponsor extends Component {
- 自我介绍: - {user && current_user && user.login===current_user.login? - ():""} - - {user && user.description? - (

{user.description}

):(

暂无自我介绍

)} + {content}
赞助者: diff --git a/src/forge/sponsor/SponsorConfirmation.js b/src/forge/sponsor/SponsorConfirmation.js new file mode 100644 index 00000000..0e22a282 --- /dev/null +++ b/src/forge/sponsor/SponsorConfirmation.js @@ -0,0 +1,221 @@ +import React, { Component } from "react"; +import { Link } from "react-router-dom"; +import { Avatar, Tag, Button, Spin, Input, Divider, Form, Radio, Alert, message} 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 SponsorConfirmation = Form.create()( +class extends Component{ + + constructor(props) { + super(props); + this.state = { + isSpin: false, + user: undefined, + tier: undefined, + single: true, + balance: undefined, + }; + } + + componentDidMount = () => { + this.fetchUser(); + this.fetchTierInformation(); + 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 = () => { + //TODO: 和后端交互 + this.setState({ + tier: tempData + }) + } + + fetchBalance = () => { + this.setState({ + balance: tempBalance + }) + } + + 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 + }) + } + + submit = () => { + const value = this.props.form.getFieldsValue(); + console.log(value); + message.success("赞助成功!"); + } + + render(){ + const {tier_id, username} = this.props.match.params; + const {current_user, form} = this.props; + const {user, isSpin, tier, balance} = this.state; + const {getFieldDecorator} = form; + + const current_username = current_user && current_user.username; + const alert_text = this.state.single? `您选择了单次付费,本次扣除${tier && tier.amount}硬币` + :`您选择了按月付费,每月20日将扣除${tier && tier.amount}硬币`; + + // console.log("user", user) + // console.log("current user", current_user); + + const radioStyle = { + display: 'block', + height: '30px', + lineHeight: '30px', + }; + + return ( +
+ +
+
+
+

+ + 赞助{user && user.username}/赞助等级确认 +

+

+ 赞助者为 + + {current_user && current_user.username} +

+ +

所选赞助等级

+

{tier && tier.amount}硬币

+

{tier && tier.description}

+ +
+
+ +
+
+
+ + {getFieldDecorator(`single`,{ + rules: [{ + required: true + }], + initialValue: true + })( + this.changeSingle(e)}> + 单次付费 + 按月支付 + + )} + +

本次支付金额{tier && tier.amount}硬币

+

{this.state.single? "单次付费": "即日起-次月20日"}

+ + +
支付信息
+
+
+ +
+
+
{current_user && current_user.username}
+
硬币余额{balance}
+
+
+ + + 赞助关系可见性 + + {getFieldDecorator(`private`,{ + rules: [{ + required: true + }], + initialValue: false + })( + + 所有人可见 + 私密 + + )} + + + +
+
+
+
+
+ ); + } +}); + + +export default withRouter( + ImageLayerOfCommentHOC({ + imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget", + parentSelector: ".newMain", + })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(SponsorConfirmation)))) + ); + \ No newline at end of file diff --git a/src/forge/sponsor/sponsor.css b/src/forge/sponsor/sponsor.css index e52ca123..707819e8 100644 --- a/src/forge/sponsor/sponsor.css +++ b/src/forge/sponsor/sponsor.css @@ -17,4 +17,22 @@ 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-confirmation-inline{ + display: inline-block; } \ No newline at end of file diff --git a/src/forge/sponsor/sponsor_tier_item.js b/src/forge/sponsor/sponsor_tier_item.js index bd932bc0..c3f15ea1 100644 --- a/src/forge/sponsor/sponsor_tier_item.js +++ b/src/forge/sponsor/sponsor_tier_item.js @@ -1,6 +1,6 @@ import React, { Component } from "react"; import { Link } from "react-router-dom"; -import { Avatar, Tag, Button, Spin, Icon, Modal, Input, Form} from "antd"; +import { Avatar, Tag, Button, Spin, Icon, Modal, Input, Form, message, Popconfirm, Divider} from "antd"; import { Route, Switch } from "react-router-dom"; import { withRouter } from "react-router"; // import { EditOutlined } from "@ant-design/icons"; @@ -40,6 +40,7 @@ class extends Component{ {getFieldDecorator(`amount`,{ rules: [{ message: '必填字段!', + pattern: /^[0-9]+$/, required: true }], initialValue: initValue1 ? initValue1 : undefined @@ -48,7 +49,7 @@ class extends Component{ )} - {getFieldDecorator(`name`,{ + {getFieldDecorator(`description`,{ rules: [{ message: '必填字段!', required: true @@ -73,16 +74,41 @@ class SponsorTierItem extends Component{ this.state = { tiers: props.tiers, - new_tier: false, - visible: false, + new_tier: undefined, edit: edit, + isSpin: false, } } componentDidMount = () => { // console.log(this.props.tiers) + this.fetchUser(); } + 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; edit[key] = true; @@ -92,56 +118,70 @@ class SponsorTierItem extends Component{ } confirmEdit = (item, key, e) => { + if (this.state.new_tier == key){ + console.log("new tier"); + } console.log("key", key, "item", item) let values = this.formRef.getItemsValue(); console.log("values:", values) // TODO: 在此处加入对后端的修改请求 - var edit = this.state.edit; + var {tiers, edit} = this.state; + tiers[key] = values; edit[key] = false; this.setState({ - edit:edit + tiers: tiers, + edit: edit, + new_tier: undefined }) } - canelEdit = (item, key, e) => { - var edit = this.state.edit; - edit[key] = false; - this.setState({ - edit:edit - }) - } - - showModal = () => { + cancelEdit = (item, key, e) => { let {tiers, edit} = this.state; - // this.setState({ - // visible: true - // }) - } - - hideModal = () => { + tiers.pop(); + edit.pop(); this.setState({ - visible: false + tiers: tiers, + edit: edit, + new_tier: undefined }) } - createTier = () => { + newTier = () => { + if (this.state.new_tier !== undefined){ + message.info("请先完成当前编辑") + return; + } + + let {tiers, edit} = this.state; + tiers.push({amount: 1, description: ""}) + edit.push(true); this.setState({ - visible: false + tiers: tiers, + edit: edit, + new_tier: tiers.length - 1, }) } - newTierModal = () => { - return ( - -

12312312

-
- ); + deleteTier = (item, key, e) => { + // TODO: 此处向后端发送请求删除 + let {tiers, edit} = this.state; + + tiers.splice(key, 1) + edit.splice(key, 1) + this.setState({ + tiers: tiers, + edit: edit, + }) + } + + toConformation = (item, key, e) => { + const {user} = this.state + this.setState({ + route_type: undefined + }) + this.props.history.push(`/sponsor_confirmation/${user && user.login}/${item.id}`) } visitorTemplate = (item, key) => { @@ -150,7 +190,7 @@ class SponsorTierItem extends Component{
金额:{item.amount} - +
描述:{item.description} @@ -168,7 +208,15 @@ class SponsorTierItem extends Component{
描述:{item.description} - + this.deleteTier(item, key, e)} + // onCancel={cancel} + okText="是" + cancelText="否" + > + + ,
); @@ -203,7 +251,8 @@ class SponsorTierItem extends Component{ render() { const {tiers} = this.state; - const { current_user, user} = this.props; + const { current_user} = this.props; + const {user} = this.state; const renderList = ( tiers && tiers.length > 0 ? tiers.map((item, key) => { @@ -247,10 +296,9 @@ class SponsorTierItem extends Component{
{renderList}
{current_user && user && user.login === current_user.login ? - ( ): + ( ): "" } - {this.newTierModal()}
) } diff --git a/src/forge/users/Infos.js b/src/forge/users/Infos.js index ee59e55c..434197fe 100644 --- a/src/forge/users/Infos.js +++ b/src/forge/users/Infos.js @@ -40,6 +40,10 @@ const Wallet = Loadable({ loader: () => import("./sponsor/wallet"), loading: Loading, }); +const SponsorManagement = Loadable({ + loader: () => import("./sponsor/SponsorManagement"), + loading: Loading, +}) class Infos extends Component { constructor(props) { super(props); @@ -125,6 +129,14 @@ class Infos extends Component { this.props.history.push(`/sponsor/${user && user.login}`) } + sponsor_management_link = () => { + const {user} = this.state + this.setState({ + route_type: undefined + }) + this.props.history.push(`/users/${user && user.login}/sponsor_management`) + } + wallet_link = () => { const {user} = this.state this.setState({ @@ -185,7 +197,13 @@ class Infos extends Component { 修改资料 - +
@@ -307,7 +325,7 @@ class Infos extends Component {

-
  • this.sponsor_link()}> +
  • this.sponsor_management_link()}>

    赞助管理 @@ -341,6 +359,12 @@ class Infos extends Component { return ; }} > + { + return ; + }} + > { diff --git a/src/forge/users/sponsor/SponsorManagement.js b/src/forge/users/sponsor/SponsorManagement.js new file mode 100644 index 00000000..5e43605d --- /dev/null +++ b/src/forge/users/sponsor/SponsorManagement.js @@ -0,0 +1,190 @@ +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 SponsorList from "./sponsor_list"; +const Search = Input.Search; + +const tempData = [ + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, + {image_url: "avatars/User/b", username: "万山川", user_id: 1369, login:"alpc104", format_time: "2020-08-01"}, +]; + + +class SponsorManagement extends Component{ + + constructor(props) { + super(props); + this.state = { + page: 1, + limit: 15, + sort_by: undefined, + totalCount: undefined, + isSpin: false, + coinChangeList: undefined, + total: undefined, + category: undefined, + is_public: undefined, + sponsors: undefined, + }; + } + + 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, + // }); + }; + + componentDidMount = () => { + this.get_sponsors(); + } + + get_sponsors = ()=>{ + this.setState({ + sponsors: tempData, + }) + } + + //切换页数 + 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 =()=> ( +

    + 时间从近到远排序 + 时间从远到近排序 + + ); + + 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: "已终止" }, + ] + : + []; + + let list = button_lists.map((item, key) => { + return ( + + + + ); + }) + return list; + } + + + render() { + const { current_user, user } = this.props; + const { category , is_public, sponsors } = this.state; + const { coinChangeList, isSpin, total, search, limit, page } = this.state; + return ( + +
    + + +
    +
    +
    {this.category_button(category)}
    + +
    + {sponsors && sponsors.length > 0 ? + + : + + } + { + total && total > limit ? +
    + +
    + : + "" + } +
    + ); + } +}; + +export default SponsorManagement; \ No newline at end of file diff --git a/src/forge/users/sponsor/sponsor_list.js b/src/forge/users/sponsor/sponsor_list.js new file mode 100644 index 00000000..04cdf893 --- /dev/null +++ b/src/forge/users/sponsor/sponsor_list.js @@ -0,0 +1,62 @@ +import React, { Component } from "react"; +import { getImageUrl } from "educoder"; +import FocusButton from "../../UsersList/focus_button"; +import { Button } from "antd"; +import "../../UsersList/list.css"; +class SponsorList extends Component { + + renderList = (users, userClass, current_user) => { + + if (users && users.length > 0) { + return users.map((item, key) => { + return ( +
    +
    +
    + + + +
    +
    + +
    + + 加入时间:{item.format_time} +
    + { + current_user && current_user.login === item.login ? + + : + + } +
    +
    +
    + ); + }); + } + } + render() { + const { users, userClass, current_user } = this.props; + console.log(users); + return ( + this.renderList(users, userClass, current_user) + ); + } +} + +export default SponsorList;