新闻业务 -- 撰写新闻

发布于:2025-04-15 ⋅ 阅读:(86) ⋅ 点赞:(0)

各个字段 的含义: 

从前天开始觉醒了觉得自己花三百块报篮球杯这个钱不能白花,于是开始写题,结果写了两天就撑不住了,感觉自己不是吃这碗饭的,故放弃,写出生理性不适了脑阔疼+牙疼?。,。。

故回来写项目,穿插着来。。。在圈钱杯开始之前本人将尽量把算法模板多背几个。。。

页头

kerwin老师使用pageheader实现了页头,但是在antd5中这样的写法已经被废除了,所以需要尝试新写法,比如这样:

import React from 'react'
import { Breadcrumb, Typography, Button, Space } from 'antd';

const { Title } = Typography;

export default function NewsAdd() {
  return (
    <div style={{ marginBottom: 24 }}>
    <Breadcrumb items={[
      { title: 'Home' },
      { title: 'List' },
      { title: 'App' },
    ]} />
    <Space style={{ justifyContent: 'space-between', width: '100%' }}>
      <Title level={2} style={{ margin: '16px 0' }}>Page Title</Title>
      <Space>
        <Button>Cancel</Button>
        <Button type="primary">Submit</Button>
      </Space>
    </Space>
  </div>
  )
}

步骤条

组件库中有现成的,所以可以直接引入

import React, { useState }  from 'react'
import { Breadcrumb, Typography, Button, Space,Steps, message,theme } from 'antd';
import style from './News.module.css'

const { Title } = Typography;
const description = 'This is a description';
const steps = [
  {
    title: '基本信息',
    content: '新闻标题 新闻分类',
  },
  {
    title: '新闻内容',
    content: '新闻主体内容',
  },
  {
    title: '新闻提交',
    content: '保存草稿 审核提交',
  },
];

export default function NewsAdd() {
  const { token } = theme.useToken();
  const [current, setCurrent] = useState(0);
  const next = () => {
    setCurrent(current + 1);
  };
  const prev = () => {
    setCurrent(current - 1);
  };
  const items = steps.map((item) => ({
    key: item.title,
    title: item.title,
  }));
  const contentStyle = {
    lineHeight: '260px',
    textAlign: 'center',
    color: token.colorTextTertiary,
    backgroundColor: token.colorFillAlter,
    borderRadius: token.borderRadiusLG,
    border: `1px dashed ${token.colorBorder}`,
    marginTop: 16,
  };
  return (
  <div style={{ marginBottom: 24 }}>
      <Breadcrumb items={[
        { title: 'Home' },
        { title: 'List' },
        { title: 'App' },
      ]} />
      <Space style={{ justifyContent: 'space-between', width: '100%' }}>
        <Title level={2} style={{ margin: '16px 0' }}>撰写新闻</Title>
        <Space>
          <Button>Cancel</Button>
          <Button type="primary">Submit</Button>
        </Space>
      </Space>
      <Steps current={current} items={items} />
      <div className={current===0?'':style.active}> 
          11111
      </div>
      <div style={contentStyle}>{steps[current].content}</div>
      <div
        style={{
          marginTop: 24,
        }}
      >
        {current < steps.length - 1 && (
          <Button type="primary" onClick={() => next()}>
            Next
          </Button>
        )}
        {current === steps.length - 1 && (
        <>
        <Button type="primary" style={{
              margin: '0 8px',
            }} onClick={() => message.success('Processing complete!')}>
            保存草稿
          </Button>
           <Button type="primary">
           提交审核
         </Button>
         </>
        )}
        {current > 0 && (
          <Button
            style={{
              margin: '0 8px',
            }}
            onClick={() => prev()}
          >
            Previous
          </Button>
        )}
      </div>
    </div>
  )
}

大部分代码都是antd里面的,想要实现动态的就不能只是创建,而是想办法让它显示和隐藏

表单

引入一下form表单

import React, { useState, useEffect,useRef } from 'react'
import {
  Breadcrumb,
  Typography,
  Button,
  Space,
  Steps,
  message,
  theme,
  Checkbox,
  Form,
  Input,
  Select,
} from 'antd'
import style from './News.module.css'
import axios from 'axios'
import { set } from 'nprogress'

const { Title } = Typography
const description = 'This is a description'
const { Option } = Select

const onFinish = (values) => {
  console.log('Success:', values)
}
const onFinishFailed = (errorInfo) => {
  console.log('Failed:', errorInfo)
}

