import { Text, Box, Heading, Image, HStack, Center, Button, Flex, FormControl, FormLabel, Input, FormErrorMessage, VStack, Textarea, Divider, useToast, Stack, StackDivider, useColorModeValue, Table, Thead, Tr, Th, Tbody, Td, CloseButton, Editable, EditablePreview, EditableInput, Select } from "@chakra-ui/react" import Card from "components/card" import Sidebar from "layouts/sidebar/sidebar" import React, { useEffect, useState } from "react" import { editorLinks } from "src/data/links" import { requestApi } from "utils/axios/request" import { useDisclosure } from "@chakra-ui/react" import { Field, Form, Formik } from "formik" import { config } from "configs/config" import TextStoryCard from "components/story/manage-story-card" import { Story } from "src/types/story" import { FaExternalLinkAlt, FaPlus, FaRegEdit } from "react-icons/fa" import { useRouter } from "next/router" import { ReserveUrls } from "src/data/reserve-urls" import Link from "next/link" import PageContainer1 from "layouts/page-container1" import Empty from "components/empty" import { IDType } from "src/types/id" import PostSelect from "components/story/post-select" import { cloneDeep, find, remove } from "lodash" import userCustomTheme from "theme/user-custom" import Tags from "components/tags/tags" import ManageStories from "components/story/manage-stories" var validator = require('validator'); const newSeries: Story = { title: '', brief: '', cover: '', type: IDType.Series } const SeriesPage = () => { const [currentSeries, setCurrentSeries]: [Story, any] = useState(null) const [series, setSeries] = useState([]) const [posts, setPosts] = useState([]) const [seriesPosts, setSeriesPosts] = useState([]) const toast = useToast() const borderColor = useColorModeValue(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark) const getSeries = () => { requestApi.get(`/story/posts/editor?type=${IDType.Series}`).then((res) => setSeries(res.data)).catch(_ => setPosts([])) } const getPosts = () => { requestApi.get(`/story/posts/editor?type=${IDType.Post}`).then((res) => setPosts(res.data)).catch(_ => setPosts([])) } useEffect(() => { getSeries() getPosts() }, []) function validateTitle(value) { let error if (!value?.trim()) { error = "标题不能为空" } if (value?.length > config.posts.titleMaxLen) { error = "标题长度不能超过128" } return error } function validateUrl(value) { let error if (value && !validator.isURL(value)) { error = "URL格式不合法" } return error } function validateBrief(value) { let error if (value && value.length > config.posts.briefMaxLen) { error = `文本长度不能超过${config.posts.briefMaxLen}` } return error } const submitSeries = async (values, _) => { // 这里必须按照顺序同步提交 await requestApi.post(`/story`, values) await requestApi.post(`/story/series/post/${values.id}`, seriesPosts) toast({ description: "提交成功", status: "success", duration: 2000, isClosable: true, }) setCurrentSeries(null) getSeries() } const editSeries = async (series: Story) => { const res = await requestApi.get(`/story/series/post/${series.id}`) setSeriesPosts(res.data) setCurrentSeries(series) } const onDeleteSeries = async (id) => { await requestApi.delete(`/story/series/post/${id}`) await requestApi.delete(`/story/post/${id}`) getSeries() toast({ description: "删除成功", status: "success", duration: 2000, isClosable: true, }) } const onPostSelect = id => { const sposts = cloneDeep(seriesPosts) if (!find(sposts, v => v.id === id)) { sposts.push({ id: id, priority: 0 }) setSeriesPosts(sposts) } } const onPostDelete = id => { const sposts = cloneDeep(seriesPosts) remove(sposts, v => v.id === id) setSeriesPosts(sposts) } const onPriorityChange = (e, s) => { if (e.currentTarget.value) { const i = parseInt(e.currentTarget.value) if (i) { s.priority = i } } else { s.priority = 0 } const sposts = cloneDeep(seriesPosts) setSeriesPosts(sposts) } const addSeries = async () => { const res = await requestApi.get(`/story/id/${IDType.Series}`) newSeries.id = res.data setSeriesPosts([]) setCurrentSeries(newSeries) } const onPinPost = async id => { await requestApi.post(`/story/pin/${id}`) getSeries() } return ( <> {currentSeries ? <> {(props) => (
{({ field, form }) => ( 标题 {form.errors.title} )} {/* {({ field, form }) => ( 发布于 {form.errors.ownerId} )} */} {({ field, form }) => ( 封面图片 {form.errors.cover} )} {({ field, form }) => ( 简介 {form.errors.brief} )} {({ field, form }) => ( 标签 currentSeries.tags = ids} /> )} {({ field, form }) => ( 关联文章 {seriesPosts?.length > 0 && }> { seriesPosts.map(s => { const post = find(posts, p => p.id === s.id) if (post) { return } return null }) }
Title Priority(desc)
{post.title} onPriorityChange(e, s)} /> onPostDelete(s.id)} _focus={null} />
}
)}
)}
: <> 系列({series.length}) { series.length === 0 ? : editSeries(story)} onDelete={(id) => onDeleteSeries(id)} showSource={false} onPin={(id) => onPinPost(id)}/> } }
) } export default SeriesPage