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 ZupAudio, { ZupAudioType } from '../ZupAudio'
import { Button, Checkbox, Input } from 'antd'
import { ArrowDownOutlined, DeleteOutlined, ArrowUpOutlined } from '@ant-design/icons'
import MyPopconfirm from '../MyPopconfirm'
export type SectionArrType = {
id: number
name: string
txt: any
fileInfo: ZupAudioType
}
type Props = {
check: boolean //表单校验,为fasle表示不校验
dirCode: string //文件的code码
isLook: boolean //是否是查看进来
ref: any //当前自己的ref,给父组件调用
myUrl: string //上传的api地址
isOne?: boolean //只显示单个富文本
upAudioBtnNone?: boolean //是否能上传无障碍音频
}
function ZRichTexts(
{ check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false }: Props,
ref: any
) {
const [sectionArr, setSectionArr] = useState([
{
id: Date.now(),
name: '',
txt: BraftEditor.createEditorState(''),
fileInfo: { fileName: '', filePath: '' }
}
])
// 是否按章节发布
const [isSection, setIsSection] = useState(false)
// 当前上传 图片 视频的索引
const nowIndexRef = useRef(0)
// 判断 富文本是否为空
const isTxtFlag = useMemo(() => {
let flag = false
// 不是按章节发布,检查第一个富文本
if (!isSection) {
const txt = sectionArr[0].txt.toHTML()
const txtRes = txt.replaceAll(' ', '').replaceAll('
', '')
if (txtRes.split('>
').length - 1 === 1 || txtRes === '') flag = true
} else {
// 按章节发布 检查 所有的 标题 和富文本
sectionArr.forEach((v, i) => {
if (!v.name) flag = true
const txt: string = v.txt.toHTML()
const txtRes = txt.replaceAll(' ', '').replaceAll('', '')
if (txtRes.split('>
').length - 1 === 1 || txtRes === '') flag = true
})
}
return flag
}, [isSection, sectionArr])
const myInput = useRef(null)
// 上传图片、视频
const handeUpPhoto = useCallback(
async (e: React.ChangeEvent) => {
if (e.target.files) {
// 拿到files信息
const filesInfo = e.target.files[0]
let type = ['image/jpeg', 'image/png', 'video/mp4']
let size = 5
let txt = '图片只支持png、jpg和jpeg格式!'
let txt2 = '图片最大支持5M!'
const isVideoFlag = filesInfo.name.endsWith('.mp4') || filesInfo.name.endsWith('.MP4')
if (isVideoFlag) {
// 上传视频
size = 500
txt = '视频只支持mp4格式!'
txt2 = '视频最大支持500M!'
}
// 校验格式
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', isVideoFlag ? 'video' : 'img')
fd.append('dirCode', dirCode)
fd.append('file', filesInfo)
e.target.value = ''
try {
const res = await API_upFile(fd, myUrl)
if (res.code === 0) {
MessageFu.success('上传成功!')
// 在光标位置插入图片
const newTxt = ContentUtils.insertMedias(sectionArr[nowIndexRef.current].txt, [
{
type: isVideoFlag ? 'VIDEO' : 'IMAGE',
url: baseURL + res.data.filePath
}
])
const arr = [...sectionArr]
arr[nowIndexRef.current].txt = newTxt
setSectionArr(arr)
}
fileDomInitialFu()
} catch (error) {
fileDomInitialFu()
}
}
},
[dirCode, myUrl, sectionArr]
)
// 让父组件调用的 回显 富文本
const ritxtShowFu = useCallback((val: any) => {
if (val) {
setIsSection(val.isSection || false)
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: isSection, //是否按章节发布
txtArr: arr
}
return { val: obj, flag: isTxtFlag }
}, [isSection, isTxtFlag, sectionArr])
// 可以让父组件调用子组件的方法
useImperativeHandle(ref, () => ({
ritxtShowFu,
fatherBtnOkFu
}))
// 点击新增章节
const addSectionFu = useCallback(() => {
if (sectionArr.length >= 20) return MessageFu.warning('最多存在20个章节')
setSectionArr([
...sectionArr,
{
id: Date.now(),
name: '',
txt: BraftEditor.createEditorState(''),
fileInfo: { fileName: '', filePath: '' }
}
])
}, [sectionArr])
// 章节音频上传成功
const upSectionFu = useCallback(
(info: ZupAudioType, index: number) => {
const arr = [...sectionArr]
arr[index].fileInfo = info
setSectionArr(arr)
},
[sectionArr]
)
// 章节音频删除
const delSectionFu = useCallback(
(index: number) => {
// console.log("ppppppppp", index);
const arr = [...sectionArr]
arr[index].fileInfo = { fileName: '', filePath: '' }
setSectionArr(arr)
},
[sectionArr]
)
// 整个章节的删除
const delSectionAllFu = useCallback(
(id: number) => {
setSectionArr(sectionArr.filter(v => v.id !== id))
},
[sectionArr]
)
// 整个章节的位移
const moveSectionFu = useCallback(
(index: number, num: number) => {
const arr = [...sectionArr]
const temp = arr[index]
arr[index] = arr[index + num]
arr[index + num] = temp
setSectionArr(arr)
},
[sectionArr]
)
// 单个富文本是否输入完整
const isOneTxtFlag = useCallback(
(name: string, txt: any) => {
let flag = false
if (!name && isSection) flag = true
const txtRes: string = txt.toHTML()
if (txtRes.replaceAll('', '').replaceAll('
', '').replaceAll(' ', '') === '')
flag = true
return flag
},
[isSection]
)
return (
handeUpPhoto(e)}
/>
{isOne ? (
) : (
setIsSection(e.target.checked)}>
按章节发布
)}
{isSection ? (
) : (
{upAudioBtnNone ? null : (
upSectionFu(info, 0)}
delFu={() => delSectionFu(0)}
dirCode={dirCode}
myUrl={myUrl}
isLook={isLook}
/>
)}
)}
{sectionArr.map((item, index) => (
0}
>
{/* 顶部 */}
upSectionFu(info, index)}
delFu={() => delSectionFu(index)}
dirCode={dirCode}
myUrl={myUrl}
isLook={isLook}
/>
moveSectionFu(index, -1)}
>
moveSectionFu(index, 1)}
>
{isLook || sectionArr.length <= 1 ? null : (
delSectionAllFu(item.id)}
Dom={}
/>
)}
{/* 主体 */}
{
const arr = [...sectionArr]
arr[index].txt = e
setSectionArr(arr)
}}
imageControls={['remove']}
/>
))}
{`请完整输入${isSection ? '标题/' : ''}正文!`}
)
}
export default forwardRef(ZRichTexts)