export default function NewsAdd() {
  const { token } = theme.useToken()
  const [current, setCurrent] = useState(0)
  const [categoryList, setCategoryList] = useState([])
  const NewsForm = useRef(null)
  const steps = [
    {
      title: '基本信息',
      content: (
        <Form
          name="basic"
          ref = {NewsForm}
          labelCol={{
            span: 4,
          }}
          wrapperCol={{
            span: 20,
          }}
          style={{
            maxWidth: 600,
            margin: '25px',
          }}
          initialValues={{
            remember: true,
          }}
          onFinish={onFinish}
          onFinishFailed={onFinishFailed}
          autoComplete="off"
        >
          <Form.Item
            label="新闻标题"
            name="title"
            rules={[
              {
                required: true,
                message: 'Please input your username!',
              },
            ]}
          >
            <Input></Input>
          </Form.Item>
          <Form.Item
            label="新闻分类"
            name="categoryId"
            rules={[
              {
                required: true,
                message: 'Please input your username!',
              },
            ]}
          >
            <Select>
              {categoryList.map((item) => (
                <Select.Option value={item.id} key={item.id}>
                  {item.title}
                </Select.Option>
              ))}
            </Select>
          </Form.Item>
        </Form>
      ),
    },
    {
      title: '新闻内容',
      content: '新闻主体内容',
    },
    {
      title: '新闻提交',
      content: '保存草稿 审核提交',
    },
  ]
  const next = () => {
    if(current === 0){
      NewsForm.current.validateFields().then((res) => {
        console.log(res)
        setCurrent(current + 1)
      }).catch((err) => {
        console.log(err)
      })
    }
    else{
      setCurrent(current + 1)
    }
  }
  const prev = () => {
    setCurrent(current - 1)
  }
  const items = steps.map((item) => ({
    key: item.title,
    title: item.title,
  }))
  useEffect(() => {
    axios.get('/categories').then((res) => {
      setCategoryList(res.data)
    })
  }, [])

  return (
    <div style={{ marginBottom: 24 }}>
      <Breadcrumb
        items={[{ title: 'Home' }, { title: 'List' }, { title: 'App' }]}
      />
      <Space style={{ justifyContent: 'space-between', width: '100%' }}>
        <Title level={2} style={{ margin: '16px 0' }}>
          撰写新闻
        </Title>
        <Space>
          <Button>Cancel</Button>
          <Button type="primary">Submit</Button>
        </Space>
      </Space>
      <Steps current={current} items={items} />
      <div>{steps[current].content}</div>
      <div
        style={{
          marginTop: 24,
        }}
      >
        {current < steps.length - 1 && (
          <Button type="primary" onClick={() => next()}>
            Next
          </Button>
        )}

        {current === steps.length - 1 && (
          <>
            <Button
              type="primary"
              style={{
                margin: '0 8px',
              }}
              onClick={() => message.success('Processing complete!')}
            >
              保存草稿
            </Button>
            <Button type="primary">提交审核</Button>
          </>
        )}
        {current > 0 && (
          <Button
            style={{
              margin: '0 8px',
            }}
            onClick={() => prev()}
          >
            Previous
          </Button>
        )}
      </div>
    </div>
  )
}

富文本编辑器

富文本编辑器也是自己导入的,用前人写好的项目

jpuri/react-draft-wysiwyg: A Wysiwyg editor build on top of ReactJS and DraftJS. https://jpuri.github.io/react-draft-wysiwyghttps://github.com/jpuri/react-draft-wysiwyg使用npm下载下来:

$ npm install --save react-draft-wysiwyg draft-js

安装它之后,需要改一下配置:vite.config.js

加个global

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';

export default defineConfig({
  plugins: [react()],
  define: {
    global: 'window'  // 解决 global 和 setImmediate 问题
  },
  server: {
    proxy: {
      '/schedule': {
        target: 'https://api.tvmaze.com', // 代理地址
        changeOrigin: true, // 允许跨域
        rewrite: (path) => path.replace(/^\/schedule/, ''), // 重写路径,去掉 /shows
      },
    },
  },
});

NewsEditor.jsx:

import React, { useState } from 'react'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import { EditorState } from 'draft-js'

export default function NewsEditor() {
  // 定义 editorState 初始状态
  const [editorState, setEditorState] = useState(EditorState.createEmpty())

  // 处理 editorState 更新
  const onEditorStateChange = (newState) => {
    setEditorState(newState)
  }

  return (
    <div>
      <Editor
        editorState={editorState}
        toolbarClassName="toolbarClassName"
        wrapperClassName="wrapperClassName"
        editorClassName="editorClassName"
        onEditorStateChange={onEditorStateChange}
      />
    </div>
  )
}

就这样水灵灵的成功

但是现在的这个不能保存数据,应该是转成html或者markdown的,最后子传父调用提交到父组件

看一下项目的文档:

React Draft Wysiwyghttps://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp 

这里有演示不同的格式之间的转换

提交

现在写提交的部分

康康这个蚂蚁编程:

最好加一个提示框

现在综合一下写路由跳转和提示框:

import React, { useState, useEffect,useRef } from 'react'
import {
  Breadcrumb,
  Typography,
  Button,
  Space,
  Steps,
  message,
  theme,
  Checkbox,
  Form,
  Input,
  Select,
  notification,
} from 'antd'
import style from './News.module.css'
import axios from 'axios'
import { set } from 'nprogress'
import NewsEditor from '../../../../src/components/news-manage/NewsEditor.jsx'
import { useNavigate } from 'react-router-dom'

const { Title } = Typography
const description = 'This is a description'
const { Option } = Select

