123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- import React, { useCallback, useMemo, useRef, useState } from 'react'
- import styles from './index.module.scss'
- // 引入编辑器组件
- // 安装---npm install braft-editor --save --force
- // npm install braft-utils --save --force
- import { ContentUtils } from 'braft-utils'
- import BraftEditor from 'braft-editor'
- // 引入编辑器样式
- import 'braft-editor/dist/index.css'
- import classNames from 'classnames'
- import { MessageFu } from '@/utils/message'
- import { fileDomInitialFu } from '@/utils/domShow'
- import { baseURL } from '@/utils/http'
- import { forwardRef, useImperativeHandle } from 'react'
- import { API_upFile } from '@/store/action/layout'
- import { Button } from 'antd'
- import { TopTypeType } from '@/pages/A2Abusiness/data'
- export type SectionArrType = {
- id: number
- txt: any
- }
- type Props = {
- check: boolean //表单校验,为fasle表示不校验
- dirCode: string //文件的code码
- isLook: boolean //是否是查看进来
- ref: any //当前自己的ref,给父组件调用
- myUrl: string //上传的api地址
- topType: TopTypeType
- }
- function ZRichTexts({ check, dirCode, isLook, myUrl, topType }: Props, ref: any) {
- const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
- {
- id: Date.now(),
- txt: BraftEditor.createEditorState('')
- }
- ])
- // 判断 富文本是否为空
- const isTxtFlag = useMemo(() => {
- let flag = false
- // 不是按章节发布,检查第一个富文本
- const txt = sectionArr[0].txt.toHTML()
- const txtRes = txt.replaceAll(' ', '').replaceAll('</p><p>', '')
- if (txtRes === '') flag = true
- if (txtRes.split('></p>').length - 1 === 1 && !txtRes.includes('class="media-')) flag = true
- return flag
- }, [sectionArr])
- const myInput = useRef<HTMLInputElement>(null)
- // 上传图片、视频
- const handeUpPhoto = useCallback(
- async (e: React.ChangeEvent<HTMLInputElement>) => {
- if (e.target.files) {
- // 拿到files信息
- const filesInfo = e.target.files[0]
- let type = ['image/jpeg', 'image/png']
- let size = 5
- let txt = '图片只支持png、jpg和jpeg格式!'
- let txt2 = '图片最大支持5M!'
- // 校验格式
- if (!type.includes(filesInfo.type)) {
- e.target.value = ''
- return MessageFu.warning(txt)
- }
- // 校验大小
- if (filesInfo.size > size * 1024 * 1024) {
- e.target.value = ''
- return MessageFu.warning(txt2)
- }
- // 创建FormData对象
- const fd = new FormData()
- // 把files添加进FormData对象(‘photo’为后端需要的字段)
- fd.append('type', 'img')
- fd.append('dirCode', dirCode)
- fd.append('file', filesInfo)
- fd.append('orderType', topType)
- e.target.value = ''
- try {
- const res = await API_upFile(fd, myUrl)
- if (res.code === 0) {
- MessageFu.success('上传成功!')
- // 在光标位置插入图片
- const newTxt = ContentUtils.insertMedias(sectionArr[0].txt, [
- {
- type: 'IMAGE',
- url: baseURL + res.data.filePath
- }
- ])
- const arr = [...sectionArr]
- arr[0].txt = newTxt
- setSectionArr(arr)
- }
- fileDomInitialFu()
- } catch (error) {
- fileDomInitialFu()
- }
- }
- },
- [dirCode, myUrl, sectionArr, topType]
- )
- // 让父组件调用的 回显 富文本
- const ritxtShowFu = useCallback((val: any) => {
- if (val) {
- if (val.txtArr) {
- const arr = val.txtArr.map((v: any) => ({
- ...v,
- txt: BraftEditor.createEditorState(v.txt)
- }))
- setSectionArr(arr)
- }
- }
- }, [])
- // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
- const fatherBtnOkFu = useCallback(() => {
- const arr: any[] = []
- sectionArr.forEach((v, i) => {
- arr.push({
- ...v,
- txt: v.txt.toHTML()
- })
- })
- const obj = {
- isSection: 'no',
- txtArr: arr
- }
- return { val: obj, flag: isTxtFlag }
- }, [isTxtFlag, sectionArr])
- // 可以让父组件调用子组件的方法
- useImperativeHandle(ref, () => ({
- ritxtShowFu,
- fatherBtnOkFu
- }))
- // 单个富文本是否输入完整
- const isOneTxtFlag = useCallback((txt: any) => {
- let flag = false
- const txtRes: string = txt.toHTML()
- const txtRes2 = txtRes.replaceAll(' ', '').replaceAll('</p><p>', '')
- if (txtRes2 === '') flag = true
- if (txtRes2.split('></p>').length - 1 === 1 && !txtRes2.includes('class="media-')) flag = true
- return flag
- }, [])
- return (
- <div className={styles.ZRichTexts}>
- <input
- id='upInput'
- type='file'
- accept='.png,.jpg,.jpeg'
- ref={myInput}
- onChange={e => handeUpPhoto(e)}
- />
- <div className={classNames('formRightZW', isLook ? 'formRightZWLook' : '')}>
- <div className='formRightZWRR'>
- <div hidden={isLook}>
- <Button
- onClick={() => {
- myInput.current?.click()
- }}
- >
- 上传图片
- </Button>
- </div>
- </div>
- </div>
- <div className={classNames('txtBox', isLook ? 'txtBoxLook' : '')}>
- {sectionArr.map((item, index) => (
- <div
- className={classNames('zztxtRow', isOneTxtFlag(item.txt) && check ? 'zztxtRowErr' : '')}
- key={item.id}
- >
- {/* 主体 */}
- <BraftEditor
- readOnly={isLook}
- placeholder='请输入内容'
- value={item.txt}
- onChange={e => {
- const arr = [...sectionArr]
- arr[index].txt = e
- setSectionArr(arr)
- }}
- imageControls={['remove']}
- />
- </div>
- ))}
- </div>
- <div className={classNames('noUpThumb', check && isTxtFlag ? 'noUpThumbAc' : '')}>
- {`请输入!`}
- </div>
- </div>
- )
- }
- export default forwardRef(ZRichTexts)
|