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(
+
+
+
+
+
+ {
+ 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
})