From 466596ffc2e3be3d2b590e962f7047adbaffe998 Mon Sep 17 00:00:00 2001 From: 15620693528 <2363140194@qq.com> Date: Tue, 9 Aug 2016 17:04:41 +0800 Subject: [PATCH] =?UTF-8?q?tag=E9=A1=B5=E9=9D=A2=E5=92=8C=20recommendHome?= =?UTF-8?q?=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scripts/actions/recommendHomeAction.js | 37 ++++ app/scripts/actions/tagAction.js | 116 ++++++++++++ .../RecommendHome/RecommendHome.jsx | 66 +++++++ app/scripts/components/RecommendHome/index.js | 17 ++ app/scripts/components/TagList/TagList.jsx | 166 ++++++++++++++++++ app/scripts/components/TagList/index.js | 25 +++ app/scripts/reducers/recommendHomeReducer.js | 18 ++ app/scripts/reducers/tagReducer.js | 63 +++++++ app/scripts/routes.js | 6 +- app/scripts/store.js | 4 + 10 files changed, 516 insertions(+), 2 deletions(-) create mode 100644 app/scripts/actions/recommendHomeAction.js create mode 100644 app/scripts/actions/tagAction.js create mode 100644 app/scripts/components/RecommendHome/RecommendHome.jsx create mode 100644 app/scripts/components/RecommendHome/index.js create mode 100644 app/scripts/components/TagList/TagList.jsx create mode 100644 app/scripts/components/TagList/index.js create mode 100644 app/scripts/reducers/recommendHomeReducer.js create mode 100644 app/scripts/reducers/tagReducer.js diff --git a/app/scripts/actions/recommendHomeAction.js b/app/scripts/actions/recommendHomeAction.js new file mode 100644 index 0000000..9bbaed6 --- /dev/null +++ b/app/scripts/actions/recommendHomeAction.js @@ -0,0 +1,37 @@ +import Request from 'superagent' + +export const RECEIVE_HOMEADS = 'RECEIVE_HOMEADS' +export const DELETE_HOMEADS = 'DELETE_HOMEADS' + +function receiveHomeads(res) { + return { + type: RECEIVE_HOMEADS, + res + } +} +function _deleteHomeAd(id) { + return { + type: DELETE_HOMEADS, + id + } +} + +export const fetchHomeads = () => { + return (dispatch) => { + return Request + .get(`/api/recommend/homeads`) + .end(function(err,res){ + dispatch(receiveHomeads(res.body.items)) + }) + } +} + +export const deleteHomeAd = (id) => { + return (dispatch) => { + return Request + .del(`/api/recommend/${id}`) + .end((err, res) => { + dispatch(_deleteHomeAd(id)) + }) + } +} \ No newline at end of file diff --git a/app/scripts/actions/tagAction.js b/app/scripts/actions/tagAction.js new file mode 100644 index 0000000..e294f73 --- /dev/null +++ b/app/scripts/actions/tagAction.js @@ -0,0 +1,116 @@ +import Request from 'superagent' + +export const TL_RECEIVE_TAG = 'TL_RECEIVE_TAG' +export const TL_RECEIVE_TAG_NEW = 'TL_RECEIVE_TAG_NEW' + +export const TL_SET_CLASSIFICATION = 'TL_SET_CLASSIFICATION' +export const TL_REMOVE_CLASSIFICATION = 'TL_REMOVE_CLASSIFICATION' + +export const TL_RECOMMEND_TAG = 'TL_RECOMMEND_TAG' +export const TL_DELETE_TAG = 'TL_DELETE_TAG' + +function receiveTag(res) { + return { + type: TL_RECEIVE_TAG, + res + } +} +function receiveTagNew(res) { + return { + type: TL_RECEIVE_TAG_NEW, + res + } +} +function _setClassification(tid, cid) { + return { + type: TL_SET_CLASSIFICATION, + tid, + cid + } +} +function _removeClassification(tid, c) { + return { + type: TL_REMOVE_CLASSIFICATION, + tid, + c + } +} +function _recommendTag(tid) { + return { + type: TL_RECOMMEND_TAG, + tid, + } +} +function _deleteTag(tid) { + return { + type: TL_DELETE_TAG, + tid, + } +} +const status = { + filter: '', + page:0, + overload: false, +} +export const fetchTag = (filter) => { + + if (filter !== status.filter) { + status.filter = filter + status.page = 0 + status.overload = true + } else { + status.overload = false + } + let params = {} + params.page = status.page + if (status.filter !== '') { + params.filter = status.filter + } + return function(dispatch) { + return Request + .get(`/api/tags`) + .query(params) + .end(function(err, res) { + status.page = res.body.nextPage + status.overload ? dispatch(receiveTagNew(res.body)) : dispatch(receiveTag(res.body)) + }) + } +} + +export const setClassification = (tid, cid) => { + return (dispatch, getState) => { + return Request + .post(`/api/tag/${tid}/class/${cid}`) + .end(function(err, res) { + dispatch(_setClassification(tid, cid)) + }) + } +} +export const removeClassification = (tid, c) => { + return (dispatch, getState) => { + return Request + .del(`/api/tag/${tid}/class/${c}`) + .end(function(err, res) { + dispatch(_removeClassification(tid, c)) + }) + } +} + +export const recommendTag = (tid) => { + return (dispatch) => { + return Request + .post(`/api/recommend/home/${tid}?type=tag`) + .end((err,res) => { + dispatch(_recommendTag(tid)) + }) + } +} +export const deleteTag = (tid) => { + return (dispatch) => { + return Request + .del(`/api/tag/${tid}`) + .end((err,res) => { + dispatch(_deleteTag(tid)) + }) + } +} \ No newline at end of file diff --git a/app/scripts/components/RecommendHome/RecommendHome.jsx b/app/scripts/components/RecommendHome/RecommendHome.jsx new file mode 100644 index 0000000..36377df --- /dev/null +++ b/app/scripts/components/RecommendHome/RecommendHome.jsx @@ -0,0 +1,66 @@ +import React,{ Component } from 'react' +import Reflux from 'reflux' +import { Row, Col } from 'react-bootstrap' +import CDN from '../../widgets/cdn' + +export default class RecommendHome extends Component{ + constructor(props) { + super(props); + + this.state = {} + this.deleteHomeAd = this._deleteHomeAd.bind(this) + } + componentWillMount() { + this.props.fetchHomeads() + } + _deleteHomeAd(id) { + if (confirm('删除这个推荐?')) { + this.props.deleteHomeAd(id) + } + } + render() { + + if (this.props.homeads) { + return ( +
+ + { + this.props.homeads.map( (ad) => { + return ( + +
+
+

+
+ +
+
+
+ +
+
+ + ) + }) + } +
+
+ ) + } else { + return (
) + } + } +} \ No newline at end of file diff --git a/app/scripts/components/RecommendHome/index.js b/app/scripts/components/RecommendHome/index.js new file mode 100644 index 0000000..a7c6ec1 --- /dev/null +++ b/app/scripts/components/RecommendHome/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux' +import RecommendHome from './RecommendHome' + +import { fetchHomeads, deleteHomeAd } from '../../actions/recommendHomeAction' +const mapActionCreators = { + fetchHomeads, + deleteHomeAd +} + +const mapStateToProps = (state) => { + const { homeads } = state.recommendHomeReducer.toJS() + return { + homeads + } +} + +export default connect(mapStateToProps, mapActionCreators)(RecommendHome) \ No newline at end of file diff --git a/app/scripts/components/TagList/TagList.jsx b/app/scripts/components/TagList/TagList.jsx new file mode 100644 index 0000000..0480003 --- /dev/null +++ b/app/scripts/components/TagList/TagList.jsx @@ -0,0 +1,166 @@ +import React,{ Component } from 'react' +const _ = require('lodash') +import { + Col, Row, Modal, Form, FormGroup, InputGroup, FormControl, Button, ButtonToolbar +} from 'react-bootstrap' +import { Link } from 'react-router' +import CDN from '../../widgets/cdn' +import If from '../../widgets/if' + +export default class TagList extends Component{ + constructor(props) { + super(props) + + this.state = { + query:'', + filter:'', + selectedTag: null + } + this.onChangeFilter = (e) => this.setState({ + query: this.props.classifications[e.target.value].name, + // filter:e.target.value + }) + this.onChangeQuery = (e) => this.setState({query:e.target.value}) + this.search = () => this.props.fetchTag(this.state.query) + + this.setTagClassification = (tid,cid) => this._setTagClassification(tid,cid) + this.removeTagClassification = (tid,c) => this._removeTagClassification(tid,c) + this.openTag = (tag) => this.setState({ selectedTag: tag }) + this.closeTag = (tag) => this.setState({ selectedTag: null }) + + this.recommendTag = (tid) => this._recommendTag(tid) + this.deleteTag = (tid) => this._deleteTag(tid) + } + componentWillMount() { + this.props.fetchTag(this.state.query) + if(!this.props.classLoaded){ + this.props.fetchTagClass() + } + } + _setTagClassification(tid,cid) { + this.state.selectedTag.cls.push(cid) + this.props.setClassification(tid,cid) + } + _removeTagClassification(tid,c) { + let index = this.state.selectedTag.cls.indexOf(c) + index !== -1 ? this.state.selectedTag.cls.splice(index,1) : null + this.props.removeClassification(tid,c) + } + _recommendTag(tid) { + if (confirm('推荐这个标签?')) { + this.props.recommendTag(tid) + } + } + _deleteTag(tid) { + if (confirm('删除这个标签?')) { + this.props.deleteTag(tid) + } + } + render() { + let modal = (
) + if (this.state.selectedTag !== null) { + let cls = _.filter(this.props.classifications, function(c){ + return this.state.selectedTag.cls.indexOf(c.id) === -1 + }.bind(this)) + modal = ( +
+ + + 已选类别 +
+ { + this.state.selectedTag.cls.map(function(c){ + return ( + this.removeTagClassification( this.state.selectedTag.id, c) } + className="label label-warning label-margin" >{_.isEmpty(this.props.classifications) ? c : this.props.classifications[c].name}); + }, this) + } +
+ 全部类别 +
+ { + cls.map((c,key) => { + return ( + this.setTagClassification(this.state.selectedTag.id, c.id) }>{c.name} + ) + }) + } +
+
+
+
+ ) + } + return( +
+
+
+ + + + + {_.map(this.props.classifications, function (c, key) { + return (); + })} + + + + + + + + + + + + + + + + +
+
+ + { + this.props.tags.map( (tag) => { + return ( + +
+
+

{tag.text}

+ {tag.counts.posts + ' 照片 ' + tag.counts.follows + ' 关注'} +
+
+ +

+ {tag.cls.map((c) => { + return ({_.isEmpty(this.props.classifications) ? c : this.props.classifications[c].name}); + })} +

+
+
+ + + this.recommendTag(tag.id)}> + this.openTag(tag)}> + this.deleteTag(tag.id) }> + +
+
+ + ) + }) + } +
+ +
Load More
+
+ {modal} +
+ ) + } +} \ No newline at end of file diff --git a/app/scripts/components/TagList/index.js b/app/scripts/components/TagList/index.js new file mode 100644 index 0000000..dd13072 --- /dev/null +++ b/app/scripts/components/TagList/index.js @@ -0,0 +1,25 @@ +import { connect } from 'react-redux' +import TagList from './TagList' +import { fetchTagClass } from '../../actions/tagClassAction' +import { fetchTag, setClassification, removeClassification, recommendTag, deleteTag } from '../../actions/tagAction' + +const mapActionCreators = { + fetchTagClass, + fetchTag, + setClassification, + removeClassification, + recommendTag, + deleteTag, +} + +const mapStateToProps = (state) => { + const { classifications, loaded } = state.tagClassReducer.toJS() + const { tags } = state.tagReducer.toJS() + return { + tags, + classifications, + classLoaded:loaded + } +} + +export default connect(mapStateToProps, mapActionCreators)(TagList) \ No newline at end of file diff --git a/app/scripts/reducers/recommendHomeReducer.js b/app/scripts/reducers/recommendHomeReducer.js new file mode 100644 index 0000000..fa8a95c --- /dev/null +++ b/app/scripts/reducers/recommendHomeReducer.js @@ -0,0 +1,18 @@ +import Immutable from 'immutable' +import { RECEIVE_HOMEADS, DELETE_HOMEADS } from '../actions/recommendHomeAction' + +export default (state = Immutable.fromJS({ homeads: [] }),action)=>{ + switch (action.type) { + case RECEIVE_HOMEADS: + return state.set('homeads',Immutable.fromJS(action.res)) + + case DELETE_HOMEADS: + return state.updateIn(['homeads'], (homeads) => { + return homeads.delete(homeads.findKey((homead) => { + return homead.get('id') === action.id + })) + }) + default: + return state + } +} \ No newline at end of file diff --git a/app/scripts/reducers/tagReducer.js b/app/scripts/reducers/tagReducer.js new file mode 100644 index 0000000..cf3070c --- /dev/null +++ b/app/scripts/reducers/tagReducer.js @@ -0,0 +1,63 @@ +import Immutable from 'immutable' +import { + TL_RECEIVE_TAG, + TL_RECEIVE_TAG_NEW, + TL_SET_CLASSIFICATION, + TL_REMOVE_CLASSIFICATION, + TL_RECOMMEND_TAG, + TL_DELETE_TAG, +} from '../actions/tagAction' + +export default (state = Immutable.fromJS({ tags:[] }),action)=>{ + switch (action.type) { + case TL_RECEIVE_TAG: + return state.updateIn(['tags'], (tags) => tags.concat(Immutable.fromJS(action.res.tags))) + case TL_RECEIVE_TAG_NEW: + return state.updateIn(['tags'], (tags) => tags.clear().concat(Immutable.fromJS(action.res.tags))) + case TL_SET_CLASSIFICATION: + return state.updateIn(['tags'], (tags) => { + return tags.update( + tags.findIndex((item) => { + return item.get('id') === action.tid + }), (item) => { + return item.updateIn(['cls'], (cls) => { + return cls.push(action.cid) + }) + } + ) + }) + case TL_REMOVE_CLASSIFICATION: + return state.updateIn(['tags'], (tags) => { + return tags.update( + tags.findIndex((item) => { + return item.get('id') === action.tid + }), (item) => { + return item.updateIn(['cls'], (cls) => { + return cls.delete(cls.findKey((cl) => { + return cl === action.c + })) + }) + } + ) + }) + case TL_RECOMMEND_TAG: + return state.updateIn(['tags'], (tags) => { + return tags.update( + tags.findIndex((item) => { + return item.get('id') === action.tid + }), (item) => { + return item + } + ) + }) + case TL_DELETE_TAG: + return state.updateIn(['tags'], (tags) => { + return tags.delete(tags.findKey((tag) => { + return tag.get('id') === action.tid + })) + }) + default: + return state + } +} + diff --git a/app/scripts/routes.js b/app/scripts/routes.js index 266c0a1..941653d 100644 --- a/app/scripts/routes.js +++ b/app/scripts/routes.js @@ -5,14 +5,16 @@ import PostList from './components/PostList/index' import UserDetail from './components/UserDetail/index' import Home from './components/Home/index' +import RecommendHome from './components/RecommendHome/index' +import TagList from './components/TagList/index' //old // import UserDetail from './components/userdetail' // import Home from './components/home'; -import RecommendHome from './components/recommendhome'; +// import RecommendHome from './components/recommendhome'; import ExplorePage from './components/explorepage'; import UserList from './components/userlist'; import SkuList from './components/skulist'; -import TagList from './components/taglist'; +// import TagList from './components/taglist'; import StickerList from './components/stickerlist'; import ArticleList from './components/articlelist'; diff --git a/app/scripts/store.js b/app/scripts/store.js index 96b9f6c..2c41f70 100644 --- a/app/scripts/store.js +++ b/app/scripts/store.js @@ -6,6 +6,8 @@ import postReducer from './reducers/postReducer' import tagClassReducer from './reducers/tagClassReducer' import userDetailReducer from './reducers/userDetailReducer' import statsReducer from './reducers/statsReducer' +import recommendHomeReducer from './reducers/recommendHomeReducer' +import tagReducer from './reducers/tagReducer' export const makeRootReducer = (asyncReducers) => { return combineReducers({ // Add sync reducers here @@ -13,6 +15,8 @@ export const makeRootReducer = (asyncReducers) => { tagClassReducer, userDetailReducer, statsReducer, + recommendHomeReducer, + tagReducer, router, ...asyncReducers })