From 4a116f9f9edee534d608d72b9e42678763a18d0f Mon Sep 17 00:00:00 2001
From: DsAco <2363140194@qq.com>
Date: Wed, 18 Oct 2017 18:16:50 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=BE=E6=8A=A5=E5=8F=8D=E9=A6=88=EF=BC=8C?=
=?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A0=B7=E5=BC=8F=E5=BC=95=E7=94=A8=E8=B0=83?=
=?UTF-8?q?=E6=95=B4=EF=BC=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/sass/metronic/customize.scss | 1 +
src/scripts/actions/feedbackAction.js | 19 ++
.../components/FeedbackList/FeedbackList.jsx | 220 +++++++++++++++---
src/scripts/components/FeedbackList/index.js | 4 +-
src/scripts/metronic/popper.js | 5 -
src/scripts/reducers/feedbackReducer.js | 28 ++-
src/scripts/widgets/index.js | 15 +-
src/scripts/widgets/plugin.js | 3 +
webpack.config.js | 6 +-
webpack.production.config.js | 14 +-
10 files changed, 255 insertions(+), 60 deletions(-)
delete mode 100644 src/scripts/metronic/popper.js
create mode 100644 src/scripts/widgets/plugin.js
diff --git a/src/sass/metronic/customize.scss b/src/sass/metronic/customize.scss
index 2e4e089..0841db9 100644
--- a/src/sass/metronic/customize.scss
+++ b/src/sass/metronic/customize.scss
@@ -60,6 +60,7 @@
cursor: default;
background-color: #337ab7;
border-color: #337ab7;
+ z-index: 5;
}
}
&.disabled {
diff --git a/src/scripts/actions/feedbackAction.js b/src/scripts/actions/feedbackAction.js
index b22049c..2923d76 100644
--- a/src/scripts/actions/feedbackAction.js
+++ b/src/scripts/actions/feedbackAction.js
@@ -8,6 +8,8 @@ export const REPORT_DELETE_REPORT = 'REPORT_DELETE_REPORT'
export const REPORT_TOGGLE_BLK = 'REPORT_TOGGLE_BLK'
export const REPORT_TOGGLE_R18 = 'REPORT_TOGGLE_R18'
+export const REPORT_REPLY_LOG = 'REPORT_REPLY_LOG'
+export const FEEDBACK_REPLY_LOG = 'FEEDBACK_REPLY_LOG'
export function deleteFeedback(id) {
return (dispatch) => {
@@ -78,6 +80,7 @@ export function toggleBlk(id) {
block: true
})
.end((err, res) => {
+ Toastr.success(`此帖子已屏蔽`)
dispatch({
type: REPORT_TOGGLE_BLK,
id
@@ -93,10 +96,26 @@ export function toggleR18(id) {
r18: true
})
.end((err, res) => {
+ Toastr.success(`此帖子已设为十八禁`)
dispatch({
type: REPORT_TOGGLE_R18,
id
})
})
}
+}
+
+export function reportPushReply(id,log) {
+ return {
+ type:REPORT_REPLY_LOG,
+ id,
+ log
+ }
+}
+export function feedbackPushReply(id,log) {
+ return {
+ type:FEEDBACK_REPLY_LOG,
+ id,
+ log
+ }
}
\ No newline at end of file
diff --git a/src/scripts/components/FeedbackList/FeedbackList.jsx b/src/scripts/components/FeedbackList/FeedbackList.jsx
index b8f2fd1..8304b58 100644
--- a/src/scripts/components/FeedbackList/FeedbackList.jsx
+++ b/src/scripts/components/FeedbackList/FeedbackList.jsx
@@ -1,12 +1,10 @@
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
-import Moment from 'moment'
import ReactPaginate from 'react-paginate'
-import { parsePage } from '../../widgets/parse'
+import { dateFormat } from '../../widgets'
-import { Row, Form, FormGroup, FormControl, Button, InputGroup, ButtonToolbar, Modal } from 'react-bootstrap'
import Lightbox from 'react-images'
-
+import Request from 'superagent'
export default class FeedbackList extends Component{
constructor(props) {
super(props)
@@ -14,6 +12,11 @@ export default class FeedbackList extends Component{
lightboxIsOpen:false,
images:[],
currentImage:0,
+ reportId:'',
+ reportContent:'您的举报已处理',
+ feedbackId:'',
+ feedbackContent:'',
+ logs:[]
}
this.deleteFeedback = (id) => confirm('Delete this Feedback?') && this.props.deleteFeedback(id)
@@ -26,7 +29,16 @@ export default class FeedbackList extends Component{
this.setState({ lightboxIsOpen: true,images:imgs,currentImage:0})
}
this.closeLightbox = () => this.setState({lightboxIsOpen:false,images:[]})
-
+ this.sendMsg = this._sendMsg.bind(this)
+ this.showReportModal = this._showReportModal.bind(this)
+ this.sendFeedbackMsg = this._sendFeedbackMsg.bind(this)
+ this.showFeedbackModal = this._showFeedbackModal.bind(this)
+
+ this.showLogs = (logs) => {
+ this.setState({logs},() => {
+ $('#logsModal').modal('show')
+ })
+ }
}
componentWillMount() {
const { fPage,rPage } = this.props
@@ -38,12 +50,76 @@ export default class FeedbackList extends Component{
this.props.getReport()
}
}
+ componentDidMount() {
+ $('#reportModal').on('hidden.bs.modal', (e) => {
+ this.setState({
+ reportId:''
+ })
+ })
+ $('#feedbackModal').on('hidden.bs.modal', (e) => {
+ this.setState({
+ feedbackId:'',
+ feedbackContent:''
+ })
+ })
+ $('#logsModal').on('hidden.bs.modal', (e) => {
+ this.setState({
+ logs:[],
+ })
+ })
+ }
formatUrl(images,caption) {
images.map((image) => {
image.src = image.url
})
return images
}
+ _sendMsg() {
+ const { reportId,reportContent } = this.state
+ Request.post(`/api/report/${reportId}/reply`)
+ .send({
+ content:reportContent
+ })
+ .end((err,res) => {
+ if(err) {
+ Toastr.error(`举报失败。`)
+ }else{
+ this.props.reportPushReply(reportId,res.text)
+ Toastr.success(`举报 已通知~`)
+ $('#reportModal').modal('hide')
+
+ }
+
+ })
+ }
+ _showReportModal(reportId) {
+ this.setState({reportId},() => {
+ $('#reportModal').modal('show')
+ })
+ }
+ _showFeedbackModal(feedbackId,content) {
+
+ this.setState({feedbackId,feedbackContent:`您的反馈 ${content} 已处理`},() => {
+ $('#feedbackModal').modal('show')
+ })
+ }
+ _sendFeedbackMsg() {
+ const { feedbackId,feedbackContent } = this.state
+ Request.post(`/api/report/${feedbackId}/reply`)
+ .send({
+ content:feedbackContent
+ })
+ .end((err,res) => {
+ if(err) {
+ Toastr.error(`反馈失败。`)
+ }else{
+ this.props.feedbackPushReply(feedbackId,res.text)
+ Toastr.success(`反馈 已通知~`)
+ $('#feedbackModal').modal('hide')
+
+ }
+ })
+ }
render() {
return(
@@ -67,7 +143,7 @@ export default class FeedbackList extends Component{
- Reporter | Reason | Created | Type | Thumbnail | Operate |
+ Reporter | Reason | Created | Type | Thumbnail | State | Operate |
{
this.props.reports.map((report) => {
@@ -77,7 +153,7 @@ export default class FeedbackList extends Component{
{report.content} |
- {Moment.unix(report.created / 1000).fromNow()} |
+ {dateFormat(report.created)} |
{
report.targetType === 'post' ?
@@ -98,19 +174,25 @@ export default class FeedbackList extends Component{
}
|
-
- this.props.deleteReport(report.id)}>
- {
- report.targetType === 'post' ?
- this.props.toggleBlk(report.targetId)}>
- :
- }
- {
- report.targetType === 'post' ?
- this.props.toggleR18(report.targetId)}>
- :
- }
-
+ {
+ report.logs.length ?
+ this.showLogs(report.logs)} className="m-badge m-badge--accent m-badge--wide">已处理
+ :未处理
+ }
+ |
+
+ {
+ report.targetType === 'post' ?
+ this.props.toggleBlk(report.targetId)}>
+ :
+ }
+ {
+ report.targetType === 'post' ?
+ this.props.toggleR18(report.targetId)}>
+ :
+ }
+ this.props.deleteReport(report.id)}>
+ this.showReportModal(report.id)}>
|
)
@@ -119,26 +201,25 @@ export default class FeedbackList extends Component{
-
-
«}
- nextLabel={»}
- breakLabel={...}
- breakClassName={"break-me"}
- pageCount={this.props.rPages}
- marginPagesDisplayed={2}
- pageRangeDisplayed={5}
- onPageChange={obj => this.props.getReport(obj.selected)}
- containerClassName={"pagination"}
- subContainerClassName={"pages pagination"}
- forcePage={this.props.rPage || 0}
- activeClassName={"active"} />
-
+
«}
+ nextLabel={»}
+ breakLabel={...}
+ breakClassName={"break-me"}
+ pageCount={this.props.rPages}
+ marginPagesDisplayed={2}
+ pageRangeDisplayed={5}
+ onPageChange={obj => this.props.getReport(obj.selected)}
+ containerClassName={"pagination"}
+ subContainerClassName={"pages pagination"}
+ forcePage={this.props.rPage || 0}
+ activeClassName={"active"}
+ />
- User | Content | Created | userAgent |
+ User | Content | Created | userAgent | State |
{
this.props.feedbacks.map((feedback) => {
@@ -154,10 +235,18 @@ export default class FeedbackList extends Component{
{feedback.content} |
- {Moment.unix(feedback.created / 1000).fromNow()} |
+ {dateFormat(feedback.created)} |
{feedback.userAgent||''} |
+
+ {
+ feedback.logs.length ?
+ this.showLogs(feedback.logs)} className="m-badge m-badge--accent m-badge--wide">已处理
+ :未处理
+ }
+ |
this.deleteFeedback(feedback.id)} className="btn btn-sm">
+ this.showFeedbackModal(feedback.id,feedback.content)}>
|
)
@@ -195,6 +284,63 @@ export default class FeedbackList extends Component{
backdropClosesModal={true}
showCloseButton={false}
/>
+
+
+
+
+
举报结果通知
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
反馈结果通知
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
处理结果
+
+
+
+ {
+ this.state.logs.map(log => {
+ return(
+
{log}
+ )
+ })
+ }
+
+
+
+
)
}
diff --git a/src/scripts/components/FeedbackList/index.js b/src/scripts/components/FeedbackList/index.js
index 851e4b6..7cf7e8b 100644
--- a/src/scripts/components/FeedbackList/index.js
+++ b/src/scripts/components/FeedbackList/index.js
@@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import FeedbackList from './FeedbackList'
-import { getFeedback, deleteFeedback,getReport, deleteReport, toggleBlk,toggleR18 } from '../../actions/feedbackAction'
+import { getFeedback, deleteFeedback,getReport, deleteReport, toggleBlk,toggleR18,reportPushReply,feedbackPushReply } from '../../actions/feedbackAction'
import { setTouid } from '../../actions/adminAction'
const mapActionCreators = {
getFeedback,
@@ -11,6 +11,8 @@ const mapActionCreators = {
deleteReport,
toggleBlk,
toggleR18,
+ reportPushReply,
+ feedbackPushReply,
setTouid,
}
diff --git a/src/scripts/metronic/popper.js b/src/scripts/metronic/popper.js
deleted file mode 100644
index 63e30d6..0000000
--- a/src/scripts/metronic/popper.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import Popper from 'popper.js'
-import Toastr from 'toastr'
-
-window.Popper = Popper
-window.Toastr = Toastr
\ No newline at end of file
diff --git a/src/scripts/reducers/feedbackReducer.js b/src/scripts/reducers/feedbackReducer.js
index 31463e1..8cbf015 100644
--- a/src/scripts/reducers/feedbackReducer.js
+++ b/src/scripts/reducers/feedbackReducer.js
@@ -1,7 +1,7 @@
import Immutable from 'immutable'
import {
- FEEDBACK_RECEIVE_DATA, FEEDBACK_DELETE_FEEDBACK,
- REPORT_RECEIVE_DATA, REPORT_DELETE_REPORT, REPORT_TOGGLE_BLK,REPORT_TOGGLE_R18
+ FEEDBACK_RECEIVE_DATA, FEEDBACK_DELETE_FEEDBACK, FEEDBACK_REPLY_LOG,
+ REPORT_RECEIVE_DATA, REPORT_DELETE_REPORT, REPORT_TOGGLE_BLK,REPORT_TOGGLE_R18,REPORT_REPLY_LOG
} from '../actions/feedbackAction'
export default (state = Immutable.fromJS({
@@ -51,6 +51,30 @@ export default (state = Immutable.fromJS({
}
)
})
+ case REPORT_REPLY_LOG:
+ return state.updateIn(['reports'], (reports) => {
+ return reports.update(
+ reports.findIndex((item) => {
+ return item.get('id') === action.id
+ }), (item) => {
+ return item.updateIn(['logs'], (logs) => {
+ return logs.push(Immutable.fromJS(action.log))
+ })
+ }
+ )
+ })
+ case FEEDBACK_REPLY_LOG:
+ return state.updateIn(['feedbacks'], (feedbacks) => {
+ return feedbacks.update(
+ feedbacks.findIndex((item) => {
+ return item.get('id') === action.id
+ }), (item) => {
+ return item.updateIn(['logs'], (logs) => {
+ return logs.push(Immutable.fromJS(action.log))
+ })
+ }
+ )
+ })
default:
return state
}
diff --git a/src/scripts/widgets/index.js b/src/scripts/widgets/index.js
index 53df311..30e7df6 100644
--- a/src/scripts/widgets/index.js
+++ b/src/scripts/widgets/index.js
@@ -1,13 +1,22 @@
import Moment from 'moment'
-
+import { parse } from 'qs'
Moment.locale('zh-cn')
export const dateFormat = (time) => {
- return Moment(time).format("D MMM, H:mm A")
+ return Moment(time).format("MMM Do, H:mm A")
}
export const dateFromNow = (time) => {
return Moment(time).fromNow()
-}
\ No newline at end of file
+}
+
+export const parsePage = (str) => {
+ const page = parse(str.substr(1)).page
+ if(page){
+ return parseInt(page)
+ }else{
+ return 0
+ }
+}
diff --git a/src/scripts/widgets/plugin.js b/src/scripts/widgets/plugin.js
new file mode 100644
index 0000000..17bdadc
--- /dev/null
+++ b/src/scripts/widgets/plugin.js
@@ -0,0 +1,3 @@
+import Toastr from 'toastr'
+
+window.Toastr = Toastr
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index f25ee1b..a454b91 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -10,11 +10,8 @@ module.exports = {
],
vendor: [
'jquery',
- // 'popper',
- path.resolve(__dirname, 'src/scripts/metronic/popper.js'),
+ path.resolve(__dirname, 'src/scripts/widgets/plugin.js'),
'bootstrap/dist/js/bootstrap.js',
- // 'admin-lte/dist/js/app.js'
- // path.resolve(__dirname, 'src/scripts/metronic/app.js')
path.resolve(__dirname, 'src/scripts/metronic/scripts.bundle.js')
]
},
@@ -69,6 +66,7 @@ module.exports = {
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
+ Popper: ['popper.js', 'default'],
}),
],
devServer: {
diff --git a/webpack.production.config.js b/webpack.production.config.js
index 4b4eaad..b7d864b 100644
--- a/webpack.production.config.js
+++ b/webpack.production.config.js
@@ -13,14 +13,11 @@ const config = {
entry: {
app: path.resolve(__dirname, 'src/scripts/main.js'),
vendor: [
- 'jquery',
- // 'popper',
- path.resolve(__dirname, 'src/scripts/metronic/popper.js'),
- 'bootstrap/dist/js/bootstrap.js',
- // 'admin-lte/dist/js/app.js'
- // path.resolve(__dirname, 'src/scripts/metronic/app.js')
- path.resolve(__dirname, 'src/scripts/metronic/scripts.bundle.js')
- ]
+ 'jquery',
+ path.resolve(__dirname, 'src/scripts/widgets/plugin.js'),
+ 'bootstrap/dist/js/bootstrap.js',
+ path.resolve(__dirname, 'src/scripts/metronic/scripts.bundle.js')
+ ]
},
output: {
path: path.resolve(__dirname, 'dist'),
@@ -73,6 +70,7 @@ const config = {
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
+ Popper: ['popper.js', 'default'],
}),
new CopyWebpackPlugin([{
from: path.resolve(__dirname, "src/index.html"),