mirror of https://github.com/sunface/rust-course
parent
a5f9c744c2
commit
f6fc6ddc84
@ -0,0 +1,79 @@
|
|||||||
|
import {Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast } from "@chakra-ui/react"
|
||||||
|
import Card from "components/card"
|
||||||
|
import Nav from "layouts/nav/nav"
|
||||||
|
import PageContainer from "layouts/page-container"
|
||||||
|
import Sidebar from "layouts/sidebar/sidebar"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
import {adminLinks, followLinks} from "src/data/links"
|
||||||
|
import { requestApi } from "utils/axios/request"
|
||||||
|
import TagCard from "components/tags/tag-card"
|
||||||
|
import { useRouter } from "next/router"
|
||||||
|
import Link from "next/link"
|
||||||
|
import { ReserveUrls } from "src/data/reserve-urls"
|
||||||
|
import { Tag } from "src/types/tag"
|
||||||
|
import { route } from "next/dist/next-server/server/router"
|
||||||
|
import PageContainer1 from "layouts/page-container1"
|
||||||
|
import Empty from "components/empty"
|
||||||
|
|
||||||
|
|
||||||
|
const FollowersPage = () => {
|
||||||
|
const [tags, setTags] = useState([])
|
||||||
|
const router = useRouter()
|
||||||
|
const toast = useToast()
|
||||||
|
const getTags = () => {
|
||||||
|
requestApi.get(`/tag/all`).then((res) => setTags(res.data)).catch(_ => setTags([]))
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getTags()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const editTag = (tag: Tag) => {
|
||||||
|
router.push(`${ReserveUrls.Admin}/tag/${tag.name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteTag= async (id) => {
|
||||||
|
await requestApi.delete(`/tag/${id}`)
|
||||||
|
getTags()
|
||||||
|
toast({
|
||||||
|
description: "删除成功",
|
||||||
|
status: "success",
|
||||||
|
duration: 2000,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageContainer1>
|
||||||
|
<Box display="flex">
|
||||||
|
<Sidebar routes={followLinks} title="我的关注" />
|
||||||
|
<Card ml="4" p="6" width="100%">
|
||||||
|
<Flex alignItems="center" justify="space-between">
|
||||||
|
<Heading size="md">标签列表({tags.length})</Heading>
|
||||||
|
<Button colorScheme="teal" size="sm" _focus={null}><Link href={`${ReserveUrls.Admin}/tag/new`}>新建标签</Link></Button>
|
||||||
|
</Flex>
|
||||||
|
{
|
||||||
|
tags.length === 0 ?
|
||||||
|
<Empty />
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<VStack mt="4">
|
||||||
|
{tags.map(tag =>
|
||||||
|
<Box width="100%" key={tag.id}>
|
||||||
|
<TagCard tag={tag} showActions={true} mt="4" onEdit={() => editTag(tag)} onDelete={() => deleteTag(tag.id)} />
|
||||||
|
<Divider mt="5" />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</VStack>
|
||||||
|
<Center><Text layerStyle="textSecondary" fontSize="sm" mt="5">没有更多标签了</Text></Center>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
</PageContainer1>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default FollowersPage
|
||||||
|
|
@ -0,0 +1,97 @@
|
|||||||
|
import { Text, Box, Heading, Image, Divider, useToast, HStack, Slider, SliderTrack, SliderFilledTrack, SliderThumb, Wrap, WrapItem } from "@chakra-ui/react"
|
||||||
|
import Card from "components/card"
|
||||||
|
import Sidebar from "layouts/sidebar/sidebar"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
import { followLinks } from "src/data/links"
|
||||||
|
import { requestApi } from "utils/axios/request"
|
||||||
|
import { useRouter } from "next/router"
|
||||||
|
import PageContainer1 from "layouts/page-container1"
|
||||||
|
import { IDType } from "src/types/id"
|
||||||
|
import Empty from "components/empty"
|
||||||
|
|
||||||
|
|
||||||
|
const TagsPage = () => {
|
||||||
|
const [tags, setTags] = useState([])
|
||||||
|
const [following, setFollowing] = useState([])
|
||||||
|
useEffect(() => {
|
||||||
|
getFollowing()
|
||||||
|
}, [])
|
||||||
|
const getFollowing = async () => {
|
||||||
|
const res = await requestApi.get(`/interaction/following/0?type=${IDType.Tag}`)
|
||||||
|
const ids = []
|
||||||
|
for (const f of res.data) {
|
||||||
|
ids.push(f.id)
|
||||||
|
}
|
||||||
|
setFollowing(res.data)
|
||||||
|
|
||||||
|
const res1 = await requestApi.post(`/tag/ids`, ids)
|
||||||
|
setTags(res1.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTagWeight = tag => {
|
||||||
|
for (const f of following) {
|
||||||
|
if (f.id === tag.id) {
|
||||||
|
return f.weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageContainer1>
|
||||||
|
<Box display="flex">
|
||||||
|
<Sidebar routes={followLinks} title="我的关注" />
|
||||||
|
<Card ml="4" p="6" width="100%">
|
||||||
|
<Text fontSize=".95rem" fontWeight="600">Adjust tag weight to modify your home feed. Higher values mean more appearances.</Text>
|
||||||
|
<Divider my="6" />
|
||||||
|
{
|
||||||
|
tags.length === 0 ?
|
||||||
|
<Empty />
|
||||||
|
:
|
||||||
|
<Wrap spacing="10px">
|
||||||
|
|
||||||
|
{tags.map(tag =>
|
||||||
|
<WrapItem width={["100%","100%","100%","31%"]}><FollowingTag key={tag.id} tag={tag} weight={getTagWeight(tag)} /> </WrapItem>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
</Wrap>
|
||||||
|
}
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
</PageContainer1>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default TagsPage
|
||||||
|
|
||||||
|
|
||||||
|
function FollowingTag(props) {
|
||||||
|
const [weight, setWeight] = React.useState(props.weight)
|
||||||
|
const onWeightChange = async w => {
|
||||||
|
await requestApi.post(`/interaction/following/weight`, { id: props.tag.id, weight: weight })
|
||||||
|
setWeight(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card shadowed mt="2" width="100%">
|
||||||
|
<HStack spacing="4">
|
||||||
|
<Image src={props.tag.icon} width="50px" />
|
||||||
|
<Box>
|
||||||
|
<Heading size="sm">{props.tag.title}</Heading>
|
||||||
|
<Text>#{props.tag.name}</Text>
|
||||||
|
</Box>
|
||||||
|
</HStack>
|
||||||
|
<Box px="1">
|
||||||
|
<Slider min={1} max={10} mt="4" size="sm" focusThumbOnChange={false} value={weight} onChange={w => setWeight(w)} onChangeEnd={onWeightChange}>
|
||||||
|
<SliderTrack>
|
||||||
|
<SliderFilledTrack />
|
||||||
|
</SliderTrack>
|
||||||
|
<SliderThumb _focus={null} fontSize="sm" boxSize="32px" children={weight} />
|
||||||
|
</Slider>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
import {Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast } from "@chakra-ui/react"
|
||||||
|
import Card from "components/card"
|
||||||
|
import Nav from "layouts/nav/nav"
|
||||||
|
import PageContainer from "layouts/page-container"
|
||||||
|
import Sidebar from "layouts/sidebar/sidebar"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
import {adminLinks, followLinks} from "src/data/links"
|
||||||
|
import { requestApi } from "utils/axios/request"
|
||||||
|
import TagCard from "components/tags/tag-card"
|
||||||
|
import { useRouter } from "next/router"
|
||||||
|
import Link from "next/link"
|
||||||
|
import { ReserveUrls } from "src/data/reserve-urls"
|
||||||
|
import { Tag } from "src/types/tag"
|
||||||
|
import { route } from "next/dist/next-server/server/router"
|
||||||
|
import PageContainer1 from "layouts/page-container1"
|
||||||
|
import Empty from "components/empty"
|
||||||
|
|
||||||
|
|
||||||
|
const UsersPage = () => {
|
||||||
|
const [tags, setTags] = useState([])
|
||||||
|
const router = useRouter()
|
||||||
|
const toast = useToast()
|
||||||
|
const getTags = () => {
|
||||||
|
requestApi.get(`/tag/all`).then((res) => setTags(res.data)).catch(_ => setTags([]))
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getTags()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const editTag = (tag: Tag) => {
|
||||||
|
router.push(`${ReserveUrls.Admin}/tag/${tag.name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteTag= async (id) => {
|
||||||
|
await requestApi.delete(`/tag/${id}`)
|
||||||
|
getTags()
|
||||||
|
toast({
|
||||||
|
description: "删除成功",
|
||||||
|
status: "success",
|
||||||
|
duration: 2000,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageContainer1>
|
||||||
|
<Box display="flex">
|
||||||
|
<Sidebar routes={followLinks} title="我的关注" />
|
||||||
|
<Card ml="4" p="6" width="100%">
|
||||||
|
<Flex alignItems="center" justify="space-between">
|
||||||
|
<Heading size="md">标签列表({tags.length})</Heading>
|
||||||
|
<Button colorScheme="teal" size="sm" _focus={null}><Link href={`${ReserveUrls.Admin}/tag/new`}>新建标签</Link></Button>
|
||||||
|
</Flex>
|
||||||
|
{
|
||||||
|
tags.length === 0 ?
|
||||||
|
<Empty />
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<VStack mt="4">
|
||||||
|
{tags.map(tag =>
|
||||||
|
<Box width="100%" key={tag.id}>
|
||||||
|
<TagCard tag={tag} showActions={true} mt="4" onEdit={() => editTag(tag)} onDelete={() => deleteTag(tag.id)} />
|
||||||
|
<Divider mt="5" />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</VStack>
|
||||||
|
<Center><Text layerStyle="textSecondary" fontSize="sm" mt="5">没有更多标签了</Text></Center>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
</PageContainer1>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default UsersPage
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Following struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Weight int `json:"weight"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Followings []*Following
|
||||||
|
|
||||||
|
func (s Followings) Len() int { return len(s) }
|
||||||
|
func (s Followings) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s Followings) Less(i, j int) bool {
|
||||||
|
return s[i].Weight > s[j].Weight
|
||||||
|
}
|
Loading…
Reference in new issue