add report manage

pull/52/head
sunface 4 years ago
parent 17f627846e
commit 1540c7dd62

@ -1,4 +1,4 @@
import { Box, useToast } from "@chakra-ui/react" import { Box, Button, chakra, Flex, Heading, HStack, IconButton, Image, Table, Tbody, Td, Text, Th, Thead, Tr, useToast, VStack } from "@chakra-ui/react"
import Card from "components/card" import Card from "components/card"
import Sidebar from "layouts/sidebar/sidebar" import Sidebar from "layouts/sidebar/sidebar"
@ -6,28 +6,66 @@ import React, { useEffect, useState } from "react"
import { adminLinks } from "src/data/links" import { adminLinks } from "src/data/links"
import { requestApi } from "utils/axios/request" import { requestApi } from "utils/axios/request"
import PageContainer1 from "layouts/page-container1" import PageContainer1 from "layouts/page-container1"
import { getSvgIcon } from "components/svg-icon"
import { getUserName } from "utils/user"
import { IDType } from "src/types/id"
import moment from 'moment'
import { useRouter } from "next/router"
const PostsPage = () => { const PostsPage = () => {
const [reports, setReports] = useState([]) const [reports, setReports] = useState([])
const router = useRouter()
const toast = useToast() const toast = useToast()
const getConfig = async () => { const getReports = async () => {
const res = await requestApi.get(`/admin/reports`) const res = await requestApi.get(`/admin/reports`)
console.log(res.data) console.log(res.data)
setReports(res.data) setReports(res.data)
} }
useEffect(() => { useEffect(() => {
getConfig() getReports()
}, []) }, [])
const displayContent = type => {
switch (type) {
case IDType.Post:
return "文章"
case IDType.Comment:
return "评论"
default:
break;
}
}
const deleteReport = async id => {
await requestApi.delete(`/admin/report/${id}`)
getReports()
}
return ( return (
<> <>
<PageContainer1> <PageContainer1>
<Box display="flex"> <Box display="flex">
<Sidebar routes={adminLinks} title="管理员" /> <Sidebar routes={adminLinks} title="管理员" />
<Card ml="4" p="6" width="100%"> <Card ml="4" p="6" width="100%">
<Flex justifyContent="space-between" alignItems="center">
<Heading size="sm" mb="2">Report</Heading>
</Flex>
{
reports.map(r =>
<Flex alignItems="center" mt="6" justifyContent="space-between">
<HStack>
<Image src={r.reporter.avatar} width="40px" height="40px"/>
<Heading size="xs">{getUserName(r.reporter)}</Heading>
<Text fontSize=".9rem">{moment(r.created).fromNow()} <chakra.span color="teal">{displayContent(r.type)} </chakra.span> : {r.content}</Text>
</HStack>
<HStack >
<Button size="sm" onClick={() => router.push(r.url)}></Button>
<Button colorScheme="orange" size="sm" onClick={() => deleteReport(r.id)}>Report</Button>
</HStack>
</Flex>)
}
</Card> </Card>
</Box> </Box>
</PageContainer1> </PageContainer1>

@ -0,0 +1,49 @@
import { Box, Button, Flex, Heading, HStack, Image, Text, VStack } from "@chakra-ui/react"
import Card from "components/card"
import Empty from "components/empty"
import { MarkdownRender } from "components/markdown-editor/render"
import Stories from "components/story/stories"
import SEO from "components/seo"
import siteConfig from "configs/site-config"
import useSession from "hooks/use-session"
import PageContainer1 from "layouts/page-container1"
import { useRouter } from "next/router"
import React, { useEffect, useState } from "react"
import { ReserveUrls } from "src/data/reserve-urls"
import { Story } from "src/types/story"
import { Tag } from "src/types/tag"
import { requestApi } from "utils/axios/request"
import { isAdmin } from "utils/role"
import Follow from "components/interaction/follow"
import Count from "components/count"
import StoryFilters from "components/story/story-filter"
import CommentCard from "components/comments/comment"
import { Comment } from "src/types/comments"
const CommentPage = () => {
const router = useRouter()
const session = useSession()
const [comment,setComment]:[Comment,any] = useState(null)
useEffect(() => {
if (router.query.id) {
initData()
}
}, [router.query.id])
const initData = async () => {
const res = await requestApi.get(`/story/comment/${router.query.id}`)
res.data.replies = []
setComment(res.data)
console.log(res.data)
}
return (
<>
{comment && session && <CommentCard user={session.user} comment={comment} onChange={null}/>}
</>
)
}
export default CommentPage

@ -2,6 +2,7 @@ package admin
import ( import (
"database/sql" "database/sql"
"fmt"
"net/http" "net/http"
"sort" "sort"
"time" "time"
@ -18,8 +19,8 @@ const (
) )
func AddReport(targetID string, content string, reporter string) *e.Error { func AddReport(targetID string, content string, reporter string) *e.Error {
_, err := db.Conn.Exec("INSERT INTO report (target_id,type,reporter,status,created) VALUES (?,?,?,?,?)", _, err := db.Conn.Exec("INSERT INTO report (target_id,type,content,reporter,status,created) VALUES (?,?,?,?,?,?)",
targetID, models.GetIDType(targetID), reporter, StatusUndealed, time.Now()) targetID, models.GetIDType(targetID), content, reporter, StatusUndealed, time.Now())
if err != nil { if err != nil {
if e.IsErrUniqueConstraint(err) { if e.IsErrUniqueConstraint(err) {
@ -34,7 +35,7 @@ func AddReport(targetID string, content string, reporter string) *e.Error {
func GetReports(page int) ([]*models.Report, *e.Error) { func GetReports(page int) ([]*models.Report, *e.Error) {
reports := make(models.Reports, 0) reports := make(models.Reports, 0)
rows, err := db.Conn.Query("SELECT id,target_id,reporter,status,created FROM report") rows, err := db.Conn.Query("SELECT id,type,content,target_id,reporter,status,created FROM report")
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
logger.Warn("get reports error", "error", err) logger.Warn("get reports error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal) return nil, e.New(http.StatusInternalServerError, e.Internal)
@ -49,7 +50,7 @@ func GetReports(page int) ([]*models.Report, *e.Error) {
Reporter: &models.UserSimple{}, Reporter: &models.UserSimple{},
} }
var uid string var uid string
err := rows.Scan(&r.ID, &r.TargetID, &uid, &r.Status, &r.Created) err := rows.Scan(&r.ID, &r.Type, &r.Content, &r.TargetID, &uid, &r.Status, &r.Created)
if err != nil { if err != nil {
logger.Warn("scan report error", "error", err) logger.Warn("scan report error", "error", err)
continue continue
@ -57,6 +58,13 @@ func GetReports(page int) ([]*models.Report, *e.Error) {
r.Reporter.ID = uid r.Reporter.ID = uid
r.Reporter.Query() r.Reporter.Query()
switch r.Type {
case models.IDTypePost:
r.URL = fmt.Sprintf("/%s/%s", r.Reporter.Username, r.TargetID)
case models.IDTypeComment:
r.URL = fmt.Sprintf("/r/comment/%s", r.TargetID)
}
reports = append(reports, r) reports = append(reports, r)
} }
@ -64,3 +72,13 @@ func GetReports(page int) ([]*models.Report, *e.Error) {
return reports, nil return reports, nil
} }
func DeleteReport(id string) *e.Error {
_, err := db.Conn.Exec("DELETE FROM report WHERE id=?", id)
if err != nil {
logger.Warn("delete report error", "error", err)
return e.New(http.StatusInternalServerError, e.Internal)
}
return nil
}

@ -102,3 +102,20 @@ func GetReports(c *gin.Context) {
c.JSON(http.StatusOK, common.RespSuccess(res)) c.JSON(http.StatusOK, common.RespSuccess(res))
} }
func DeleteReport(c *gin.Context) {
id := c.Param("id")
currentUser := user.CurrentUser(c)
if !currentUser.Role.IsAdmin() {
c.JSON(http.StatusForbidden, common.RespError(e.NoPermission))
return
}
err := admin.DeleteReport(id)
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
c.JSON(http.StatusOK, common.RespSuccess(nil))
}

@ -85,6 +85,22 @@ func GetStoryComments(c *gin.Context) {
c.JSON(http.StatusOK, common.RespSuccess(comments)) c.JSON(http.StatusOK, common.RespSuccess(comments))
} }
func GetStoryComment(c *gin.Context) {
id := c.Param("id")
comment, err := story.GetComment(id)
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
comment.Creator = &models.UserSimple{
ID: comment.CreatorID,
}
comment.Creator.Query()
c.JSON(http.StatusOK, common.RespSuccess(comment))
}
func DeleteStoryComment(c *gin.Context) { func DeleteStoryComment(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
//only admin and owner can delete comment //only admin and owner can delete comment

@ -70,6 +70,7 @@ func (s *Server) Start() error {
r.GET("/story/post/:id", api.GetStory) r.GET("/story/post/:id", api.GetStory)
r.GET("/story/id/:type", IsLogin(), InvasionCheck(), api.GenStoryID) r.GET("/story/id/:type", IsLogin(), InvasionCheck(), api.GenStoryID)
r.GET("/story/comments/:id", api.GetStoryComments) r.GET("/story/comments/:id", api.GetStoryComments)
r.GET("/story/comment/:id", api.GetStoryComment)
r.POST("/story/comment", IsLogin(), api.SubmitComment) r.POST("/story/comment", IsLogin(), api.SubmitComment)
r.DELETE("/story/comment/:id", IsLogin(), api.DeleteStoryComment) r.DELETE("/story/comment/:id", IsLogin(), api.DeleteStoryComment)
@ -152,6 +153,7 @@ func (s *Server) Start() error {
r.GET("/admin/user/all", IsLogin(), api.AdminGetUsers) r.GET("/admin/user/all", IsLogin(), api.AdminGetUsers)
r.GET("/admin/config", IsLogin(), api.AdminConfig) r.GET("/admin/config", IsLogin(), api.AdminConfig)
r.GET("/admin/reports", IsLogin(), api.GetReports) r.GET("/admin/reports", IsLogin(), api.GetReports)
r.DELETE("/admin/report/:id", IsLogin(), api.DeleteReport)
// notification apis // notification apis
r.GET("/notifications/list/:type", IsLogin(), api.GetNotifications) r.GET("/notifications/list/:type", IsLogin(), api.GetNotifications)
r.GET("/notifications/unread", IsLogin(), api.GetUnread) r.GET("/notifications/unread", IsLogin(), api.GetUnread)

@ -290,6 +290,7 @@ var sqlTables = map[string]string{
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
target_id VARCHAR(255), target_id VARCHAR(255),
type VARCHAR(1) NOT NULL, type VARCHAR(1) NOT NULL,
content VARCHAR(255),
reporter VARCHAR(255) NOT NULL, reporter VARCHAR(255) NOT NULL,
status tinyint NOT NULL, status tinyint NOT NULL,
created DATETIME NOT NULL created DATETIME NOT NULL

@ -131,6 +131,9 @@ func GetComment(id string) (*models.Comment, *e.Error) {
&c.ID, &c.TargetID, &c.CreatorID, &rawMd, &c.Created, &c.Updated, &c.ID, &c.TargetID, &c.CreatorID, &rawMd, &c.Created, &c.Updated,
) )
if err != nil { if err != nil {
if err == sql.ErrNoRows {
return nil, e.New(http.StatusNotFound, "评论不存在")
}
logger.Warn("get comment error", "error", err) logger.Warn("get comment error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal) return nil, e.New(http.StatusInternalServerError, e.Internal)
} }

@ -4,10 +4,13 @@ import "time"
type Report struct { type Report struct {
ID int `json:"id"` ID int `json:"id"`
Type string `json:"type"`
Content string `json:"content"`
TargetID string `json:"target_id"` TargetID string `json:"target_id"`
Reporter *UserSimple Reporter *UserSimple `json:"reporter"`
Status int `json:"status"` Status int `json:"status"`
Created time.Time `json:"created"` Created time.Time `json:"created"`
URL string `json:"url"`
} }
type Reports []*Report type Reports []*Report

Loading…
Cancel
Save