const onFinish = (values) => {
  console.log('Success:', values)
}
const onFinishFailed = (errorInfo) => {
  console.log('Failed:', errorInfo)
}

export default function NewsAdd(props) {
  const { token } = theme.useToken()
  const [current, setCurrent] = useState(0)
  const [categoryList, setCategoryList] = useState([])

  const [formInfo, setFormInfo] = useState({})
  const [content, setContent] = useState("")
  const User = JSON.parse(localStorage.getItem('token')) 

  const NewsForm = useRef(null)
  const steps = [
    {
      title: '基本信息',
      content: (
        <Form
          name="basic"
          ref = {NewsForm}
          labelCol={{
            span: 4,
          }}
          wrapperCol={{
            span: 20,
          }}
          style={{
            maxWidth: 600,
            margin: '25px',
          }}
          initialValues={{
            remember: true,
          }}
          onFinish={onFinish}
          onFinishFailed={onFinishFailed}
          autoComplete="off"
        >
          <Form.Item
            label="新闻标题"
            name="title"
            rules={[
              {
                required: true,
                message: 'Please input your username!',
              },
            ]}
          >
            <Input></Input>
          </Form.Item>
          <Form.Item
            label="新闻分类"
            name="categoryId"
            rules={[
              {
                required: true,
                message: 'Please input your username!',
              },
            ]}
          >
            <Select>
              {categoryList.map((item) => (
                <Select.Option value={item.id} key={item.id}>
                  {item.title}
                </Select.Option>
              ))}
            </Select>
          </Form.Item>
        </Form>
      ),
    },
    {
      title: '新闻内容',
      // 留一个回调函数用于子传父
      content: <NewsEditor getContent={(value)=>{
        // console.log(value) 
        setContent(value)
      }}>
         
      </NewsEditor>,
    },
    {
      title: '新闻提交',
      content: '保存草稿 审核提交',
    },
  ]
  const next = () => {
    if(current === 0){
      NewsForm.current.validateFields().then((res) => {
        setFormInfo(res)
        setCurrent(current + 1)
      }).catch((err) => {
        console.log(err)
      })
    }
    else{
      if(content === "" || content.trim()==="<p></p>"){
        //如果收集的是空的就不放行
        message.error('新闻内容不能为空')
        return
      }
      else{
        setCurrent(current + 1)
      }
    }
  }
  const prev = () => {
    setCurrent(current - 1)
  }
  const items = steps.map((item) => ({
    key: item.title,
    title: item.title,
  }))
  useEffect(() => {
    axios.get('/categories').then((res) => {
      setCategoryList(res.data)
    })
  }, [])

  const navigate = useNavigate()
  const handleSave = (auditState) => {
    axios.post('/news', {
      ...formInfo,
      "content":content,
      "region": User.region?User.region:"全球",
      "author": User.username,
      "roleId": User.roleId,
      "auditState": auditState,
      "publishState": 0,
      "createTime": Date.now(),
      "star":0,
      "view":0,
      "publishState": 0,
    }).then((res) => {
       //这个写法已经舍弃了
      //  props.history.push(auditState===0?'/news-manage/draft':'/audit-manage/list')
      navigate(auditState === 0 ? '/news-manage/draft' : '/audit-manage/list')
     notification.info({
      message:`通知`,
      description:
      `您可以到${auditState===0?'草稿箱':'审核列表'}查看您的新闻`,
      placement: 'bottomRight',
    })
  })
}

  return (
    <div style={{ marginBottom: 24 }}>
      <Breadcrumb
        items={[{ title: 'Home' }, { title: 'List' }, { title: 'App' }]}
      />
      <Space style={{ justifyContent: 'space-between', width: '100%' }}>
        <Title level={2} style={{ margin: '16px 0' }}>
          撰写新闻
        </Title>
        <Space>
          <Button>Cancel</Button>
          <Button type="primary">Submit</Button>
        </Space>
      </Space>
      <Steps current={current} items={items} />
      <div>{steps[current].content}</div>
      <div
        style={{
          marginTop: 24,
        }}
      >
        {current < steps.length - 1 && (
          <Button type="primary" onClick={() => next()}>
            Next
          </Button>
        )}

        {current === steps.length - 1 && (
          <>
            <Button
              type="primary"
              style={{
                margin: '0 8px',
              }}
              onClick={() => handleSave(0)}
            >
              保存草稿
            </Button>
            <Button type="primary" onClick={() => handleSave(1)}>提交审核</Button>
          </>
        )}
        {current > 0 && (
          <Button
            style={{
              margin: '0 8px',
            }}
            onClick={() => prev()}
          >
            Previous
          </Button>
        )}
      </div>
    </div>
  )
}

前两天是算法day!项目没怎么推进。。。因为去打篮球杯和校赛了,校赛队名叫帮我,带,,饭,,和可 乐,靠强劲的小哥带飞成功金奖,可以去打后续的省赛了捏,省赛的队名商讨之后决定叫“搞点哦润吉吃吃”


网站公告

今日签到

点亮在社区的每一天
去签到