提交 6737d2b7 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 5ff64b0f
...@@ -7,7 +7,7 @@ import EditorSimple from '@/common/editor-simple' ...@@ -7,7 +7,7 @@ import EditorSimple from '@/common/editor-simple'
import './index.less' import './index.less'
import { addExpandRead, expandReadInfo } from '../utils/request' import { addExpandRead, expandReadInfo } from '../utils/request'
const ExpandModal = forwardRef((props, ref) => { const ExpandModal = (props, ref) => {
const { const {
editor, editor,
ossClient, ossClient,
...@@ -361,6 +361,6 @@ const ExpandModal = forwardRef((props, ref) => { ...@@ -361,6 +361,6 @@ const ExpandModal = forwardRef((props, ref) => {
</div> </div>
</div> </div>
) )
}) }
export default ExpandModal export default forwardRef(ExpandModal)
import React, { useEffect, useState, useRef, useImperativeHandle, forwardRef } from 'react'; import React, { useEffect, useState, useRef, useImperativeHandle, forwardRef } from 'react'
import { Modal, Drawer, Tree, Button, Spin, Space, Input, Image } from 'antd'; import { Modal, Drawer, Tree, Button, Spin, Space, Input, Image } from 'antd'
import { LeftOutlined, RightOutlined } from '@ant-design/icons'; import { LeftOutlined, RightOutlined } from '@ant-design/icons'
import { getInfoByChapterId } from '@/pages/books/section/request'; import { getInfoByChapterId } from '@/pages/books/section/request'
import { get } from 'lodash-es'; import { get } from 'lodash-es'
import $, { event } from 'jquery'; import $, { event } from 'jquery'
import baike from '@/assets/images/editor/icon-baike.png'; import baike from '@/assets/images/editor/icon-baike.png'
import { getChapterTopic, expandReadInfo } from '../utils/request'; import { getChapterTopic, expandReadInfo } from '../utils/request'
import TopicItem from '../practice/components/topicItem'; import TopicItem from '../practice/components/topicItem'
import '../utils/iconfont'; import '../utils/iconfont'
import '@/common/preview.less'; import '@/common/preview.less'
import { clacTopicText } from '@/utils/common'; import { clacTopicText } from '@/utils/common'
import hljs from 'highlight.js'; import hljs from 'highlight.js'
import 'highlight.js/styles/github.css'; import 'highlight.js/styles/github.css'
const correctList = [ const correctList = [
'A', 'A',
...@@ -40,137 +40,135 @@ const correctList = [ ...@@ -40,137 +40,135 @@ const correctList = [
'W', 'W',
'X', 'X',
'Y', 'Y',
'Z', 'Z'
]; ]
const PreviewScreen = forwardRef((props, ref) => { const PreviewScreen = (props, ref) => {
const { editor, bookId, chapterId, gData, nowTitle } = props; const { editor, bookId, chapterId, gData, nowTitle } = props
const [loading, setLoading] = useState(false); // 展示 const [loading, setLoading] = useState(false) // 展示
const [prviewHtml, setPrviewHtml] = useState(''); // 预览html const [prviewHtml, setPrviewHtml] = useState('') // 预览html
const [open, setOpen] = useState(false); // 抽屉 const [open, setOpen] = useState(false) // 抽屉
const [toolTip, setTooltip] = useState({}); const [toolTip, setTooltip] = useState({})
const [headTitle, setHeadTitle] = useState(nowTitle); const [headTitle, setHeadTitle] = useState(nowTitle)
const [newChapterId, setNewChapterId] = useState(chapterId); const [newChapterId, setNewChapterId] = useState(chapterId)
const [opend, setOpend] = useState(false); const [opend, setOpend] = useState(false)
const [gallery, setGallery] = useState([]); const [gallery, setGallery] = useState([])
const [galleryIndex, setGalleryIndex] = useState(0); const [galleryIndex, setGalleryIndex] = useState(0)
const [isType, setIsType] = useState(''); const [isType, setIsType] = useState('')
const [secondType, setSecondType] = useState(false); const [secondType, setSecondType] = useState(false)
const [topicList, setTopicList] = useState([]); // 题库 const [topicList, setTopicList] = useState([]) // 题库
const [radioList, setRadioList] = useState([]); // 单选 const [radioList, setRadioList] = useState([]) // 单选
const [checkBoxList, setCheckBoxList] = useState([]); // 多选 const [checkBoxList, setCheckBoxList] = useState([]) // 多选
const [judgeList, setJudgeList] = useState([]); // 判断 const [judgeList, setJudgeList] = useState([]) // 判断
const [fillList, setFillList] = useState([]); // 填空 const [fillList, setFillList] = useState([]) // 填空
const [textareaList, setTextareaList] = useState([]); // 简答 const [textareaList, setTextareaList] = useState([]) // 简答
const [expandContent, setExpandContent] = useState(''); // 扩展阅读内容 const [expandContent, setExpandContent] = useState('') // 扩展阅读内容
const [previewImg, setPreviewImg] = useState(''); // 扩展阅读内容 const [previewImg, setPreviewImg] = useState('') // 扩展阅读内容
const getTopicList = async ({ practicenum, chapterid, bookid }) => { const getTopicList = async ({ practicenum, chapterid, bookid }) => {
const data = await getChapterTopic({ const data = await getChapterTopic({
position: practicenum, position: practicenum,
book_id: bookid, book_id: bookid,
chapter_id: chapterid, chapter_id: chapterid
}); })
const temp = []; const temp = []
data.forEach((item) => { data.forEach(item => {
let obj = { ...item }; let obj = { ...item }
if ([1, 2, 3].includes(parseInt(item.question_style))) { if ([1, 2, 3].includes(parseInt(item.question_style))) {
try { try {
obj.question_list = JSON.parse(item.question_list); obj.question_list = JSON.parse(item.question_list)
} catch (err) { } catch (err) {
obj.question_list = []; obj.question_list = []
} }
} }
temp.push(obj); temp.push(obj)
}); })
const tempRadio = temp.filter((item) => parseInt(item.question_style) === 1); const tempRadio = temp.filter(item => parseInt(item.question_style) === 1)
const tempCheckbox = temp.filter((item) => parseInt(item.question_style) === 2); const tempCheckbox = temp.filter(item => parseInt(item.question_style) === 2)
const tempJudge = temp.filter((item) => parseInt(item.question_style) === 3); const tempJudge = temp.filter(item => parseInt(item.question_style) === 3)
const tempFill = temp.filter((item) => parseInt(item.question_style) === 4); const tempFill = temp.filter(item => parseInt(item.question_style) === 4)
const tempTextarea = temp.filter((item) => parseInt(item.question_style) === 5); const tempTextarea = temp.filter(item => parseInt(item.question_style) === 5)
setRadioList(tempRadio); setRadioList(tempRadio)
setCheckBoxList(tempCheckbox); setCheckBoxList(tempCheckbox)
setJudgeList(tempJudge); setJudgeList(tempJudge)
setFillList(tempFill); setFillList(tempFill)
setTextareaList(tempTextarea); setTextareaList(tempTextarea)
setTopicList(temp); setTopicList(temp)
}; }
const getExpandInfo = async ({ chapterId, position }) => { const getExpandInfo = async ({ chapterId, position }) => {
const data = await expandReadInfo({ const data = await expandReadInfo({
book_id: bookId, book_id: bookId,
chapter_id: chapterId, chapter_id: chapterId,
position: position, position: position
}); })
if (data) { if (data) {
setExpandContent(data.content); setExpandContent(data.content)
}
} }
};
const handlerClick = () => { const handlerClick = () => {
const iParentW = $('.preview-content-it').innerWidth(); const iParentW = $('.preview-content-it').innerWidth()
const iParentH = $('.preview-content-it').innerHeight(); const iParentH = $('.preview-content-it').innerHeight()
const parentOffset = $('.preview-content-it').offset(); // 获取父元素相对于文档的位置 const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置
const parentRect = $('.preview-content-it')[0].getBoundingClientRect(); // 获取父元素相对于文档的位置 const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置
$('.preview-content-html').on('click', (ev) => { $('.preview-content-html').on('click', ev => {
ev.stopPropagation(); ev.stopPropagation()
const target = ev.target; const target = ev.target
const tooltip = $(target).closest('.chapter-item-tooltip'); const tooltip = $(target).closest('.chapter-item-tooltip')
const alink = $(target).closest('.chapter-item-link'); const alink = $(target).closest('.chapter-item-link')
const aGallery = $(target).closest('.chapter-gallery-container'); const aGallery = $(target).closest('.chapter-gallery-container')
const practice = $(target).closest('.chapter-practice'); const practice = $(target).closest('.chapter-practice')
const aA = $(target).closest('a'); const aA = $(target).closest('a')
const aExpand = $(target).closest('.chapter-expand'); const aExpand = $(target).closest('.chapter-expand')
if (tooltip.length > 0) { if (tooltip.length > 0) {
const random = $(tooltip).data('random'); const random = $(tooltip).data('random')
const link = $(tooltip).data('link'); const link = $(tooltip).data('link')
const content = $(tooltip).data('content'); const content = $(tooltip).data('content')
const tooltipType = $(tooltip).data('tooltip-type'); const tooltipType = $(tooltip).data('tooltip-type')
const title = $(tooltip).data('title'); const title = $(tooltip).data('title')
const tooltipParent = $(target).closest( const tooltipParent = $(target).closest('p, div, h1, h2, h3, h4, h5, h6, li, dt, dd, section')
'p, div, h1, h2, h3, h4, h5, h6, li, dt, dd, section', const tooltipParentPosition = $(tooltipParent).position()
); const tooltipPosition = $(tooltip).position()
const tooltipParentPosition = $(tooltipParent).position(); const childOffset = $(tooltip).offset() // 获取子元素相对于文档的位置
const tooltipPosition = $(tooltip).position(); const childWidth = $(tooltip).outerWidth(true) // 获取元素的宽度
const childOffset = $(tooltip).offset(); // 获取子元素相对于文档的位置 const childHeight = $(tooltip).outerHeight(true) // 获取元素的高度
const childWidth = $(tooltip).outerWidth(true); // 获取元素的宽度 let toolRect = null
const childHeight = $(tooltip).outerHeight(true); // 获取元素的高度 let targetPositon = null
let toolRect = null;
let targetPositon = null;
if (target.nodeName.toLowerCase() === 'svg' || target.nodeName.toLowerCase() === 'use') { if (target.nodeName.toLowerCase() === 'svg' || target.nodeName.toLowerCase() === 'use') {
toolRect = target.parentNode.parentNode.getBoundingClientRect(); toolRect = target.parentNode.parentNode.getBoundingClientRect()
targetPositon = $(target).closest('.chapter-item-tooltip').position(); targetPositon = $(target).closest('.chapter-item-tooltip').position()
} else { } else {
toolRect = target.parentNode.getBoundingClientRect(); toolRect = target.parentNode.getBoundingClientRect()
targetPositon = $(target).position(); targetPositon = $(target).position()
} }
const lineHeight = $(tooltip).css('line-height'); const lineHeight = $(tooltip).css('line-height')
let inSide = ''; let inSide = ''
let left = childOffset.left - parentOffset.left; let left = childOffset.left - parentOffset.left
let top = 0; let top = 0
let squareStyle = {}; let squareStyle = {}
if (childWidth + left >= iParentW) { if (childWidth + left >= iParentW) {
left = iParentW - childWidth - 10; left = iParentW - childWidth - 10
} }
if (left <= 0) { if (left <= 0) {
left = 10; left = 10
} }
let style1 = { let style1 = {
top: `${top}px`, top: `${top}px`,
left: `${left}px`, left: `${left}px`
}; }
setTooltip({ setTooltip({
title, title,
...@@ -180,53 +178,53 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -180,53 +178,53 @@ const PreviewScreen = forwardRef((props, ref) => {
tooltipType, tooltipType,
inSide, inSide,
style: style1, style: style1,
squareStyle: squareStyle, squareStyle: squareStyle
}); })
setTimeout(() => { setTimeout(() => {
const childMoveHeight = $('.tooltip').outerHeight(); // 获取元素的高度 const childMoveHeight = $('.tooltip').outerHeight() // 获取元素的高度
const childMoveWidth = $('.tooltip').outerWidth(); // 获取元素的高度 const childMoveWidth = $('.tooltip').outerWidth() // 获取元素的高度
const scrollTop = $('.preview-content-show').scrollTop(); const scrollTop = $('.preview-content-show').scrollTop()
let squareStyle = {}; let squareStyle = {}
if (left <= 0) { if (left <= 0) {
left = 10; left = 10
squareStyle.left = 10; squareStyle.left = 10
} else if (left + childMoveWidth >= iParentW) { } else if (left + childMoveWidth >= iParentW) {
left = iParentW - childMoveWidth - 20; left = iParentW - childMoveWidth - 20
squareStyle.left = targetPositon.left - left; squareStyle.left = targetPositon.left - left
} else { } else {
squareStyle.left = childWidth / 2; squareStyle.left = childWidth / 2
} }
// 换行了 // 换行了
// console.log(toolRect.height, parseInt(lineHeight)); // console.log(toolRect.height, parseInt(lineHeight));
if (tooltipType === 1 && toolRect.height / 1.5 > parseInt(lineHeight)) { if (tooltipType === 1 && toolRect.height / 1.5 > parseInt(lineHeight)) {
left = toolRect.right - parentRect.left - childMoveWidth + 15; left = toolRect.right - parentRect.left - childMoveWidth + 15
squareStyle.left = childMoveWidth - 30; squareStyle.left = childMoveWidth - 30
} }
// 是否被遮挡 // 是否被遮挡
if (tooltipPosition.top + childMoveHeight + childHeight + 30 >= scrollTop + iParentH) { if (tooltipPosition.top + childMoveHeight + childHeight + 30 >= scrollTop + iParentH) {
inSide = 'bottom'; inSide = 'bottom'
top = tooltipPosition.top - childMoveHeight; top = tooltipPosition.top - childMoveHeight
squareStyle.left = childWidth / 2; squareStyle.left = childWidth / 2
} else { } else {
inSide = 'top'; inSide = 'top'
if (toolRect.height / 1.5 > parseInt(lineHeight)) { if (toolRect.height / 1.5 > parseInt(lineHeight)) {
top = tooltipPosition.top + childHeight + toolRect.height; top = tooltipPosition.top + childHeight + toolRect.height
top = tooltipPosition.top + toolRect.height + parseInt(lineHeight); top = tooltipPosition.top + toolRect.height + parseInt(lineHeight)
} else { } else {
top = tooltipPosition.top + childHeight + 25; top = tooltipPosition.top + childHeight + 25
} }
} }
top = top - scrollTop; top = top - scrollTop
let style2 = { let style2 = {
top: `${top}px`, top: `${top}px`,
left: `${left}px`, left: `${left}px`,
zIndex: 1000, zIndex: 1000,
opacity: 1, opacity: 1
}; }
setTooltip({ setTooltip({
title, title,
random, random,
...@@ -235,142 +233,142 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -235,142 +233,142 @@ const PreviewScreen = forwardRef((props, ref) => {
tooltipType, tooltipType,
inSide, inSide,
style: style2, style: style2,
squareStyle: squareStyle, squareStyle: squareStyle
}); })
}, 100); }, 100)
return false; return false
} else if (alink.length > 0) { } else if (alink.length > 0) {
const link = $(alink).data('link'); const link = $(alink).data('link')
const linkType = $(alink).data('linktype'); const linkType = $(alink).data('linktype')
const chapters = $(alink).data('chapters'); const chapters = $(alink).data('chapters')
const title = $(alink).data('title'); const title = $(alink).data('title')
let last = ''; let last = ''
if (parseInt(linkType) === 2) { if (parseInt(linkType) === 2) {
if (chapters.toString().indexOf(',') > -1) { if (chapters.toString().indexOf(',') > -1) {
const arr = chapters.split(','); const arr = chapters.split(',')
last = arr[arr.length - 1]; last = arr[arr.length - 1]
} else { } else {
last = chapters; last = chapters
} }
setHeadTitle(title); setHeadTitle(title)
setOpend(true); setOpend(true)
setNewChapterId(last); setNewChapterId(last)
} else { } else {
window.open(link); window.open(link)
} }
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aGallery.length > 0) { } else if (aGallery.length > 0) {
const title = $(aGallery).data('title'); const title = $(aGallery).data('title')
const flex = $(aGallery).data('flex'); const flex = $(aGallery).data('flex')
const gallerylist = $(aGallery).data('gallerylist'); const gallerylist = $(aGallery).data('gallerylist')
const galleryArr = JSON.parse(decodeURI(gallerylist)); const galleryArr = JSON.parse(decodeURI(gallerylist))
setOpend(true); setOpend(true)
setHeadTitle(title); setHeadTitle(title)
if (galleryArr && galleryArr.length > 0 && galleryArr instanceof Array) { if (galleryArr && galleryArr.length > 0 && galleryArr instanceof Array) {
setGallery(galleryArr); setGallery(galleryArr)
if (parseInt(flex) === 2) { if (parseInt(flex) === 2) {
setGalleryIndex(0); setGalleryIndex(0)
} else { } else {
setGalleryIndex($(target).closest('.chapter-gallery-item').index()); setGalleryIndex($(target).closest('.chapter-gallery-item').index())
} }
} else { } else {
setGallery([]); setGallery([])
} }
setIsType('gallery'); setIsType('gallery')
setTooltip({}); setTooltip({})
return false; return false
} else if (practice.length > 0) { } else if (practice.length > 0) {
const title = $(practice).data('title'); const title = $(practice).data('title')
const bookid = $(practice).data('bookid'); const bookid = $(practice).data('bookid')
const chapterid = $(practice).data('chapterid'); const chapterid = $(practice).data('chapterid')
const practicenum = $(practice).data('practicenum'); const practicenum = $(practice).data('practicenum')
getTopicList({ practicenum, chapterid, bookid }); getTopicList({ practicenum, chapterid, bookid })
setOpend(true); setOpend(true)
setHeadTitle(title); setHeadTitle(title)
setIsType('practice'); setIsType('practice')
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aA.length > 0) { } else if (aA.length > 0) {
const href = $(aA).attr('href'); const href = $(aA).attr('href')
let newLink = ''; let newLink = ''
if (!/^https*:\/\//.test(href)) { if (!/^https*:\/\//.test(href)) {
newLink = `http://${href}`; newLink = `http://${href}`
} else { } else {
newLink = href; newLink = href
} }
window.open(newLink); window.open(newLink)
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aExpand.length > 0) { } else if (aExpand.length > 0) {
const title = $(aExpand).data('title'); const title = $(aExpand).data('title')
const name = $(aExpand).data('name'); const name = $(aExpand).data('name')
const position = $(aExpand).data('random'); const position = $(aExpand).data('random')
setOpend(true); setOpend(true)
getExpandInfo({ chapterId, position }); getExpandInfo({ chapterId, position })
setIsType('expand'); setIsType('expand')
setHeadTitle(name); setHeadTitle(name)
} else if (target.nodeName.toLowerCase() === 'img') { } else if (target.nodeName.toLowerCase() === 'img') {
const alt = $(target).attr('alt'); const alt = $(target).attr('alt')
const src = $(target).attr('src'); const src = $(target).attr('src')
setOpend(true); setOpend(true)
setIsType('img'); setIsType('img')
setPreviewImg(src); setPreviewImg(src)
setHeadTitle(alt ? alt : '图片展示'); setHeadTitle(alt ? alt : '图片展示')
} }
setTooltip({}); setTooltip({})
setGallery([]); setGallery([])
}); })
$('.expand-content, .gallery-prview-container').on('click', (ev) => { $('.expand-content, .gallery-prview-container').on('click', ev => {
const target = ev.target; const target = ev.target
if (target.nodeName.toLowerCase() === 'img') { if (target.nodeName.toLowerCase() === 'img') {
const alt = $(target).attr('alt'); const alt = $(target).attr('alt')
const src = $(target).attr('src'); const src = $(target).attr('src')
setOpend(true); setOpend(true)
setIsType('img'); setIsType('img')
setPreviewImg(src); setPreviewImg(src)
setSecondType('扩展图片'); setSecondType('扩展图片')
}
})
} }
});
};
useEffect(() => { useEffect(() => {
handlerClick(); handlerClick()
}, [isType]); }, [])
const getChapterId = async () => { const getChapterId = async () => {
setLoading(true); setLoading(true)
const data = await getInfoByChapterId({ chapter_id: newChapterId }); const data = await getInfoByChapterId({ chapter_id: newChapterId })
if (data) { if (data) {
const content = get(data, 'content', ''); const content = get(data, 'content', '')
setPrviewHtml(content); setPrviewHtml(content)
$('#previee-container') $('#previee-container')
.find('video audio') .find('video audio')
.each((index, item) => { .each((index, item) => {
$(item).attr('controls', true).attr('controlslist', 'nodownload'); $(item).attr('controls', true).attr('controlslist', 'nodownload')
}); })
setTimeout(() => { setTimeout(() => {
document document
.querySelectorAll('.preview-content-show ')[0] .querySelectorAll('.preview-content-show ')[0]
.querySelectorAll('pre code') .querySelectorAll('pre code')
.forEach((el) => { .forEach(el => {
hljs.highlightElement(el); hljs.highlightElement(el)
}); })
}, 200); }, 200)
}
setLoading(false)
} }
setLoading(false);
};
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false)
}; }
// const handleSelect = async (checkedKeys, info) => { // const handleSelect = async (checkedKeys, info) => {
// setLoading(true); // setLoading(true);
// const data = await getInfoByChapterId({ chapter_id: info.node.key }); // const data = await getInfoByChapterId({ chapter_id: info.node.key });
...@@ -388,345 +386,300 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -388,345 +386,300 @@ const PreviewScreen = forwardRef((props, ref) => {
// }; // };
useEffect(() => { useEffect(() => {
getChapterId(); getChapterId()
}, [bookId, newChapterId]); }, [bookId, newChapterId])
const galleryLeft = () => { const galleryLeft = () => {
let temp = galleryIndex; let temp = galleryIndex
if (temp <= 0) { if (temp <= 0) {
temp = 0; temp = 0
} else { } else {
temp = temp - 1; temp = temp - 1
}
setGalleryIndex(temp)
} }
setGalleryIndex(temp);
};
const galleryRight = () => { const galleryRight = () => {
let temp = galleryIndex; let temp = galleryIndex
if (temp >= gallery.length - 1) { if (temp >= gallery.length - 1) {
temp = gallery.length - 1; temp = gallery.length - 1
} else { } else {
temp = temp + 1; temp = temp + 1
}
setGalleryIndex(temp)
} }
setGalleryIndex(temp);
};
return ( return (
<div className='priview-modal'> <div className="priview-modal">
<div className='previee-container' id='previee-container'> <div className="previee-container" id="previee-container">
<div className='chapter-head-title'> <div className="chapter-head-title">
<h2> <h2>
{opend ? ( {opend ? (
<Space> <Space>
<Button <Button
type='text' type="text"
onClick={() => { onClick={() => {
if (secondType) { if (secondType) {
setSecondType(false); setSecondType(false)
setPreviewImg(null); setPreviewImg(null)
setIsType('expand'); setIsType('expand')
return; return
} }
setOpend(false); setOpend(false)
setIsType(''); setIsType('')
setExpandContent(''); setExpandContent('')
setTopicList([]); setTopicList([])
setGalleryIndex(-1); setGalleryIndex(-1)
setNewChapterId(chapterId); setNewChapterId(chapterId)
setPreviewImg(''); setPreviewImg('')
}} }}>
>
<LeftOutlined /> <LeftOutlined />
</Button> </Button>
{secondType ? secondType : headTitle} {secondType ? secondType : headTitle}
</Space> </Space>
) : ( ) : (
<span className='no'>{nowTitle}</span> <span className="no">{nowTitle}</span>
)} )}
</h2> </h2>
</div> </div>
<div className='preview-content-it'> <div className="preview-content-it">
<div className='preview-content-show'> <div className="preview-content-show">
<Spin spinning={loading} wrapperClassName='chapter-loading'> <Spin spinning={loading} wrapperClassName="chapter-loading">
<div <div className="preview-content-html" dangerouslySetInnerHTML={{ __html: prviewHtml }}></div>
className='preview-content-html'
dangerouslySetInnerHTML={{ __html: prviewHtml }}
></div>
</Spin> </Spin>
</div> </div>
{isType && ( {isType && (
<div className='preview-content-other'> <div className="preview-content-other">
{isType === 'gallery' && ( {isType === 'gallery' && (
<div className='gallery-prview-container'> <div className="gallery-prview-container">
{gallery && gallery.length > 0 ? ( {gallery && gallery.length > 0 ? (
<> <>
<div className='gallery-img'> <div className="gallery-img">
<img <img src={gallery[parseInt(galleryIndex)].url} alt={gallery[parseInt(galleryIndex)].title} />
src={gallery[parseInt(galleryIndex)].url} <div className="opa prev" onClick={galleryLeft}></div>
alt={gallery[parseInt(galleryIndex)].title} <div className="opa next" onClick={galleryRight}></div>
/>
<div className='opa prev' onClick={galleryLeft}></div>
<div className='opa next' onClick={galleryRight}></div>
</div> </div>
<div className='steps'> <div className="steps">
当前 {parseInt(galleryIndex) + 1}/{gallery.length} 当前 {parseInt(galleryIndex) + 1}/{gallery.length}
</div> </div>
<div className='title'>{gallery[parseInt(galleryIndex)].title}</div> <div className="title">{gallery[parseInt(galleryIndex)].title}</div>
<div className='desc'>{gallery[parseInt(galleryIndex)].desc}</div> <div className="desc">{gallery[parseInt(galleryIndex)].desc}</div>
</> </>
) : ( ) : (
<> <>
<div className='gallery-img noData'>画廊数据异常</div> <div className="gallery-img noData">画廊数据异常</div>
</> </>
)} )}
</div> </div>
)} )}
{isType === 'practice' && ( {isType === 'practice' && (
<div className='practice-insert-topic'> <div className="practice-insert-topic">
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('radio')}. 单选题</h3> <h3>{clacTopicText('radio')}. 单选题</h3>
<div className='practice-list'> <div className="practice-list">
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{checkBoxList.length > 0 && ( {checkBoxList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('checkbox', radioList)}. 多选题</h3> <h3>{clacTopicText('checkbox', radioList)}. 多选题</h3>
<div className='practice-list'> <div className="practice-list">
{checkBoxList.map((item, index) => { {checkBoxList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{judgeList.length > 0 && ( {judgeList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3> <h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3>
<div className='practice-list'> <div className="practice-list">
{judgeList.map((item, index) => { {judgeList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{fillList.length > 0 && ( {fillList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3> <h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3>
<div className='practice-list'> <div className="practice-list">
{fillList.map((item, index) => { {fillList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3> <h3>{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. 简答题</h3>
{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. <div className="practice-list">
简答题
</h3>
<div className='practice-list'>
{textareaList.map((item, index) => { {textareaList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `${correctList[cindex]}. ${citem.option}`, __html: `${correctList[cindex]}. ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
...@@ -734,33 +687,31 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -734,33 +687,31 @@ const PreviewScreen = forwardRef((props, ref) => {
</div> </div>
)} )}
{isType === 'expand' && ( {isType === 'expand' && (
<div className='expand-container'> <div className="expand-container">
<div <div className="expand-content" dangerouslySetInnerHTML={{ __html: expandContent }}></div>
className='expand-content'
dangerouslySetInnerHTML={{ __html: expandContent }}
></div>
</div> </div>
)} )}
{isType === 'img' && ( {isType === 'img' && (
<div className='img-preview'> <div className="img-preview">
<Image width={430} src={previewImg} /> <Image width={430} src={previewImg} />
</div> </div>
)} )}
</div> </div>
)} )}
<div className='tooltip' style={toolTip.style}> <div className="tooltip" style={toolTip.style}>
<div <div
className={`square ${toolTip.inSide === 'top' ? 'square_top' : toolTip.inSide === 'bottom' ? 'square_bottom' : ''}`} className={`square ${
style={toolTip.squareStyle} toolTip.inSide === 'top' ? 'square_top' : toolTip.inSide === 'bottom' ? 'square_bottom' : ''
></div> }`}
<div className='tooltip-content-container'> style={toolTip.squareStyle}></div>
<div className='tooltip-content'> <div className="tooltip-content-container">
<div className='content'> <div className="tooltip-content">
<div className="content">
<p>{toolTip.content}</p> <p>{toolTip.content}</p>
</div> </div>
{toolTip.link && ( {toolTip.link && (
<div className='content-opa'> <div className="content-opa">
<a href={toolTip.link} target='_blank' rel='noreferrer' className='c-link'></a> <a href={toolTip.link} target="_blank" rel="noreferrer" className="c-link"></a>
</div> </div>
)} )}
</div> </div>
...@@ -788,7 +739,7 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -788,7 +739,7 @@ const PreviewScreen = forwardRef((props, ref) => {
/> />
</Drawer> */} </Drawer> */}
</div> </div>
); )
}); }
export default PreviewScreen; export default forwardRef(PreviewScreen)
import React, { useState, forwardRef, useImperativeHandle, useRef } from 'react'; import React, { useState, forwardRef, useImperativeHandle, useRef } from 'react'
import { Input, InputNumber } from 'antd'; import { Input, InputNumber } from 'antd'
import '../index.less'; import '../index.less'
const PaddingSpace = forwardRef((props, ref) => { const PaddingSpace = (props, ref) => {
const { editorNodes, editor } = props; const { editorNodes, editor } = props
const [inputValue1, setInputValue1] = useState(''); const [inputValue1, setInputValue1] = useState('')
const [inputValue2, setInputValue2] = useState(''); const [inputValue2, setInputValue2] = useState('')
const [inputValue3, setInputValue3] = useState(''); const [inputValue3, setInputValue3] = useState('')
const timeDebonceRef = useRef(); const timeDebonceRef = useRef()
const InpoutValueChange1 = (value) => { const InpoutValueChange1 = value => {
setInputValue1(value); setInputValue1(value)
changeIt(); changeIt()
}; }
const InpoutValueChange2 = (value) => { const InpoutValueChange2 = value => {
setInputValue2(value); setInputValue2(value)
}; }
const InpoutValueChange3 = (value) => { const InpoutValueChange3 = value => {
setInputValue3(value); setInputValue3(value)
}; }
const changeIt = () => { const changeIt = () => {
clearTimeout(timeDebonceRef.current); clearTimeout(timeDebonceRef.current)
timeDebonceRef.current = setTimeout(() => { timeDebonceRef.current = setTimeout(() => {}, 500)
}, 500);
if (editorNodes) { if (editorNodes) {
} else { } else {
} }
} }
...@@ -37,49 +33,34 @@ const PaddingSpace = forwardRef((props, ref) => { ...@@ -37,49 +33,34 @@ const PaddingSpace = forwardRef((props, ref) => {
return { return {
inputValue1, inputValue1,
inputValue2, inputValue2,
inputValue3, inputValue3
}; }
}); })
return ( return (
<div className='custom-bar-box-input'> <div className="custom-bar-box-input">
<div className='box'> <div className="box">
<div className='customer-box-input-item'> <div className="customer-box-input-item">
<p> <p>
<InputNumber <InputNumber controls={false} id="padding_1" value={inputValue1} onChange={InpoutValueChange1} />
controls={false}
id='padding_1'
value={inputValue1}
onChange={InpoutValueChange1}
/>
</p> </p>
<p className='text'>段前间距</p> <p className="text">段前间距</p>
</div> </div>
<div className='customer-box-input-item'> <div className="customer-box-input-item">
<p> <p>
<InputNumber <InputNumber controls={false} id="padding_2" value={inputValue2} onChange={InpoutValueChange2} />
controls={false}
id='padding_2'
value={inputValue2}
onChange={InpoutValueChange2}
/>
</p> </p>
<p className='text'>段后间距</p> <p className="text">段后间距</p>
</div> </div>
<div className='customer-box-input-item'> <div className="customer-box-input-item">
<p> <p>
<InputNumber <InputNumber controls={false} id="padding_3" value={inputValue3} onChange={InpoutValueChange3} />
controls={false}
id='padding_3'
value={inputValue3}
onChange={InpoutValueChange3}
/>
</p> </p>
<p className='text'>行距</p> <p className="text">行距</p>
</div> </div>
</div> </div>
</div> </div>
); )
}); }
export default PaddingSpace; export default forwardRef(PaddingSpace)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Form, Space, Input, Select, Button, Spin, Row, Col, Checkbox, Radio } from 'antd'; import { Form, Space, Input, Select, Button, Spin, Row, Col, Checkbox, Radio } from 'antd'
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux'
import { Editor, Toolbar } from '@wangeditor/editor-for-react'; import { Editor, Toolbar } from '@wangeditor/editor-for-react'
import { DomEditor } from '@wangeditor/editor'; import { DomEditor } from '@wangeditor/editor'
import { questionAdd, typeAllList, questionAddType, bookNameList } from '../request'; import { questionAdd, typeAllList, questionAddType, bookNameList } from '../request'
import AliOSS from 'ali-oss'; import AliOSS from 'ali-oss'
import dayjs from 'dayjs'; import dayjs from 'dayjs'
import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet'; import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet'
import { uploadFiles } from '@/utils/upload'; import { uploadFiles } from '@/utils/upload'
import QuestionEditr from '@/pages/books/question-bank/questionEditr'; import QuestionEditr from '@/pages/books/question-bank/questionEditr'
import { values } from 'lodash-es'; import { values } from 'lodash-es'
const CustomerTopic = forwardRef((props, ref) => { const CustomerTopic = (props, ref) => {
const { getTopList, bookNameIdData, setPracticeStatus, bookId, setCustomerType } = props; const { getTopList, bookNameIdData, setPracticeStatus, bookId, setCustomerType } = props
// 获取操作权限 // 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user); const { operationPermissionsList } = useSelector(state => state.user)
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return {}; return {}
}); })
// oss // oss
const [ossClient, setOssClient] = useState(null); // oss 操作 const [ossClient, setOssClient] = useState(null) // oss 操作
const [STSToken, setSTSToken] = useState(null); // oss 过期设置 const [STSToken, setSTSToken] = useState(null) // oss 过期设置
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false)
const [form] = Form.useForm(); const [form] = Form.useForm()
const questionType = Form.useWatch('question_style', form); const questionType = Form.useWatch('question_style', form)
// 题干名称的编辑器实例 // 题干名称的编辑器实例
const [titlesEditor, setTitlesEditor] = useState(null); const [titlesEditor, setTitlesEditor] = useState(null)
const [quesList, setQuesList] = useState([]); const [quesList, setQuesList] = useState([])
const [initialValues, setinitialValues] = useState({ const [initialValues, setinitialValues] = useState({
titles: '', titles: '',
type_id: '', type_id: '',
...@@ -39,20 +39,20 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -39,20 +39,20 @@ const CustomerTopic = forwardRef((props, ref) => {
analysis: '', analysis: '',
answers: '', answers: '',
question_list: [], question_list: [],
book_id: bookId, book_id: bookId
}); })
// 书籍名称的参数和获取 // 书籍名称的参数和获取
const [selectedBookId, setSelectedBookId] = useState(bookId); const [selectedBookId, setSelectedBookId] = useState(bookId)
useEffect(() => { useEffect(() => {
setSelectedBookId(bookId); setSelectedBookId(bookId)
}, [bookId]); }, [bookId])
const getStsAuthToken = async () => { const getStsAuthToken = async () => {
const data = await getAliOSSSTSToken(); const data = await getAliOSSSTSToken()
if (data) { if (data) {
window.sessionStorage.setItem('sts', JSON.stringify(data)); window.sessionStorage.setItem('sts', JSON.stringify(data))
setSTSToken(data); setSTSToken(data)
const ossClientTemp = await new AliOSS({ const ossClientTemp = await new AliOSS({
accessKeyId: data.AccessKeyId, accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret, accessKeySecret: data.AccessKeySecret,
...@@ -62,66 +62,66 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -62,66 +62,66 @@ const CustomerTopic = forwardRef((props, ref) => {
timeout: 180000, timeout: 180000,
refreshSTSToken: async () => { refreshSTSToken: async () => {
const info = await getAliOSSSTSToken(); const info = await getAliOSSSTSToken()
return { return {
AccessKeyId: info.AccessKeyId, AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret, AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken, SecurityToken: info.SecurityToken
}; }
}, },
refreshSTSTokenInterval: 14 * 60 * 1000, refreshSTSTokenInterval: 14 * 60 * 1000
}); })
setOssClient(ossClientTemp); setOssClient(ossClientTemp)
}
} }
};
// 显示不同类型的选项函数 // 显示不同类型的选项函数
const [edierVal, setedierVal] = useState(''); const [edierVal, setedierVal] = useState('')
// 是否显示选项 // 是否显示选项
const [showList, setShowList] = useState(false); const [showList, setShowList] = useState(false)
const [formLoading, setFormLoading] = useState(false); const [formLoading, setFormLoading] = useState(false)
const [typeDate, setTypeDate] = useState([]); const [typeDate, setTypeDate] = useState([])
const [showAddClass, setShowAddClass] = useState(false); const [showAddClass, setShowAddClass] = useState(false)
const [addClassVal, setaddClassVal] = useState(''); // 添加分类 const [addClassVal, setaddClassVal] = useState('') // 添加分类
const [questionStyle, setQuestionStyle] = useState(''); const [questionStyle, setQuestionStyle] = useState('')
// 题目分类 // 题目分类
const getTypeList = async () => { const getTypeList = async () => {
const { list } = await typeAllList({ page: 1, page_size: 999 }); const { list } = await typeAllList({ page: 1, page_size: 999 })
setTypeDate(list); setTypeDate(list)
}; }
// 获取数据 // 获取数据
useEffect(() => { useEffect(() => {
(async () => { ;(async () => {
await getTypeList(); await getTypeList()
await getStsAuthToken(); await getStsAuthToken()
})(); })()
}, []); }, [])
// 分类 // 分类
const sureFn = async () => { const sureFn = async () => {
const bool = await questionAddType({ typename: addClassVal }); const bool = await questionAddType({ typename: addClassVal })
if (bool) { if (bool) {
await getTypeList(); await getTypeList()
form.setFieldsValue({ type_id: bool.type_id }); form.setFieldsValue({ type_id: bool.type_id })
setinitialValues({ ...initialValues, type_id: bool.type_id }); setinitialValues({ ...initialValues, type_id: bool.type_id })
setaddClassVal(''); setaddClassVal('')
setShowAddClass(false); setShowAddClass(false)
}
} }
};
// 工具栏配置 // 工具栏配置
const toolbarConfig = {}; const toolbarConfig = {}
toolbarConfig.toolbarKeys = ['uploadImage']; toolbarConfig.toolbarKeys = ['uploadImage']
// 编辑器配置 // 编辑器配置
const editorConfig = { const editorConfig = {
// JS 语法 // JS 语法
placeholder: '请输入内容...', placeholder: '请输入内容...',
hoverbarKeys: { hoverbarKeys: {
text: { text: {
menuKeys: [], menuKeys: []
}, }
}, },
MENU_CONF: { MENU_CONF: {
// 配置默认字号 // 配置默认字号
...@@ -132,158 +132,144 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -132,158 +132,144 @@ const CustomerTopic = forwardRef((props, ref) => {
fieldName: 'image', fieldName: 'image',
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token'), Authorization: 'Bearer ' + localStorage.getItem('token')
}, },
maxFileSize: 10 * 1024 * 1024, // 10M maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 base64LimitSize: 5 * 1024, // 5kb 以下插入 base64
customUpload: async (file, insertFn) => { customUpload: async (file, insertFn) => {
if (!ossClient) { if (!ossClient) {
console.error('ossClient还未初始化', ossClient); console.error('ossClient还未初始化', ossClient)
return false; return false
} }
const fileExt = file.name.substring(file.name.lastIndexOf('.')); const fileExt = file.name.substring(file.name.lastIndexOf('.'))
const fileName = `practice-${dayjs().valueOf()}-${Math.random() const fileName = `practice-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`
.toString(36) const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`
.substring(2)}${fileExt}`;
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`;
const result = await ossClient.put(filePath, file); const result = await ossClient.put(filePath, file)
console.log('result', result); console.log('result', result)
insertFn(result.url, '题库图片'); insertFn(result.url, '题库图片')
// const { url } = await uploadFiles({ file, file_type: 'question' }); // const { url } = await uploadFiles({ file, file_type: 'question' });
// insertFn(url, '题库图片'); // insertFn(url, '题库图片');
}, }
}, }
}, },
customPaste: (editor, event) => { customPaste: (editor, event) => {
// const html = event.clipboardData.getData('text/html') // 获取粘贴的 html // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
const text = event.clipboardData.getData('text/plain'); // 获取粘贴的纯文本 const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴) // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
// 异步 // 异步
setTimeout(() => { setTimeout(() => {
editor.insertText(text); editor.insertText(text)
}, 500); }, 500)
// 阻止默认的粘贴行为 // 阻止默认的粘贴行为
event.preventDefault(); event.preventDefault()
return false; return false
}, }
}; }
// 及时销毁 editor ,重要! // 及时销毁 editor ,重要!
useEffect(() => { useEffect(() => {
if (titlesEditor !== null) { if (titlesEditor !== null) {
const toolbar = DomEditor.getToolbar(titlesEditor); const toolbar = DomEditor.getToolbar(titlesEditor)
} }
return () => { return () => {
if (titlesEditor === null) return; if (titlesEditor === null) return
titlesEditor.destroy(); titlesEditor.destroy()
setTitlesEditor(null); setTitlesEditor(null)
}; }
}, [titlesEditor]); }, [titlesEditor])
const submitForm = async (obj) => { const submitForm = async obj => {
let ilen = 0; let ilen = 0
let obj2 = { ...obj }; let obj2 = { ...obj }
if ([1, 2, 3].includes(parseInt(obj.question_style))) { if ([1, 2, 3].includes(parseInt(obj.question_style))) {
obj.question_list.forEach((item, index) => { obj.question_list.forEach((item, index) => {
if (item.correct && item.correct === true) { if (item.correct && item.correct === true) {
ilen++; ilen++
} }
}); })
if ([1, 3].includes(parseInt(obj.question_style))) { if ([1, 3].includes(parseInt(obj.question_style))) {
if (ilen > 1 || ilen === 0) { if (ilen > 1 || ilen === 0) {
form.setFields([ form.setFields([
{ {
name: ['question_list', obj.question_list.length - 1, 'correct'], name: ['question_list', obj.question_list.length - 1, 'correct'],
errors: [ errors: [`${parseInt(obj.question_style) === 3 ? '判断题' : '单选题'}有且仅有一个正确答案!`]
`${parseInt(obj.question_style) === 3 ? '判断题' : '单选题'}有且仅有一个正确答案!`, }
], ])
}, return false
]);
return false;
} else { } else {
form.setFields([ form.setFields([{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] }])
{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] },
]);
} }
} else { } else {
if (ilen <= 1) { if (ilen <= 1) {
form.setFields([ form.setFields([
{ {
name: ['question_list', obj.question_list.length - 1, 'correct'], name: ['question_list', obj.question_list.length - 1, 'correct'],
errors: ['多选题需要2个及以上正确答案!'], errors: ['多选题需要2个及以上正确答案!']
}, }
]); ])
return false; return false
} else { } else {
form.setFields([ form.setFields([{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] }])
{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] },
]);
} }
} }
obj2['question_list'] = JSON.stringify(quesList); obj2['question_list'] = JSON.stringify(quesList)
} else { } else {
obj2['answers'] = edierVal; obj2['answers'] = edierVal
} }
setLoading(true); setLoading(true)
const data = await questionAdd({ const data = await questionAdd({
...obj, ...obj,
...obj2, ...obj2
}); })
if (data) { if (data) {
setCustomerType(obj.type_id); setCustomerType(obj.type_id)
setPracticeStatus(false); setPracticeStatus(false)
}
setLoading(false)
} }
setLoading(false);
};
// 校验 // 校验
const vaildaterHtml = (_, value) => { const vaildaterHtml = (_, value) => {
if (value === '<p><br></p>') { if (value === '<p><br></p>') {
return Promise.reject('问题内容不能为空'); return Promise.reject('问题内容不能为空')
} else { } else {
return Promise.resolve(); return Promise.resolve()
}
} }
};
useEffect(() => { useEffect(() => {
console.log(quesList); console.log(quesList)
}, [quesList]); }, [quesList])
return ( return (
<div style={{ paddingTop: 20 }} className='practice_customer'> <div style={{ paddingTop: 20 }} className="practice_customer">
<Form <Form
form={form} form={form}
initialValues={initialValues} initialValues={initialValues}
onFinish={submitForm} onFinish={submitForm}
labelCol={{ span: 5 }} labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }} wrapperCol={{ span: 19 }}>
> <Form.Item name="book_id" label="书籍名称" rules={[{ required: true, message: '请选择书籍' }]}>
<Form.Item
name='book_id'
label='书籍名称'
rules={[{ required: true, message: '请选择书籍' }]}
>
<Select <Select
placeholder='请选择书籍名称' placeholder="请选择书籍名称"
allowClear allowClear
id='classify' id="classify"
style={{ width: '200px' }} style={{ width: '200px' }}
showSearch //下拉框出现搜素,并可以输入 showSearch //下拉框出现搜素,并可以输入
optionFilterProp='children' // 使搜索匹配子节点的文本内容 optionFilterProp="children" // 使搜索匹配子节点的文本内容
defaultValue={selectedBookId} defaultValue={selectedBookId}
onChange={(value) => setSelectedBookId(value)} onChange={value => setSelectedBookId(value)}>
>
{bookNameIdData && {bookNameIdData &&
bookNameIdData.length && bookNameIdData.length &&
bookNameIdData.map((item, index) => ( bookNameIdData.map((item, index) => (
...@@ -294,19 +280,14 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -294,19 +280,14 @@ const CustomerTopic = forwardRef((props, ref) => {
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item name="question_style" label="题目类型" rules={[{ required: true, message: '请选择题目类型' }]}>
name='question_style'
label='题目类型'
rules={[{ required: true, message: '请选择题目类型' }]}
>
<Select <Select
onChange={(ev) => { onChange={ev => {
setShowList(true); setShowList(true)
setQuestionStyle(ev); setQuestionStyle(ev)
}} }}
style={{ width: 260 }} style={{ width: 260 }}
placeholder='请请选择题目类型' placeholder="请请选择题目类型">
>
<Select.Option value={1}>单选题</Select.Option> <Select.Option value={1}>单选题</Select.Option>
<Select.Option value={2}>多选题</Select.Option> <Select.Option value={2}>多选题</Select.Option>
<Select.Option value={3}>判断题</Select.Option> <Select.Option value={3}>判断题</Select.Option>
...@@ -314,23 +295,18 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -314,23 +295,18 @@ const CustomerTopic = forwardRef((props, ref) => {
<Select.Option value={5}>简答题</Select.Option> <Select.Option value={5}>简答题</Select.Option>
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item label="题目分类" name="type_id" rules={[{ required: true, message: '请选择题目分类' }]}>
label='题目分类'
name='type_id'
rules={[{ required: true, message: '请选择题目分类' }]}
>
{!showAddClass ? ( {!showAddClass ? (
<> <>
<Select <Select
onChange={(value) => { onChange={value => {
form.setFieldValue('type_id', value); form.setFieldValue('type_id', value)
}} }}
style={{ width: 260 }} style={{ width: 260 }}
placeholder='请选择题目分类' placeholder="请选择题目分类">
>
{typeDate && {typeDate &&
typeDate.length && typeDate.length &&
typeDate.map((item) => ( typeDate.map(item => (
<Select.Option key={item.id} value={item.id}> <Select.Option key={item.id} value={item.id}>
{item.typename} {item.typename}
</Select.Option> </Select.Option>
...@@ -338,12 +314,11 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -338,12 +314,11 @@ const CustomerTopic = forwardRef((props, ref) => {
</Select> </Select>
<Button <Button
onClick={() => { onClick={() => {
setShowAddClass(true); setShowAddClass(true)
form.setFieldsValue({ type_id: '' }); form.setFieldsValue({ type_id: '' })
}} }}
type='link' type="link"
style={{ textDecoration: 'underline', color: '#1672EC' }} style={{ textDecoration: 'underline', color: '#1672EC' }}>
>
添加分类 添加分类
</Button> </Button>
</> </>
...@@ -352,23 +327,17 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -352,23 +327,17 @@ const CustomerTopic = forwardRef((props, ref) => {
<Input <Input
style={{ width: 260 }} style={{ width: 260 }}
value={addClassVal} value={addClassVal}
onChange={(e) => setaddClassVal(e.target.value)} onChange={e => setaddClassVal(e.target.value)}
autoComplete='off' autoComplete="off"
placeholder='请输入题目分类' placeholder="请输入题目分类"></Input>
></Input>
<Space> <Space>
<Button <Button onClick={sureFn} type="link" style={{ textDecoration: 'underline', color: '#1672EC' }}>
onClick={sureFn}
type='link'
style={{ textDecoration: 'underline', color: '#1672EC' }}
>
添加 添加
</Button> </Button>
<Button <Button
type='link' type="link"
onClick={() => setShowAddClass(false)} onClick={() => setShowAddClass(false)}
style={{ textDecoration: 'underline', color: '#AA1941', marginLeft: -30 }} style={{ textDecoration: 'underline', color: '#AA1941', marginLeft: -30 }}>
>
取消 取消
</Button> </Button>
</Space> </Space>
...@@ -376,20 +345,19 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -376,20 +345,19 @@ const CustomerTopic = forwardRef((props, ref) => {
)} )}
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name='titles' name="titles"
label='题干名称' label="题干名称"
rules={[ rules={[
{ required: true, message: '请输入题干名称' }, { required: true, message: '请输入题干名称' },
{ validator: vaildaterHtml, validateTrigger: 'onChange' }, { validator: vaildaterHtml, validateTrigger: 'onChange' }
]} ]}
extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''} extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''}>
>
<Spin spinning={formLoading}> <Spin spinning={formLoading}>
<div style={{ border: '1px solid #ccc', zIndex: 100 }}> <div style={{ border: '1px solid #ccc', zIndex: 100 }}>
<Toolbar <Toolbar
editor={titlesEditor} editor={titlesEditor}
defaultConfig={toolbarConfig} defaultConfig={toolbarConfig}
mode='default' mode="default"
style={{ borderBottom: '1px solid #ccc' }} style={{ borderBottom: '1px solid #ccc' }}
/> />
{ossClient && ( {ossClient && (
...@@ -397,38 +365,38 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -397,38 +365,38 @@ const CustomerTopic = forwardRef((props, ref) => {
defaultConfig={editorConfig} defaultConfig={editorConfig}
value={initialValues.titles} value={initialValues.titles}
onCreated={setTitlesEditor} onCreated={setTitlesEditor}
onChange={(editor) => { onChange={editor => {
form.setFieldValue('titles', editor.getHtml()); form.setFieldValue('titles', editor.getHtml())
// setHtml(editor.getHtml()) // setHtml(editor.getHtml())
}} }}
config={{ config={{
uploadImgServer: 'your_upload_server_address', uploadImgServer: 'your_upload_server_address'
// other config options // other config options
}} }}
mode='default' mode="default"
style={{ height: '200px', overflowY: 'hidden' }} style={{ height: '200px', overflowY: 'hidden' }}
/> />
)} )}
</div> </div>
</Spin> </Spin>
</Form.Item> </Form.Item>
<Form.Item name='analysis' label='题目解析'> <Form.Item name="analysis" label="题目解析">
<Input.TextArea <Input.TextArea
placeholder='请输入题目解析' placeholder="请输入题目解析"
autoSize={{ autoSize={{
minRows: 5, minRows: 5,
maxRows: 8, maxRows: 8
}} }}
/> />
</Form.Item> </Form.Item>
{(questionStyle === 1 || questionStyle === 2 || questionStyle === 3) && ( {(questionStyle === 1 || questionStyle === 2 || questionStyle === 3) && (
<Form.List name='question_list'> <Form.List name="question_list">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<Form.Item label='题目选项'> <Form.Item label="题目选项">
{fields.map(({ key, name, ...restField }, index) => ( {fields.map(({ key, name, ...restField }, index) => (
<Row gutter={4} key={key}> <Row gutter={4} key={key}>
<Col span={14} className='form_inside-out'> <Col span={14} className="form_inside-out">
<Form.Item className='inside-it'> <Form.Item className="inside-it">
<QuestionEditr <QuestionEditr
editorValue={quesList && quesList[index] && quesList[index].option} editorValue={quesList && quesList[index] && quesList[index].option}
quesList={quesList} quesList={quesList}
...@@ -446,18 +414,17 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -446,18 +414,17 @@ const CustomerTopic = forwardRef((props, ref) => {
validator: (_, value) => { validator: (_, value) => {
if (value !== '') { if (value !== '') {
if (value === '<p><br></p>') { if (value === '<p><br></p>') {
return Promise.reject(new Error('请输入正确的内容')); return Promise.reject(new Error('请输入正确的内容'))
} else { } else {
return Promise.resolve(); return Promise.resolve()
} }
} else { } else {
return Promise.reject(new Error('')); return Promise.reject(new Error(''))
}
}
} }
},
},
]} ]}
className='form_inside-out-none' className="form_inside-out-none">
>
<Input.TextArea /> <Input.TextArea />
</Form.Item> </Form.Item>
</Col> </Col>
...@@ -465,26 +432,24 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -465,26 +432,24 @@ const CustomerTopic = forwardRef((props, ref) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'correct']} name={[name, 'correct']}
valuePropName='checked' valuePropName="checked"
initialValue={restField.correct || false} initialValue={restField.correct || false}>
>
<Checkbox <Checkbox
onChange={(e) => { onChange={e => {
if (quesList.length) { if (quesList.length) {
let temp = JSON.parse(JSON.stringify(quesList)); let temp = JSON.parse(JSON.stringify(quesList))
if (questionStyle === 1 || questionStyle === 3) { if (questionStyle === 1 || questionStyle === 3) {
if (e.target.checked) { if (e.target.checked) {
temp.forEach((item) => { temp.forEach(item => {
item.correct = false; item.correct = false
}); })
} }
} }
temp[index].correct = e.target.checked; temp[index].correct = e.target.checked
setQuesList(temp); setQuesList(temp)
form.setFieldValue('question_list', temp); form.setFieldValue('question_list', temp)
} }
}} }}>
>
正确答案 正确答案
</Checkbox> </Checkbox>
</Form.Item> </Form.Item>
...@@ -492,37 +457,34 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -492,37 +457,34 @@ const CustomerTopic = forwardRef((props, ref) => {
<Col span={3}> <Col span={3}>
<Button <Button
onClick={async () => { onClick={async () => {
let temp = JSON.parse(JSON.stringify(quesList)); let temp = JSON.parse(JSON.stringify(quesList))
temp.splice(index, 1); temp.splice(index, 1)
setQuesList(temp); setQuesList(temp)
await remove(name); await remove(name)
}} }}
icon={<MinusOutlined />} icon={<MinusOutlined />}></Button>
></Button>
</Col> </Col>
</Row> </Row>
))} ))}
{quesList.length < 2 && questionStyle === 3 && ( {quesList.length < 2 && questionStyle === 3 && (
<Form.Item> <Form.Item>
<Button <Button
type='dashed' type="dashed"
onClick={async () => { onClick={async () => {
await add(); await add()
}} }}
icon={<PlusOutlined />} icon={<PlusOutlined />}></Button>
></Button>
</Form.Item> </Form.Item>
)} )}
{[1, 2].includes(questionStyle) && ( {[1, 2].includes(questionStyle) && (
<Form.Item> <Form.Item>
<Button <Button
type='dashed' type="dashed"
onClick={async () => { onClick={async () => {
await add(); await add()
}} }}
icon={<PlusOutlined />} icon={<PlusOutlined />}></Button>
></Button>
</Form.Item> </Form.Item>
)} )}
</Form.Item> </Form.Item>
...@@ -530,25 +492,20 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -530,25 +492,20 @@ const CustomerTopic = forwardRef((props, ref) => {
</Form.List> </Form.List>
)} )}
{(questionStyle === 5 || questionStyle === 4) && ( {(questionStyle === 5 || questionStyle === 4) && (
<Form.Item name='answers' label='正确答案'> <Form.Item name="answers" label="正确答案">
<QuestionEditr <QuestionEditr editorValue={edierVal} setedierVal={setedierVal} form={form} name="answers" />
editorValue={edierVal}
setedierVal={setedierVal}
form={form}
name='answers'
/>
</Form.Item> </Form.Item>
)} )}
<Form.Item wrapperCol={{ offset: 5, span: 16 }}> <Form.Item wrapperCol={{ offset: 5, span: 16 }}>
<Space size={20}> <Space size={20}>
<Button className='submit' disabled={showAddClass} loading={loading} htmlType='submit'> <Button className="submit" disabled={showAddClass} loading={loading} htmlType="submit">
提交 提交
</Button> </Button>
</Space> </Space>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>
); )
}); }
export default CustomerTopic; export default forwardRef(CustomerTopic)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Button, Popconfirm, message } from 'antd'; import { Button, Popconfirm, message } from 'antd'
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons'
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux'
import { setPracticeRandom } from '@/store/modules/editor'; import { setPracticeRandom } from '@/store/modules/editor'
import TopicItem from './topicItem'; import TopicItem from './topicItem'
import { addChapterTopic, getChapterTopic } from '../../utils/request'; import { addChapterTopic, getChapterTopic } from '../../utils/request'
import { clacTopicText } from '@/utils/common'; import { clacTopicText } from '@/utils/common'
const InsertTopic = forwardRef((props, ref) => { const InsertTopic = (props, ref) => {
const { const {
insertList, insertList,
setInsertList, setInsertList,
...@@ -17,233 +17,208 @@ const InsertTopic = forwardRef((props, ref) => { ...@@ -17,233 +17,208 @@ const InsertTopic = forwardRef((props, ref) => {
practiceRandom = '', practiceRandom = '',
closePanel, closePanel,
chapterId, chapterId,
bookId, bookId
} = props; } = props
const dispatch = useDispatch(); const dispatch = useDispatch()
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return {}; return {}
}); })
// 插入的题库 // 插入的题库
const [btnLoading, setBtnLoading] = useState(false); const [btnLoading, setBtnLoading] = useState(false)
const [radioList, setRadioList] = useState([]); const [radioList, setRadioList] = useState([])
const [checkboxList, setCheckboxList] = useState([]); const [checkboxList, setCheckboxList] = useState([])
const [equalsList, setEqualsList] = useState([]); const [equalsList, setEqualsList] = useState([])
const [pressList, setPressList] = useState([]); const [pressList, setPressList] = useState([])
const [textareaList, setTextAreaList] = useState([]); const [textareaList, setTextAreaList] = useState([])
// 删除 // 删除
const delConfirm = (record) => { const delConfirm = record => {
const temp = JSON.parse(JSON.stringify(insertList)); const temp = JSON.parse(JSON.stringify(insertList))
const newTemp = temp.filter((item) => parseInt(item.choose_id) !== parseInt(record.choose_id)); const newTemp = temp.filter(item => parseInt(item.choose_id) !== parseInt(record.choose_id))
setInsertList(newTemp); setInsertList(newTemp)
setChooseList(newTemp); setChooseList(newTemp)
}; }
// 添加 // 添加
const addChapterQuestion = async () => { const addChapterQuestion = async () => {
setBtnLoading(true); setBtnLoading(true)
const question_ids = insertList.map((item) => item.choose_id); const question_ids = insertList.map(item => item.choose_id)
const data = await addChapterTopic({ const data = await addChapterTopic({
book_id: bookId, book_id: bookId,
chapter_id: chapterId, chapter_id: chapterId,
question_ids, question_ids,
position: practiceRandom, position: practiceRandom
}); })
if (data) { if (data) {
message.success('添加成功!'); message.success('添加成功!')
dispatch(setPracticeRandom({ practiceNum: '', practiceTitle: '' })); dispatch(setPracticeRandom({ practiceNum: '', practiceTitle: '' }))
setBtnLoading(false); setBtnLoading(false)
closePanel(); closePanel()
}
} }
};
useEffect(() => { useEffect(() => {
if (insertList.length > 0) { if (insertList.length > 0) {
const t1 = insertList.filter((item) => parseInt(item.question_style) === 1); const t1 = insertList.filter(item => parseInt(item.question_style) === 1)
const t2 = insertList.filter((item) => parseInt(item.question_style) === 2); const t2 = insertList.filter(item => parseInt(item.question_style) === 2)
const t3 = insertList.filter((item) => parseInt(item.question_style) === 3); const t3 = insertList.filter(item => parseInt(item.question_style) === 3)
const t4 = insertList.filter((item) => parseInt(item.question_style) === 4); const t4 = insertList.filter(item => parseInt(item.question_style) === 4)
const t5 = insertList.filter((item) => parseInt(item.question_style) === 5); const t5 = insertList.filter(item => parseInt(item.question_style) === 5)
setRadioList(t1); setRadioList(t1)
setCheckboxList(t2); setCheckboxList(t2)
setEqualsList(t3); setEqualsList(t3)
setPressList(t4); setPressList(t4)
setTextAreaList(t5); setTextAreaList(t5)
} else { } else {
setRadioList([]); setRadioList([])
setCheckboxList([]); setCheckboxList([])
setEqualsList([]); setEqualsList([])
setPressList([]); setPressList([])
setTextAreaList([]); setTextAreaList([])
} }
}, [insertList]); }, [insertList])
return ( return (
<div className='practice-insert-container'> <div className="practice-insert-container">
<div className='practice-insert-topic list-topic-box'> <div className="practice-insert-topic list-topic-box">
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='list-topic-container'> <div className="list-topic-container">
<h4>{clacTopicText('radio')}. 单选题</h4> <h4>{clacTopicText('radio')}. 单选题</h4>
<div> <div>
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={index + 1} /> <TopicItem topic={item} index={index + 1} />
</div> </div>
<div className='checkbox'> <div className="checkbox">
<Popconfirm <Popconfirm
title='确认删除此题目吗?' title="确认删除此题目吗?"
onConfirm={() => delConfirm(item)} onConfirm={() => delConfirm(item)}
okText='确认' okText="确认"
cancelText='取消' cancelText="取消">
> <Button type="link" icon={<CloseOutlined />} style={{ color: '#b83956' }}></Button>
<Button
type='link'
icon={<CloseOutlined />}
style={{ color: '#b83956' }}
></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{checkboxList.length > 0 && ( {checkboxList.length > 0 && (
<div className='list-topic-container'> <div className="list-topic-container">
<h4>{clacTopicText('checkbox', radioList)}. 多选题</h4> <h4>{clacTopicText('checkbox', radioList)}. 多选题</h4>
<div> <div>
{checkboxList.map((item, index) => { {checkboxList.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={index + 1} /> <TopicItem topic={item} index={index + 1} />
</div> </div>
<div className='checkbox'> <div className="checkbox">
<Popconfirm <Popconfirm
title='确认删除此题目吗?' title="确认删除此题目吗?"
onConfirm={() => delConfirm(item)} onConfirm={() => delConfirm(item)}
okText='确认' okText="确认"
cancelText='取消' cancelText="取消">
> <Button type="link" icon={<CloseOutlined />} style={{ color: '#b83956' }}></Button>
<Button
type='link'
icon={<CloseOutlined />}
style={{ color: '#b83956' }}
></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{equalsList.length > 0 && ( {equalsList.length > 0 && (
<div className='list-topic-container'> <div className="list-topic-container">
<h4>{clacTopicText('judge', radioList, checkboxList)}. 判断题</h4> <h4>{clacTopicText('judge', radioList, checkboxList)}. 判断题</h4>
<div> <div>
{equalsList.map((item, index) => { {equalsList.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={index + 1} /> <TopicItem topic={item} index={index + 1} />
</div> </div>
<div className='checkbox'> <div className="checkbox">
<Popconfirm <Popconfirm
title='确认删除此题目吗?' title="确认删除此题目吗?"
onConfirm={() => delConfirm(item)} onConfirm={() => delConfirm(item)}
okText='确认' okText="确认"
cancelText='取消' cancelText="取消">
> <Button type="link" icon={<CloseOutlined />} style={{ color: '#b83956' }}></Button>
<Button
type='link'
icon={<CloseOutlined />}
style={{ color: '#b83956' }}
></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{pressList.length > 0 && ( {pressList.length > 0 && (
<div className='list-topic-container'> <div className="list-topic-container">
<h4>{clacTopicText('fill', radioList, checkboxList, equalsList)}. 填空题</h4> <h4>{clacTopicText('fill', radioList, checkboxList, equalsList)}. 填空题</h4>
<div> <div>
{pressList.map((item, index) => { {pressList.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={index + 1} /> <TopicItem topic={item} index={index + 1} />
</div> </div>
<div className='checkbox'> <div className="checkbox">
<Popconfirm <Popconfirm
title='确认删除此题目吗?' title="确认删除此题目吗?"
onConfirm={() => delConfirm(item)} onConfirm={() => delConfirm(item)}
okText='确认' okText="确认"
cancelText='取消' cancelText="取消">
> <Button type="link" icon={<CloseOutlined />} style={{ color: '#b83956' }}></Button>
<Button
type='link'
icon={<CloseOutlined />}
style={{ color: '#b83956' }}
></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='list-topic-container'> <div className="list-topic-container">
<h4>{clacTopicText('textarea', radioList, checkboxList, equalsList, pressList)}. 简答题</h4> <h4>{clacTopicText('textarea', radioList, checkboxList, equalsList, pressList)}. 简答题</h4>
<div> <div>
{textareaList.map((item, index) => { {textareaList.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={index + 1} /> <TopicItem topic={item} index={index + 1} />
</div> </div>
<div className='checkbox'> <div className="checkbox">
<Popconfirm <Popconfirm
title='确认删除此题目吗?' title="确认删除此题目吗?"
onConfirm={() => delConfirm(item)} onConfirm={() => delConfirm(item)}
okText='确认' okText="确认"
cancelText='取消' cancelText="取消">
> <Button type="link" icon={<CloseOutlined />} style={{ color: '#b83956' }}></Button>
<Button
type='link'
icon={<CloseOutlined />}
style={{ color: '#b83956' }}
></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
</div> </div>
<div className='practice-insert-buttons'> <div className="practice-insert-buttons">
<Button type='primary' loading={btnLoading} onClick={addChapterQuestion}> <Button type="primary" loading={btnLoading} onClick={addChapterQuestion}>
确定 确定
</Button> </Button>
</div> </div>
</div> </div>
); )
}); }
export default InsertTopic; export default forwardRef(InsertTopic)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Pagination, Space, Select, Button, Input, Checkbox, Spin, Row, Col } from 'antd'; import { Pagination, Space, Select, Button, Input, Checkbox, Spin, Row, Col } from 'antd'
import TopicItem from './topicItem'; import TopicItem from './topicItem'
import { getList, typeAllList, bookNameList } from '../request'; import { getList, typeAllList, bookNameList } from '../request'
const topicStyle = [ const topicStyle = [
{ id: 1, name: '单选题' }, { id: 1, name: '单选题' },
{ id: 2, name: '多选题' }, { id: 2, name: '多选题' },
{ id: 3, name: '判断题' }, { id: 3, name: '判断题' },
{ id: 4, name: '填空题' }, { id: 4, name: '填空题' },
{ id: 5, name: '简答题' }, { id: 5, name: '简答题' }
]; ]
const ListTopic = forwardRef((props, ref) => { const ListTopic = (props, ref) => {
const { addTopicList, chooseList, setChooseList, bookId, bookNameIdData, practiceStatus, customerType } = props; const { addTopicList, chooseList, setChooseList, bookId, bookNameIdData, practiceStatus, customerType } = props
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false)
const [page, setPage] = useState(1); const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10)
const [source, setSource] = useState([]); const [source, setSource] = useState([])
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0)
const [typeList, setTypeList] = useState([]); const [typeList, setTypeList] = useState([])
const [checkedArr, setCheckedArr] = useState([]); const [checkedArr, setCheckedArr] = useState([])
const [selectedBookId, setSelectedBookId] = useState(bookId); const [selectedBookId, setSelectedBookId] = useState(bookId)
useEffect(() => { useEffect(() => {
let arr = []; let arr = []
chooseList.forEach((item) => { chooseList.forEach(item => {
arr.push(item.choose_id); arr.push(item.choose_id)
}); })
setCheckedArr(arr); setCheckedArr(arr)
}, [chooseList]); }, [chooseList])
// 筛选条件设置 // 筛选条件设置
const [questionStyle, setQuestionStyle] = useState(''); const [questionStyle, setQuestionStyle] = useState('')
const [typeId, setTypeId] = useState(customerType || ''); const [typeId, setTypeId] = useState(customerType || '')
const [titles, setTitles] = useState(''); const [titles, setTitles] = useState('')
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
setPage, setPage
}; }
}); })
// 页码选择 // 页码选择
const onChange = (number) => { const onChange = number => {
setPage(number); setPage(number)
} }
const onShowSizeChange = (current, size) => { const onShowSizeChange = (current, size) => {
setPageSize(size); setPageSize(size)
} }
const getTypeList = async () => { const getTypeList = async () => {
const data = await typeAllList({ page: 1, page_size: 100000 }); const data = await typeAllList({ page: 1, page_size: 100000 })
if (data) setTypeList(data.list); if (data) setTypeList(data.list)
}; }
useEffect(() => { useEffect(() => {
getTypeList(); getTypeList()
}, []); }, [])
const getData = async (bool) => { const getData = async bool => {
setLoading(true); setLoading(true)
let obj = { page, page_size: pageSize }; let obj = { page, page_size: pageSize }
if (questionStyle) obj.question_style = questionStyle; if (questionStyle) obj.question_style = questionStyle
if (typeId) obj.type_id = typeId; if (typeId) obj.type_id = typeId
if (titles) obj.titles = titles; if (titles) obj.titles = titles
if (selectedBookId) obj.book_id = selectedBookId; if (selectedBookId) obj.book_id = selectedBookId
if (bool) { if (bool) {
setPage(1); setPage(1)
obj.page = 1; obj.page = 1
} }
const data = await getList(obj); const data = await getList(obj)
if (data) { if (data) {
let dataSource = []; let dataSource = []
data.list.forEach((item, index) => { data.list.forEach((item, index) => {
dataSource.push({ ...item, choose_id: item.id }); dataSource.push({ ...item, choose_id: item.id })
}); })
setTotal(data.total); setTotal(data.total)
setSource(dataSource); setSource(dataSource)
}
setLoading(false)
} }
setLoading(false);
};
useEffect(() => { useEffect(() => {
if (selectedBookId !== null && !practiceStatus && customerType) { if (selectedBookId !== null && !practiceStatus && customerType) {
getData(true); getData(true)
} else { } else {
getData(); getData()
} }
}, [page, pageSize, practiceStatus, customerType])
}, [page, pageSize, practiceStatus, customerType]);
const topicChange = (e, record) => { const topicChange = (e, record) => {
const temp = JSON.parse(JSON.stringify(chooseList)); const temp = JSON.parse(JSON.stringify(chooseList))
let newTemp = []; let newTemp = []
if (e.target.checked) { if (e.target.checked) {
newTemp = [...temp, record]; newTemp = [...temp, record]
} else { } else {
newTemp = temp.filter((item) => item.choose_id !== record.choose_id); newTemp = temp.filter(item => item.choose_id !== record.choose_id)
}
setChooseList(newTemp)
} }
setChooseList(newTemp);
};
return ( return (
<div className='list-topic-container'> <div className="list-topic-container">
<div className='list-topic-filter'> <div className="list-topic-filter">
<div className='list-topic-filter-list'> <div className="list-topic-filter-list">
<div className='filter-item'> <div className="filter-item">
<Space> <Space>
<span className='label'>书籍名称:</span> <span className="label">书籍名称:</span>
<Select <Select
placeholder='请选择书籍名称' placeholder="请选择书籍名称"
allowClear allowClear
defaultValue={bookId} defaultValue={bookId}
value={selectedBookId} value={selectedBookId}
onChange={(value) => { onChange={value => {
setSelectedBookId(value); setSelectedBookId(value)
}} }}>
>
{bookNameIdData && {bookNameIdData &&
bookNameIdData.length > 0 && bookNameIdData.length > 0 &&
bookNameIdData.map((item, index) => ( bookNameIdData.map((item, index) => (
...@@ -132,15 +130,14 @@ const ListTopic = forwardRef((props, ref) => { ...@@ -132,15 +130,14 @@ const ListTopic = forwardRef((props, ref) => {
</Select> </Select>
</Space> </Space>
</div> </div>
<div className='filter-item'> <div className="filter-item">
<Space> <Space>
<span className='label'>题目类型:</span> <span className="label">题目类型:</span>
<Select <Select
placeholder='请选择题目类型' placeholder="请选择题目类型"
value={questionStyle} value={questionStyle}
onChange={(value) => setQuestionStyle(value)} onChange={value => setQuestionStyle(value)}
allowClear allowClear>
>
{topicStyle && {topicStyle &&
topicStyle.length > 0 && topicStyle.length > 0 &&
topicStyle.map((item, index) => ( topicStyle.map((item, index) => (
...@@ -151,15 +148,10 @@ const ListTopic = forwardRef((props, ref) => { ...@@ -151,15 +148,10 @@ const ListTopic = forwardRef((props, ref) => {
</Select> </Select>
</Space> </Space>
</div> </div>
<div className='filter-item'> <div className="filter-item">
<Space> <Space>
<span className='label'>题目分类:</span> <span className="label">题目分类:</span>
<Select <Select placeholder="请选择题目分类" value={typeId} onChange={value => setTypeId(value)} allowClear>
placeholder='请选择题目分类'
value={typeId}
onChange={(value) => setTypeId(value)}
allowClear
>
{typeList && {typeList &&
typeList.length > 0 && typeList.length > 0 &&
typeList.map((item, index) => ( typeList.map((item, index) => (
...@@ -170,50 +162,42 @@ const ListTopic = forwardRef((props, ref) => { ...@@ -170,50 +162,42 @@ const ListTopic = forwardRef((props, ref) => {
</Select> </Select>
</Space> </Space>
</div> </div>
<div className='filter-item'> <div className="filter-item">
<Space> <Space>
<span className='label'>题干名称:</span> <span className="label">题干名称:</span>
<Input <Input placeholder="请输入题干名称" value={titles} onChange={e => setTitles(e.target.value)} allowClear />
placeholder='请输入题干名称'
value={titles}
onChange={(e) => setTitles(e.target.value)}
allowClear
/>
</Space> </Space>
</div> </div>
</div> </div>
<div className='list-topic-filter-btn'> <div className="list-topic-filter-btn">
<Space> <Space>
<Button type='default' onClick={() => getData(true)}> <Button type="default" onClick={() => getData(true)}>
筛选 筛选
</Button> </Button>
</Space> </Space>
</div> </div>
</div> </div>
<div className='list-topic-box'> <div className="list-topic-box">
<Spin spinning={loading}> <Spin spinning={loading}>
{/* <Checkbox.Group> */} {/* <Checkbox.Group> */}
{source && {source &&
source.length > 0 && source.length > 0 &&
source.map((item, index) => { source.map((item, index) => {
return ( return (
<div className='topic-item' key={index}> <div className="topic-item" key={index}>
<div className='checkbox'> <div className="checkbox">
<Checkbox <Checkbox checked={checkedArr.includes(item.choose_id)} onChange={e => topicChange(e, item)} />
checked={checkedArr.includes(item.choose_id)}
onChange={(e) => topicChange(e, item)}
/>
</div> </div>
<div className='topic-info'> <div className="topic-info">
<TopicItem topic={item} index={(page - 1) * pageSize + index + 1} /> <TopicItem topic={item} index={(page - 1) * pageSize + index + 1} />
</div> </div>
</div> </div>
); )
})} })}
{/* </Checkbox.Group> */} {/* </Checkbox.Group> */}
</Spin> </Spin>
</div> </div>
<div className='list-page'> <div className="list-page">
<Pagination <Pagination
showQuickJumper showQuickJumper
showSizeChanger showSizeChanger
...@@ -223,12 +207,12 @@ const ListTopic = forwardRef((props, ref) => { ...@@ -223,12 +207,12 @@ const ListTopic = forwardRef((props, ref) => {
onShowSizeChange={onShowSizeChange} onShowSizeChange={onShowSizeChange}
/> />
<Button type='primary' onClick={addTopicList}> <Button type="primary" onClick={addTopicList}>
添加 添加
</Button> </Button>
</div> </div>
</div> </div>
); )
}); }
export default ListTopic; export default forwardRef(ListTopic)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Input } from 'antd'; import { Input } from 'antd'
const inCorrect = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; const inCorrect = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z'
]
const TopicItem = forwardRef((props, ref) => { const TopicItem = (props, ref) => {
const { topic, index, preview = false } = props; const { topic, index, preview = false } = props
const [recordInfo, setRecordInfo] = useState({}); const [recordInfo, setRecordInfo] = useState({})
const [choose, setChoose] = useState(false); const [choose, setChoose] = useState(false)
const [chooseAnswer, setChooseAnswer] = useState([]); const [chooseAnswer, setChooseAnswer] = useState([])
const [isMap, setIsMap] = useState(false); const [isMap, setIsMap] = useState(false)
useEffect(() => { useEffect(() => {
if (Object.entries(topic).length) { if (Object.entries(topic).length) {
let temp = {}; let temp = {}
for (const key in topic) { for (const key in topic) {
if (key === 'question_list') { if (key === 'question_list') {
try { try {
temp[key] = JSON.parse(topic[key]); temp[key] = JSON.parse(topic[key])
} catch (e) { } catch (e) {
temp[key] = topic[key]; temp[key] = topic[key]
} }
} else { } else {
temp[key] = topic[key]; temp[key] = topic[key]
} }
} }
if (temp.question_style === 1 || temp.question_style === 2 || temp.question_style === 3) { if (temp.question_style === 1 || temp.question_style === 2 || temp.question_style === 3) {
setChoose(true); setChoose(true)
} }
if (temp.question_list instanceof Array && temp.question_list.length > 0) { if (temp.question_list instanceof Array && temp.question_list.length > 0) {
setIsMap(true); setIsMap(true)
let an = []; let an = []
temp.question_list.forEach((item, index) => { temp.question_list.forEach((item, index) => {
if (item.correct && (item.correct === 'true' || item.correct === true)) { if (item.correct && (item.correct === 'true' || item.correct === true)) {
an.push(inCorrect[index]); an.push(inCorrect[index])
} }
}); })
setChooseAnswer(an); setChooseAnswer(an)
} }
setRecordInfo(temp); setRecordInfo(temp)
} }
}, [topic]); }, [topic])
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return {}; return {}
}); })
return ( return (
<div className='topic-item-info'> <div className="topic-item-info">
{Object.entries(recordInfo).length && ( {Object.entries(recordInfo).length && (
<> <>
<div className='index'>{index}.</div> <div className="index">{index}.</div>
<div className='topic'> <div className="topic">
{/* <div>{recordInfo.titles}</div> */} {/* <div>{recordInfo.titles}</div> */}
<div <div className="topic-choose-title" dangerouslySetInnerHTML={{ __html: recordInfo.titles }}></div>
className='topic-choose-title'
dangerouslySetInnerHTML={{ __html: recordInfo.titles }}
></div>
{[1, 2, 3].includes(parseInt(recordInfo.question_style)) && ( {[1, 2, 3].includes(parseInt(recordInfo.question_style)) && (
<div className='topic-choose'> <div className="topic-choose">
{choose && {choose &&
isMap && isMap &&
recordInfo && recordInfo &&
...@@ -67,28 +91,27 @@ const TopicItem = forwardRef((props, ref) => { ...@@ -67,28 +91,27 @@ const TopicItem = forwardRef((props, ref) => {
recordInfo.question_list.map((item, cindex) => { recordInfo.question_list.map((item, cindex) => {
return ( return (
<div <div
className='topic-choose-item' className="topic-choose-item"
key={cindex} key={cindex}
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `${inCorrect[cindex]}. ` + item.option, __html: `${inCorrect[cindex]}. ` + item.option
}} }}></div>
></div> )
);
})} })}
</div> </div>
)} )}
{preview && ( {preview && (
<div className='notes-preivew'> <div className="notes-preivew">
{recordInfo.question_style === 5 && ( {recordInfo.question_style === 5 && (
<div className='textarea'> <div className="textarea">
<Input.TextArea autoSize={{ minRows: 3, maxRows: 4 }} /> <Input.TextArea autoSize={{ minRows: 3, maxRows: 4 }} />
</div> </div>
)} )}
</div> </div>
)} )}
<div className='answer'> <div className="answer">
<strong>答案: </strong> <strong>答案: </strong>
{[1, 2, 3].includes(recordInfo.question_style) ? ( {[1, 2, 3].includes(recordInfo.question_style) ? (
<span>{chooseAnswer.join(' ')}</span> <span>{chooseAnswer.join(' ')}</span>
...@@ -100,7 +123,7 @@ const TopicItem = forwardRef((props, ref) => { ...@@ -100,7 +123,7 @@ const TopicItem = forwardRef((props, ref) => {
</> </>
)} )}
</div> </div>
); )
}); }
export default TopicItem; export default forwardRef(TopicItem)
...@@ -16,7 +16,7 @@ import { bookNameList } from './request' ...@@ -16,7 +16,7 @@ import { bookNameList } from './request'
import '../utils/iconfont' import '../utils/iconfont'
import './index.less' import './index.less'
const PracticeSettingModal = forwardRef((props, ref) => { const PracticeSettingModal = (props, ref) => {
const { editor, chapterId, bookId, closePanel } = props const { editor, chapterId, bookId, closePanel } = props
const dispatch = useDispatch() const dispatch = useDispatch()
const { practiceRandom, practiceTitle, practiceTheme } = useSelector(state => state.editor) const { practiceRandom, practiceTitle, practiceTheme } = useSelector(state => state.editor)
...@@ -248,6 +248,6 @@ const PracticeSettingModal = forwardRef((props, ref) => { ...@@ -248,6 +248,6 @@ const PracticeSettingModal = forwardRef((props, ref) => {
</Row> </Row>
</div> </div>
) )
}) }
export default PracticeSettingModal export default forwardRef(PracticeSettingModal)
import React, { useEffect, useState, useRef, useImperativeHandle, forwardRef } from 'react'; import React, { useEffect, useState, useRef, useImperativeHandle, forwardRef } from 'react'
import { Modal, Drawer, Tree, Spin, Space, Button, Input, Image } from 'antd'; import { Modal, Drawer, Tree, Spin, Space, Button, Input, Image } from 'antd'
import { CloseOutlined, LeftOutlined, BarsOutlined } from '@ant-design/icons'; import { CloseOutlined, LeftOutlined, BarsOutlined } from '@ant-design/icons'
import { getInfoByChapterId, getAllList } from '@/pages/books/section/request'; import { getInfoByChapterId, getAllList } from '@/pages/books/section/request'
import { getChapterTopic, expandReadInfo } from '@/common/wangeditor-customer/utils/request'; import { getChapterTopic, expandReadInfo } from '@/common/wangeditor-customer/utils/request'
import '@/common/wangeditor-customer/utils/iconfont'; import '@/common/wangeditor-customer/utils/iconfont'
import { import { convertToAntdTreeData, findTreeElementByKey, findFirstNotHasChildren, clacTopicText } from '@/utils/common'
convertToAntdTreeData, import { get } from 'lodash-es'
findTreeElementByKey, import $ from 'jquery'
findFirstNotHasChildren, import '@/common/preview.less'
clacTopicText,
} from '@/utils/common'; import hljs from 'highlight.js'
import { get } from 'lodash-es'; import 'highlight.js/styles/github.css'
import $ from 'jquery';
import '@/common/preview.less';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';
const correctList = [ const correctList = [
'A', 'A',
...@@ -43,196 +38,194 @@ const correctList = [ ...@@ -43,196 +38,194 @@ const correctList = [
'W', 'W',
'X', 'X',
'Y', 'Y',
'Z', 'Z'
]; ]
const PreviewScreen = forwardRef((props, ref) => { const PreviewScreen = (props, ref) => {
const { bookId } = props; const { bookId } = props
const [gData, setGData] = useState([]); const [gData, setGData] = useState([])
const [loading, setLoading] = useState(false); // 展示 const [loading, setLoading] = useState(false) // 展示
const [prviewHtml, setPrviewHtml] = useState(''); // 预览html const [prviewHtml, setPrviewHtml] = useState('') // 预览html
const [open, setOpen] = useState(false); // 抽屉 const [open, setOpen] = useState(false) // 抽屉
const [secondType, setSecondType] = useState(false); const [secondType, setSecondType] = useState(false)
const [toolTip, setTooltip] = useState({}); const [toolTip, setTooltip] = useState({})
// 树节点设置 // 树节点设置
const [expandedKeys, setExpandedKeys] = useState([]); const [expandedKeys, setExpandedKeys] = useState([])
const [checkedKeys, setCheckedKeys] = useState([]); const [checkedKeys, setCheckedKeys] = useState([])
const [headTitle, setHeadTitle] = useState(''); const [headTitle, setHeadTitle] = useState('')
const [oldTitle, setOldTitle] = useState(''); const [oldTitle, setOldTitle] = useState('')
const [newChapterId, setNewChapterId] = useState(''); const [newChapterId, setNewChapterId] = useState('')
const [opend, setOpend] = useState(false); const [opend, setOpend] = useState(false)
const [gallery, setGallery] = useState([]); const [gallery, setGallery] = useState([])
const [galleryIndex, setGalleryIndex] = useState(0); const [galleryIndex, setGalleryIndex] = useState(0)
const [isType, setIsType] = useState(''); const [isType, setIsType] = useState('')
const [topicList, setTopicList] = useState([]); // 题库 const [topicList, setTopicList] = useState([]) // 题库
const [radioList, setRadioList] = useState([]); // 单选 const [radioList, setRadioList] = useState([]) // 单选
const [checkBoxList, setCheckBoxList] = useState([]); // 多选 const [checkBoxList, setCheckBoxList] = useState([]) // 多选
const [judgeList, setJudgeList] = useState([]); // 判断 const [judgeList, setJudgeList] = useState([]) // 判断
const [fillList, setFillList] = useState([]); // 填空 const [fillList, setFillList] = useState([]) // 填空
const [textareaList, setTextareaList] = useState([]); // 简答 const [textareaList, setTextareaList] = useState([]) // 简答
const [expandContent, setExpandContent] = useState(''); // 扩展阅读内容 const [expandContent, setExpandContent] = useState('') // 扩展阅读内容
const [previewImg, setPreviewImg] = useState(''); // 扩展阅读内容 const [previewImg, setPreviewImg] = useState('') // 扩展阅读内容
const newId = useRef(null); const newId = useRef(null)
// 递归函数,获取所有节点的key // 递归函数,获取所有节点的key
const getAllNodeKeys = (nodes) => { const getAllNodeKeys = nodes => {
let keys = []; let keys = []
nodes.forEach((node) => { nodes.forEach(node => {
keys.push(node.key); keys.push(node.key)
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
keys = keys.concat(getAllNodeKeys(node.children)); keys = keys.concat(getAllNodeKeys(node.children))
}
})
return keys
} }
});
return keys;
};
const getChapterTreeList = async () => { const getChapterTreeList = async () => {
setLoading(true); setLoading(true)
const data = await getAllList({ book_id: bookId }); const data = await getAllList({ book_id: bookId })
if (!data.data.length) { if (!data.data.length) {
setLoading(false); setLoading(false)
return; return
}
const arr = convertToAntdTreeData(data.data, 'name')
setGData(arr)
const allKeys = getAllNodeKeys(arr)
setExpandedKeys(allKeys)
const first = findFirstNotHasChildren(arr)
setOldTitle(first.title)
setNewChapterId(first.key)
setLoading(false)
} }
const arr = convertToAntdTreeData(data.data, 'name');
setGData(arr);
const allKeys = getAllNodeKeys(arr);
setExpandedKeys(allKeys);
const first = findFirstNotHasChildren(arr);
setOldTitle(first.title);
setNewChapterId(first.key);
setLoading(false);
};
const getTopicList = async ({ practicenum, chapterid, bookid }) => { const getTopicList = async ({ practicenum, chapterid, bookid }) => {
const data = await getChapterTopic({ const data = await getChapterTopic({
position: practicenum, position: practicenum,
book_id: bookid, book_id: bookid,
chapter_id: chapterid, chapter_id: chapterid
}); })
const temp = []; const temp = []
data.forEach((item) => { data.forEach(item => {
let obj = { ...item }; let obj = { ...item }
if ([1, 2, 3].includes(parseInt(item.question_style))) { if ([1, 2, 3].includes(parseInt(item.question_style))) {
try { try {
obj.question_list = JSON.parse(item.question_list); obj.question_list = JSON.parse(item.question_list)
} catch (err) { } catch (err) {
obj.question_list = []; obj.question_list = []
} }
} }
temp.push(obj); temp.push(obj)
}); })
const tempRadio = temp.filter((item) => parseInt(item.question_style) === 1); const tempRadio = temp.filter(item => parseInt(item.question_style) === 1)
const tempCheckbox = temp.filter((item) => parseInt(item.question_style) === 2); const tempCheckbox = temp.filter(item => parseInt(item.question_style) === 2)
const tempJudge = temp.filter((item) => parseInt(item.question_style) === 3); const tempJudge = temp.filter(item => parseInt(item.question_style) === 3)
const tempFill = temp.filter((item) => parseInt(item.question_style) === 4); const tempFill = temp.filter(item => parseInt(item.question_style) === 4)
const tempTextarea = temp.filter((item) => parseInt(item.question_style) === 5); const tempTextarea = temp.filter(item => parseInt(item.question_style) === 5)
setRadioList(tempRadio); setRadioList(tempRadio)
setCheckBoxList(tempCheckbox); setCheckBoxList(tempCheckbox)
setJudgeList(tempJudge); setJudgeList(tempJudge)
setFillList(tempFill); setFillList(tempFill)
setTextareaList(tempTextarea); setTextareaList(tempTextarea)
setTopicList(temp); setTopicList(temp)
}; }
const getExpandInfo = async ({ chapterId, position }) => { const getExpandInfo = async ({ chapterId, position }) => {
const data = await expandReadInfo({ const data = await expandReadInfo({
book_id: bookId, book_id: bookId,
chapter_id: chapterId, chapter_id: chapterId,
position: position, position: position
}); })
if (data) { if (data) {
setExpandContent(data.content); setExpandContent(data.content)
}
} }
};
const getChapterId = async () => { const getChapterId = async () => {
setLoading(true); setLoading(true)
newId.current = newChapterId; newId.current = newChapterId
const data = await getInfoByChapterId({ chapter_id: newChapterId }); const data = await getInfoByChapterId({ chapter_id: newChapterId })
if (data) { if (data) {
const content = get(data, 'content', ''); const content = get(data, 'content', '')
setPrviewHtml(content); setPrviewHtml(content)
$('#previee-container') $('#previee-container')
.find('video audio') .find('video audio')
.each((index, item) => { .each((index, item) => {
$(item).attr('controls', true).attr('controlslist', 'nodownload'); $(item).attr('controls', true).attr('controlslist', 'nodownload')
}); })
setTimeout(() => { setTimeout(() => {
document document
.querySelectorAll('.preview-content-show ')[0] .querySelectorAll('.preview-content-show ')[0]
.querySelectorAll('pre code') .querySelectorAll('pre code')
.forEach((el) => { .forEach(el => {
hljs.highlightElement(el); hljs.highlightElement(el)
}); })
}, 200); }, 200)
}
setLoading(false)
} }
setLoading(false);
};
const handlerClick = () => { const handlerClick = () => {
const iParentW = $('.preview-content-it').innerWidth(); const iParentW = $('.preview-content-it').innerWidth()
const iParentH = $('.preview-content-it').innerHeight(); const iParentH = $('.preview-content-it').innerHeight()
const parentOffset = $('.preview-content-it').offset(); // 获取父元素相对于文档的位置 const parentOffset = $('.preview-content-it').offset() // 获取父元素相对于文档的位置
const parentRect = $('.preview-content-it')[0].getBoundingClientRect(); // 获取父元素相对于文档的位置 const parentRect = $('.preview-content-it')[0].getBoundingClientRect() // 获取父元素相对于文档的位置
$('.preview-content-html').on('click', async (ev) => { $('.preview-content-html').on('click', async ev => {
ev.stopPropagation(); ev.stopPropagation()
const target = ev.target; const target = ev.target
const tooltip = $(target).closest('.chapter-item-tooltip'); const tooltip = $(target).closest('.chapter-item-tooltip')
const alink = $(target).closest('.chapter-item-link'); const alink = $(target).closest('.chapter-item-link')
const aGallery = $(target).closest('.chapter-gallery-container'); const aGallery = $(target).closest('.chapter-gallery-container')
const practice = $(target).closest('.chapter-practice'); const practice = $(target).closest('.chapter-practice')
const aA = $(target).closest('a'); const aA = $(target).closest('a')
const aExpand = $(target).closest('.chapter-expand'); const aExpand = $(target).closest('.chapter-expand')
if (tooltip.length > 0) { if (tooltip.length > 0) {
const random = $(tooltip).data('random'); const random = $(tooltip).data('random')
const link = $(tooltip).data('link'); const link = $(tooltip).data('link')
const content = $(tooltip).data('content'); const content = $(tooltip).data('content')
const tooltipType = $(tooltip).data('tooltip-type'); const tooltipType = $(tooltip).data('tooltip-type')
const title = $(tooltip).data('title'); const title = $(tooltip).data('title')
const tooltipParent = $(target).closest( const tooltipParent = $(target).closest('p, div, h1, h2, h3, h4, h5, h6, li, dt, dd, section')
'p, div, h1, h2, h3, h4, h5, h6, li, dt, dd, section', const tooltipParentPosition = $(tooltipParent).position()
); const tooltipPosition = $(tooltip).position()
const tooltipParentPosition = $(tooltipParent).position(); const childOffset = $(tooltip).offset() // 获取子元素相对于文档的位置
const tooltipPosition = $(tooltip).position(); const childWidth = $(tooltip).outerWidth(true) // 获取元素的宽度
const childOffset = $(tooltip).offset(); // 获取子元素相对于文档的位置 const childHeight = $(tooltip).outerHeight(true) // 获取元素的高度
const childWidth = $(tooltip).outerWidth(true); // 获取元素的宽度 let toolRect = null
const childHeight = $(tooltip).outerHeight(true); // 获取元素的高度 let targetPositon = null
let toolRect = null;
let targetPositon = null;
if (target.nodeName.toLowerCase() === 'svg' || target.nodeName.toLowerCase() === 'use') { if (target.nodeName.toLowerCase() === 'svg' || target.nodeName.toLowerCase() === 'use') {
toolRect = target.parentNode.parentNode.getBoundingClientRect(); toolRect = target.parentNode.parentNode.getBoundingClientRect()
targetPositon = $(target).closest('.chapter-item-tooltip').position(); targetPositon = $(target).closest('.chapter-item-tooltip').position()
} else { } else {
toolRect = target.parentNode.getBoundingClientRect(); toolRect = target.parentNode.getBoundingClientRect()
targetPositon = $(target).position(); targetPositon = $(target).position()
} }
const lineHeight = $(tooltip).css('line-height'); const lineHeight = $(tooltip).css('line-height')
let inSide = ''; let inSide = ''
let left = childOffset.left - parentOffset.left; let left = childOffset.left - parentOffset.left
let top = 0; let top = 0
let squareStyle = {}; let squareStyle = {}
if (childWidth + left >= iParentW) { if (childWidth + left >= iParentW) {
left = iParentW - childWidth - 10; left = iParentW - childWidth - 10
} }
if (left <= 0) { if (left <= 0) {
left = 10; left = 10
} }
let style1 = { let style1 = {
top: `${top}px`, top: `${top}px`,
left: `${left}px`, left: `${left}px`
}; }
setTooltip({ setTooltip({
title, title,
...@@ -242,52 +235,52 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -242,52 +235,52 @@ const PreviewScreen = forwardRef((props, ref) => {
tooltipType, tooltipType,
inSide, inSide,
style: style1, style: style1,
squareStyle: squareStyle, squareStyle: squareStyle
}); })
setTimeout(() => { setTimeout(() => {
const childMoveHeight = $('.tooltip').outerHeight(); // 获取元素的高度 const childMoveHeight = $('.tooltip').outerHeight() // 获取元素的高度
const childMoveWidth = $('.tooltip').outerWidth(); // 获取元素的高度 const childMoveWidth = $('.tooltip').outerWidth() // 获取元素的高度
const scrollTop = $('.preview-content-show').scrollTop(); const scrollTop = $('.preview-content-show').scrollTop()
let squareStyle = {}; let squareStyle = {}
if (left <= 0) { if (left <= 0) {
left = 10; left = 10
squareStyle.left = 10; squareStyle.left = 10
} else if (left + childMoveWidth >= iParentW) { } else if (left + childMoveWidth >= iParentW) {
left = iParentW - childMoveWidth - 20; left = iParentW - childMoveWidth - 20
squareStyle.left = targetPositon.left - left; squareStyle.left = targetPositon.left - left
} else { } else {
squareStyle.left = childWidth / 2; squareStyle.left = childWidth / 2
} }
// 换行了 // 换行了
if (toolRect.height / 1.5 > parseInt(lineHeight)) { if (toolRect.height / 1.5 > parseInt(lineHeight)) {
left = toolRect.right - parentRect.left - childMoveWidth + 15; left = toolRect.right - parentRect.left - childMoveWidth + 15
squareStyle.left = childMoveWidth - 30; squareStyle.left = childMoveWidth - 30
} }
// 是否被遮挡 // 是否被遮挡
if (tooltipPosition.top + childMoveHeight + childHeight + 30 >= scrollTop + iParentH) { if (tooltipPosition.top + childMoveHeight + childHeight + 30 >= scrollTop + iParentH) {
inSide = 'bottom'; inSide = 'bottom'
top = tooltipPosition.top - childMoveHeight; top = tooltipPosition.top - childMoveHeight
squareStyle.left = childWidth / 2; squareStyle.left = childWidth / 2
} else { } else {
inSide = 'top'; inSide = 'top'
if (toolRect.height / 1.5 > parseInt(lineHeight)) { if (toolRect.height / 1.5 > parseInt(lineHeight)) {
top = tooltipPosition.top + childHeight; top = tooltipPosition.top + childHeight
} else { } else {
top = tooltipPosition.top + childHeight + 25; top = tooltipPosition.top + childHeight + 25
} }
// squareStyle.left = childWidth / 2; // squareStyle.left = childWidth / 2;
} }
top = top - scrollTop; top = top - scrollTop
let style2 = { let style2 = {
top: `${top}px`, top: `${top}px`,
left: `${left}px`, left: `${left}px`,
zIndex: 1000, zIndex: 1000,
opacity: 1, opacity: 1
}; }
setTooltip({ setTooltip({
title, title,
random, random,
...@@ -296,493 +289,448 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -296,493 +289,448 @@ const PreviewScreen = forwardRef((props, ref) => {
tooltipType, tooltipType,
inSide, inSide,
style: style2, style: style2,
squareStyle: squareStyle, squareStyle: squareStyle
}); })
}, 100); }, 100)
return false; return false
} else if (alink.length > 0) { } else if (alink.length > 0) {
const link = $(alink).data('link'); const link = $(alink).data('link')
const linkType = $(alink).data('linktype'); const linkType = $(alink).data('linktype')
const chapters = $(alink).data('chapters'); const chapters = $(alink).data('chapters')
const title = $(alink).data('title'); const title = $(alink).data('title')
let last = ''; let last = ''
if (parseInt(linkType) === 2) { if (parseInt(linkType) === 2) {
if (chapters.toString().indexOf(',') > -1) { if (chapters.toString().indexOf(',') > -1) {
const arr = chapters.split(','); const arr = chapters.split(',')
last = arr[arr.length - 1]; last = arr[arr.length - 1]
} else { } else {
last = chapters; last = chapters
} }
setHeadTitle(title); setHeadTitle(title)
setOpend(true); setOpend(true)
setNewChapterId(last); setNewChapterId(last)
} else { } else {
window.open(link); window.open(link)
} }
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aGallery.length > 0) { } else if (aGallery.length > 0) {
const title = $(aGallery).data('title'); const title = $(aGallery).data('title')
const flex = $(aGallery).data('flex'); const flex = $(aGallery).data('flex')
const gallerylist = $(aGallery).data('gallerylist'); const gallerylist = $(aGallery).data('gallerylist')
const galleryArr = JSON.parse(decodeURI(gallerylist)); const galleryArr = JSON.parse(decodeURI(gallerylist))
if (galleryArr && galleryArr.length > 0 && galleryArr instanceof Array) { if (galleryArr && galleryArr.length > 0 && galleryArr instanceof Array) {
setGallery(galleryArr); setGallery(galleryArr)
if (parseInt(flex) === 2) { if (parseInt(flex) === 2) {
setGalleryIndex(0); setGalleryIndex(0)
} else { } else {
setGalleryIndex($(target).closest('.chapter-gallery-item').index()); setGalleryIndex($(target).closest('.chapter-gallery-item').index())
} }
} else { } else {
setGallery([]); setGallery([])
} }
setOpend(true); setOpend(true)
setHeadTitle(title); setHeadTitle(title)
setIsType('gallery'); setIsType('gallery')
setTooltip({}); setTooltip({})
return false; return false
} else if (practice.length > 0) { } else if (practice.length > 0) {
const title = $(practice).data('title'); const title = $(practice).data('title')
const bookid = $(practice).data('bookid'); const bookid = $(practice).data('bookid')
const chapterid = $(practice).data('chapterid'); const chapterid = $(practice).data('chapterid')
const practicenum = $(practice).data('practicenum'); const practicenum = $(practice).data('practicenum')
getTopicList({ practicenum, chapterid, bookid }); getTopicList({ practicenum, chapterid, bookid })
setOpend(true); setOpend(true)
setHeadTitle(title); setHeadTitle(title)
setIsType('practice'); setIsType('practice')
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aA.length > 0) { } else if (aA.length > 0) {
const href = $(aA).attr('href'); const href = $(aA).attr('href')
let newLink = ''; let newLink = ''
if (!/^https*:\/\//.test(href)) { if (!/^https*:\/\//.test(href)) {
newLink = `http://${href}`; newLink = `http://${href}`
} else { } else {
newLink = href; newLink = href
} }
window.open(newLink); window.open(newLink)
ev.preventDefault(); ev.preventDefault()
return false; return false
} else if (aExpand.length > 0) { } else if (aExpand.length > 0) {
const title = $(aExpand).data('title'); const title = $(aExpand).data('title')
const name = $(aExpand).data('name'); const name = $(aExpand).data('name')
const position = $(aExpand).data('random'); const position = $(aExpand).data('random')
setOpend(true); setOpend(true)
setIsType('expand'); setIsType('expand')
setHeadTitle(name); setHeadTitle(name)
await getExpandInfo({ chapterId: newId.current, position }); await getExpandInfo({ chapterId: newId.current, position })
} else if (target.nodeName.toLowerCase() === 'img') { } else if (target.nodeName.toLowerCase() === 'img') {
const alt = $(target).attr('alt'); const alt = $(target).attr('alt')
const src = $(target).attr('src'); const src = $(target).attr('src')
setOpend(true); setOpend(true)
setIsType('img'); setIsType('img')
setPreviewImg(src); setPreviewImg(src)
setHeadTitle(alt ? alt : '图片展示'); setHeadTitle(alt ? alt : '图片展示')
} }
setTooltip({}); setTooltip({})
setGallery([]); setGallery([])
}); })
$('.expand-content, .gallery-prview-container').on('click', (ev) => { $('.expand-content, .gallery-prview-container').on('click', ev => {
const target = ev.target; const target = ev.target
if (target.nodeName.toLowerCase() === 'img') { if (target.nodeName.toLowerCase() === 'img') {
const alt = $(target).attr('alt'); const alt = $(target).attr('alt')
const src = $(target).attr('src'); const src = $(target).attr('src')
setOpend(true); setOpend(true)
setIsType('img'); setIsType('img')
setPreviewImg(src); setPreviewImg(src)
setSecondType('扩展图片'); setSecondType('扩展图片')
}
})
} }
});
};
useEffect(() => { useEffect(() => {
handlerClick(); handlerClick()
}, [isType]); }, [isType])
useEffect(() => { useEffect(() => {
if (bookId) { if (bookId) {
getChapterTreeList(); getChapterTreeList()
} }
}, [bookId]); }, [bookId])
useEffect(() => { useEffect(() => {
if (newChapterId) { if (newChapterId) {
getChapterId(); getChapterId()
} }
}, [newChapterId]); }, [newChapterId])
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false)
}; }
const openDrawer = (e) => { const openDrawer = e => {
e.preventDefault(); e.preventDefault()
e.stopPropagation(); e.stopPropagation()
setOpen(true); setOpen(true)
}; }
const handleSelect = async (checkedKeys, info) => { const handleSelect = async (checkedKeys, info) => {
if (info.node.children && info.node.children.length > 0) { if (info.node.children && info.node.children.length > 0) {
const temp = JSON.parse(JSON.stringify(expandedKeys)); const temp = JSON.parse(JSON.stringify(expandedKeys))
if (temp.includes(info.node.key)) { if (temp.includes(info.node.key)) {
const newExpands = temp.filter((item) => item !== info.node.key); const newExpands = temp.filter(item => item !== info.node.key)
setExpandedKeys([...newExpands]); setExpandedKeys([...newExpands])
} else { } else {
setExpandedKeys([...temp, info.node.key]); setExpandedKeys([...temp, info.node.key])
} }
} else { } else {
setOldTitle(info.node.title); setOldTitle(info.node.title)
setNewChapterId(info.node.key); setNewChapterId(info.node.key)
newId.current = info.node.key; newId.current = info.node.key
setCheckedKeys(checkedKeys); setCheckedKeys(checkedKeys)
setOpen(false); setOpen(false)
}
} }
};
const galleryLeft = () => { const galleryLeft = () => {
let temp = galleryIndex; let temp = galleryIndex
if (temp <= 0) { if (temp <= 0) {
temp = 0; temp = 0
} else { } else {
temp = temp - 1; temp = temp - 1
}
setGalleryIndex(temp)
} }
setGalleryIndex(temp);
};
const galleryRight = () => { const galleryRight = () => {
let temp = galleryIndex; let temp = galleryIndex
if (temp >= gallery.length - 1) { if (temp >= gallery.length - 1) {
temp = gallery.length - 1; temp = gallery.length - 1
} else { } else {
temp = temp + 1; temp = temp + 1
}
setGalleryIndex(temp)
} }
setGalleryIndex(temp);
};
return ( return (
<div className='priview-modal'> <div className="priview-modal">
{/* <Spin spinning={loading}> */} {/* <Spin spinning={loading}> */}
<div className='previee-container' id='previee-container'> <div className="previee-container" id="previee-container">
<div className='chapter-head-title'> <div className="chapter-head-title">
<h2 className='tree'> <h2 className="tree">
{opend ? ( {opend ? (
<Space> <Space>
<Button <Button
type='text' type="text"
onClick={() => { onClick={() => {
if (secondType) { if (secondType) {
setSecondType(false); setSecondType(false)
setPreviewImg(null); setPreviewImg(null)
setIsType('expand'); setIsType('expand')
return; return
} }
setOpend(false); setOpend(false)
setIsType(''); setIsType('')
setExpandContent(''); setExpandContent('')
setTopicList([]); setTopicList([])
setGalleryIndex(-1); setGalleryIndex(-1)
setNewChapterId(newChapterId); setNewChapterId(newChapterId)
setPreviewImg(''); setPreviewImg('')
}} }}>
>
<LeftOutlined /> <LeftOutlined />
</Button> </Button>
{secondType ? secondType : headTitle} {secondType ? secondType : headTitle}
</Space> </Space>
) : ( ) : (
<> <>
<span className='no'>{oldTitle}</span> <span className="no">{oldTitle}</span>
<span className='menu'> <span className="menu">
<BarsOutlined style={{ fontSize: 22 }} onClick={() => setOpen(true)} /> <BarsOutlined style={{ fontSize: 22 }} onClick={() => setOpen(true)} />
</span> </span>
</> </>
)} )}
</h2> </h2>
</div> </div>
<div className='preview-content-it'> <div className="preview-content-it">
<div className='preview-content-show'> <div className="preview-content-show">
<Spin spinning={loading} wrapperClassName='chapter-loading'> <Spin spinning={loading} wrapperClassName="chapter-loading">
<div <div className="preview-content-html" dangerouslySetInnerHTML={{ __html: prviewHtml }}></div>
className='preview-content-html'
dangerouslySetInnerHTML={{ __html: prviewHtml }}
></div>
</Spin> </Spin>
</div> </div>
{isType && ( {isType && (
<div className='preview-content-other'> <div className="preview-content-other">
{isType === 'gallery' && ( {isType === 'gallery' && (
<div className='gallery-prview-container'> <div className="gallery-prview-container">
{gallery && gallery.length > 0 ? ( {gallery && gallery.length > 0 ? (
<> <>
<div className='gallery-img'> <div className="gallery-img">
<img <img src={gallery[parseInt(galleryIndex)].url} alt={gallery[parseInt(galleryIndex)].title} />
src={gallery[parseInt(galleryIndex)].url} <div className="opa prev" onClick={galleryLeft}></div>
alt={gallery[parseInt(galleryIndex)].title} <div className="opa next" onClick={galleryRight}></div>
/>
<div className='opa prev' onClick={galleryLeft}></div>
<div className='opa next' onClick={galleryRight}></div>
</div> </div>
<div className='steps'> <div className="steps">
当前 {parseInt(galleryIndex) + 1}/{gallery.length} 当前 {parseInt(galleryIndex) + 1}/{gallery.length}
</div> </div>
<div className='title'>{gallery[parseInt(galleryIndex)].title}</div> <div className="title">{gallery[parseInt(galleryIndex)].title}</div>
<div className='desc'>{gallery[parseInt(galleryIndex)].desc}</div> <div className="desc">{gallery[parseInt(galleryIndex)].desc}</div>
</> </>
) : ( ) : (
<> <>
<div className='gallery-img noData'>画廊数据异常</div> <div className="gallery-img noData">画廊数据异常</div>
</> </>
)} )}
</div> </div>
)} )}
{isType === 'practice' && ( {isType === 'practice' && (
<div className='practice-insert-topic'> <div className="practice-insert-topic">
{radioList.length > 0 && ( {radioList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('radio')}. 单选题</h3> <h3>{clacTopicText('radio')}. 单选题</h3>
<div className='practice-list'> <div className="practice-list">
{radioList.map((item, index) => { {radioList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{checkBoxList.length > 0 && ( {checkBoxList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('checkbox', radioList)}. 多选题</h3> <h3>{clacTopicText('checkbox', radioList)}. 多选题</h3>
<div className='practice-list'> <div className="practice-list">
{checkBoxList.map((item, index) => { {checkBoxList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{judgeList.length > 0 && ( {judgeList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3> <h3>{clacTopicText('judge', radioList, checkBoxList)}. 判断题</h3>
<div className='practice-list'> <div className="practice-list">
{judgeList.map((item, index) => { {judgeList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{fillList.length > 0 && ( {fillList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3> <h3>{clacTopicText('fill', radioList, checkBoxList, judgeList)}. 填空题</h3>
<div className='practice-list'> <div className="practice-list">
{fillList.map((item, index) => { {fillList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`, __html: `<span class="correct">${correctList[cindex]}.</span> ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
)} )}
{textareaList.length > 0 && ( {textareaList.length > 0 && (
<div className='topic_style'> <div className="topic_style">
<h3> <h3>{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. 简答题</h3>
{clacTopicText('textarea', radioList, checkBoxList, judgeList, fillList)}. <div className="practice-list">
简答题
</h3>
<div className='practice-list'>
{textareaList.map((item, index) => { {textareaList.map((item, index) => {
return ( return (
<div className='practice-item' key={index}> <div className="practice-item" key={index}>
<div <div
className='topic-choose-title' className="topic-choose-title"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<span class="index">${index + 1}.</span>${item.titles}`, __html: `<span class="index">${index + 1}.</span>${item.titles}`
}} }}></div>
></div>
<div className='topic_choose-list'> <div className="topic_choose-list">
{[1, 2, 3].includes(parseInt(item.question_style)) && {[1, 2, 3].includes(parseInt(item.question_style)) &&
item.question_list.map((citem, cindex) => { item.question_list.map((citem, cindex) => {
return ( return (
<div className='topic_choose-item' key={cindex}> <div className="topic_choose-item" key={cindex}>
<div className='choose-ico'> <div className="choose-ico">
<i <i className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}></i>
className={`ico ${item.question_style === 2 ? 'checkbox' : 'radio'}`}
></i>
</div> </div>
<div <div
className='topic_content' className="topic_content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `${correctList[cindex]}. ${citem.option}`, __html: `${correctList[cindex]}. ${citem.option}`
}} }}></div>
></div>
</div> </div>
); )
})} })}
{item.question_style === 5 && ( {item.question_style === 5 && (
<div> <div>
<Input.TextArea <Input.TextArea disabled={true} autoSize={{ minRows: 4, maxRows: 6 }} />
disabled={true}
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</div> </div>
)} )}
</div> </div>
</div> </div>
); )
})} })}
</div> </div>
</div> </div>
...@@ -790,33 +738,31 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -790,33 +738,31 @@ const PreviewScreen = forwardRef((props, ref) => {
</div> </div>
)} )}
{isType === 'expand' && ( {isType === 'expand' && (
<div className='expand-container'> <div className="expand-container">
<div <div className="expand-content" dangerouslySetInnerHTML={{ __html: expandContent }}></div>
className='expand-content'
dangerouslySetInnerHTML={{ __html: expandContent }}
></div>
</div> </div>
)} )}
{isType === 'img' && ( {isType === 'img' && (
<div className='img-preview'> <div className="img-preview">
<Image width={430} src={previewImg} /> <Image width={430} src={previewImg} />
</div> </div>
)} )}
</div> </div>
)} )}
<div className='tooltip' style={toolTip.style}> <div className="tooltip" style={toolTip.style}>
<div <div
className={`square ${toolTip.inSide === 'top' ? 'square_top' : toolTip.inSide === 'bottom' ? 'square_bottom' : ''}`} className={`square ${
style={toolTip.squareStyle} toolTip.inSide === 'top' ? 'square_top' : toolTip.inSide === 'bottom' ? 'square_bottom' : ''
></div> }`}
<div className='tooltip-content-container'> style={toolTip.squareStyle}></div>
<div className='tooltip-content'> <div className="tooltip-content-container">
<div className='content'> <div className="tooltip-content">
<div className="content">
<p>{toolTip.content}</p> <p>{toolTip.content}</p>
</div> </div>
{toolTip.link && ( {toolTip.link && (
<div className='content-opa'> <div className="content-opa">
<a href={toolTip.link} target='_blank' rel='noreferrer' className='c-link'></a> <a href={toolTip.link} target="_blank" rel="noreferrer" className="c-link"></a>
{/* <a {/* <a
href={`https://baike.baidu.com/item/${toolTip?.title}`} href={`https://baike.baidu.com/item/${toolTip?.title}`}
target='_blank' target='_blank'
...@@ -836,14 +782,13 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -836,14 +782,13 @@ const PreviewScreen = forwardRef((props, ref) => {
onClose={onClose} onClose={onClose}
open={open} open={open}
getContainer={false} getContainer={false}
placement='left' placement="left"
classNames={{ header: 'priview-drawer-header', body: 'priview-drawer-body' }} classNames={{ header: 'priview-drawer-header', body: 'priview-drawer-body' }}
width='300' width="300"
title='章节列表' title="章节列表"
rootClassName='priview-drawer-container' rootClassName="priview-drawer-container">
>
<Tree <Tree
className='draggable-tree' className="draggable-tree"
onSelect={handleSelect} onSelect={handleSelect}
defaultExpandedKeys={expandedKeys} defaultExpandedKeys={expandedKeys}
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
...@@ -854,7 +799,7 @@ const PreviewScreen = forwardRef((props, ref) => { ...@@ -854,7 +799,7 @@ const PreviewScreen = forwardRef((props, ref) => {
</Drawer> </Drawer>
{/* </Spin> */} {/* </Spin> */}
</div> </div>
); )
}); }
export default PreviewScreen; export default forwardRef(PreviewScreen)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Form, Space, Input, Select, Button, Spin, Row, Col, Checkbox, Radio } from 'antd'; import { Form, Space, Input, Select, Button, Spin, Row, Col, Checkbox, Radio } from 'antd'
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux'
import { Editor, Toolbar } from '@wangeditor/editor-for-react'; import { Editor, Toolbar } from '@wangeditor/editor-for-react'
import { DomEditor } from '@wangeditor/editor'; import { DomEditor } from '@wangeditor/editor'
import { import { questionAdd, typeList, questionAddType, questionEdit, bookNameList } from '@/pages/books/question-bank/request'
questionAdd, import { uploadFiles } from '@/utils/upload'
typeList, import QuestionEditr from '@/pages/books/question-bank/questionEditr'
questionAddType, import './index.less'
questionEdit, import dayjs from 'dayjs'
bookNameList, import AliOSS from 'ali-oss'
} from '@/pages/books/question-bank/request'; import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet'
import { uploadFiles } from '@/utils/upload';
import QuestionEditr from '@/pages/books/question-bank/questionEditr'; const CustomerTopic = (props, ref) => {
import './index.less'; const { topicData, isadd, init, getTypeList, typeDate, setShowModal, bookNameData, bookIdList, typeId } = props
import dayjs from 'dayjs';
import AliOSS from 'ali-oss';
import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet';
const CustomerTopic = forwardRef((props, ref) => {
const {
topicData,
isadd,
init,
getTypeList,
typeDate,
setShowModal,
bookNameData,
bookIdList,
typeId,
} = props;
// oss // oss
const [ossClient, setOssClient] = useState(null); // oss 操作 const [ossClient, setOssClient] = useState(null) // oss 操作
const [STSToken, setSTSToken] = useState(null); // oss 过期设置 const [STSToken, setSTSToken] = useState(null) // oss 过期设置
let ossClientTemp; let ossClientTemp
const getStsAuthToken = async () => { const getStsAuthToken = async () => {
const data = await getAliOSSSTSToken(); const data = await getAliOSSSTSToken()
if (data) { if (data) {
window.sessionStorage.setItem('sts', JSON.stringify(data)); window.sessionStorage.setItem('sts', JSON.stringify(data))
setSTSToken(data); setSTSToken(data)
ossClientTemp = await new AliOSS({ ossClientTemp = await new AliOSS({
accessKeyId: data.AccessKeyId, accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret, accessKeySecret: data.AccessKeySecret,
...@@ -50,36 +34,36 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -50,36 +34,36 @@ const CustomerTopic = forwardRef((props, ref) => {
timeout: 180000, timeout: 180000,
refreshSTSToken: async () => { refreshSTSToken: async () => {
const info = await getAliOSSSTSToken(); const info = await getAliOSSSTSToken()
return { return {
AccessKeyId: info.AccessKeyId, AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret, AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken, SecurityToken: info.SecurityToken
}; }
}, },
refreshSTSTokenInterval: 14 * 60 * 1000, refreshSTSTokenInterval: 14 * 60 * 1000
}); })
setOssClient(ossClientTemp); setOssClient(ossClientTemp)
}
} }
};
useEffect(() => { useEffect(() => {
(async () => { ;(async () => {
await getStsAuthToken(); await getStsAuthToken()
})(); })()
}, []); }, [])
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return {}; return {}
}); })
const [form] = Form.useForm(); const [form] = Form.useForm()
const questionType = Form.useWatch('question_style', form); const questionType = Form.useWatch('question_style', form)
// 获取操作权限 // 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user); const { operationPermissionsList } = useSelector(state => state.user)
// 题干名称的编辑器实例 // 题干名称的编辑器实例
const [titlesEditor, setTitlesEditor] = useState(null); const [titlesEditor, setTitlesEditor] = useState(null)
const [quesList, setQuesList] = useState([]); const [quesList, setQuesList] = useState([])
const [initialValues, setinitialValues] = useState({ const [initialValues, setinitialValues] = useState({
titles: '', titles: '',
type_id: null, type_id: null,
...@@ -87,23 +71,23 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -87,23 +71,23 @@ const CustomerTopic = forwardRef((props, ref) => {
analysis: '', analysis: '',
answers: '', answers: '',
question_list: [], question_list: [],
book_id: '', book_id: ''
}); })
const [selectedTypeId, setSelectedTypeId] = useState([]); const [selectedTypeId, setSelectedTypeId] = useState([])
useEffect(() => { useEffect(() => {
// console.log('typeId', typeId); //书的typeid // console.log('typeId', typeId); //书的typeid
// console.log('props.typeDate', props.typeDate); //所有的typeid和typename // console.log('props.typeDate', props.typeDate); //所有的typeid和typename
const getTypeNameById = (id) => { const getTypeNameById = id => {
const selectedType = props.typeDate.find((item) => item.id === id); const selectedType = props.typeDate.find(item => item.id === id)
return selectedType ? selectedType.typename : ''; return selectedType ? selectedType.typename : ''
}; }
const matchedTypename = getTypeNameById(typeId); const matchedTypename = getTypeNameById(typeId)
setSelectedTypeId(matchedTypename); setSelectedTypeId(matchedTypename)
}, [props.typeDate, typeId]); }, [props.typeDate, typeId])
useEffect(() => { useEffect(() => {
let obj = { let obj = {
...@@ -113,71 +97,71 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -113,71 +97,71 @@ const CustomerTopic = forwardRef((props, ref) => {
analysis: '', analysis: '',
answers: '', answers: '',
question_list: [], question_list: [],
book_id: '', book_id: ''
}; }
if (!isadd && Object.entries(topicData)) { if (!isadd && Object.entries(topicData)) {
obj = { obj = {
...topicData, ...topicData
}; }
setQuestionStyle(obj.question_style); setQuestionStyle(obj.question_style)
if (topicData.question_style === 4 || topicData.question_style === 5) { if (topicData.question_style === 4 || topicData.question_style === 5) {
setedierVal(topicData.answers); setedierVal(topicData.answers)
setQuesList([]); setQuesList([])
} else { } else {
if (topicData.question_list && topicData.question_list.length) { if (topicData.question_list && topicData.question_list.length) {
try { try {
obj.question_list = JSON.parse(topicData.question_list); obj.question_list = JSON.parse(topicData.question_list)
setQuesList(JSON.parse(topicData.question_list)); setQuesList(JSON.parse(topicData.question_list))
} catch (e) { } catch (e) {
obj.question_list = []; obj.question_list = []
setQuesList([]); setQuesList([])
} }
} else { } else {
obj.question_list = []; obj.question_list = []
setQuesList([]); setQuesList([])
} }
} }
setinitialValues({ ...obj }); setinitialValues({ ...obj })
form.setFieldsValue({ ...obj }); form.setFieldsValue({ ...obj })
} else { } else {
setinitialValues(obj); setinitialValues(obj)
form.setFieldsValue({ ...obj }); form.setFieldsValue({ ...obj })
} }
}, [topicData, isadd]); }, [topicData, isadd])
// 显示不同类型的选项函数 // 显示不同类型的选项函数
const [edierVal, setedierVal] = useState(''); const [edierVal, setedierVal] = useState('')
// 是否显示选项 // 是否显示选项
const [showList, setShowList] = useState(false); const [showList, setShowList] = useState(false)
const [formLoading, setFormLoading] = useState(false); const [formLoading, setFormLoading] = useState(false)
const [showAddClass, setShowAddClass] = useState(false); const [showAddClass, setShowAddClass] = useState(false)
const [addClassVal, setaddClassVal] = useState(''); // 添加分类 const [addClassVal, setaddClassVal] = useState('') // 添加分类
const [questionStyle, setQuestionStyle] = useState(''); const [questionStyle, setQuestionStyle] = useState('')
// 分类 // 分类
const sureFn = async () => { const sureFn = async () => {
const bool = await questionAddType({ typename: addClassVal }); const bool = await questionAddType({ typename: addClassVal })
if (bool) { if (bool) {
await getTypeList(); await getTypeList()
form.setFieldsValue({ type_id: bool.type_id }); form.setFieldsValue({ type_id: bool.type_id })
setinitialValues({ ...initialValues, type_id: [bool.type_id] }); setinitialValues({ ...initialValues, type_id: [bool.type_id] })
setaddClassVal(''); setaddClassVal('')
setShowAddClass(false); setShowAddClass(false)
}
} }
};
// 工具栏配置 // 工具栏配置
const toolbarConfig = {}; const toolbarConfig = {}
toolbarConfig.toolbarKeys = ['uploadImage']; toolbarConfig.toolbarKeys = ['uploadImage']
// 编辑器配置 // 编辑器配置
const editorConfig = { const editorConfig = {
// JS 语法 // JS 语法
placeholder: '请输入内容...', placeholder: '请输入内容...',
hoverbarKeys: { hoverbarKeys: {
text: { text: {
menuKeys: [], menuKeys: []
}, }
}, },
MENU_CONF: { MENU_CONF: {
// 配置默认字号 // 配置默认字号
...@@ -188,156 +172,145 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -188,156 +172,145 @@ const CustomerTopic = forwardRef((props, ref) => {
fieldName: 'image', fieldName: 'image',
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token'), Authorization: 'Bearer ' + localStorage.getItem('token')
}, },
maxFileSize: 10 * 1024 * 1024, // 10M maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 base64LimitSize: 5 * 1024, // 5kb 以下插入 base64
customUpload: async (file, insertFn) => { customUpload: async (file, insertFn) => {
if (!ossClient) { if (!ossClient) {
console.error('ossClient还未初始化', ossClient); console.error('ossClient还未初始化', ossClient)
return false; return false
} }
const fileExt = file.name.substring(file.name.lastIndexOf('.')); const fileExt = file.name.substring(file.name.lastIndexOf('.'))
const fileName = `ad-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`; const fileName = `ad-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`; const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`
const result = await ossClient.put(filePath, file); const result = await ossClient.put(filePath, file)
console.log('result', result); console.log('result', result)
insertFn(result.url, '题库图片'); insertFn(result.url, '题库图片')
// const { url } = await uploadFiles({ file, file_type: 'question' }); // const { url } = await uploadFiles({ file, file_type: 'question' });
// insertFn(url, '题库图片'); // insertFn(url, '题库图片');
}, }
}, }
}, },
customPaste: (editor, event) => { customPaste: (editor, event) => {
// const html = event.clipboardData.getData('text/html') // 获取粘贴的 html // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
const text = event.clipboardData.getData('text/plain'); // 获取粘贴的纯文本 const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴) // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
// 异步 // 异步
setTimeout(() => { setTimeout(() => {
editor.insertText(text); editor.insertText(text)
}, 500); }, 500)
// 阻止默认的粘贴行为 // 阻止默认的粘贴行为
event.preventDefault(); event.preventDefault()
return false; return false
}, }
}; }
// 及时销毁 editor ,重要! // 及时销毁 editor ,重要!
useEffect(() => { useEffect(() => {
if (titlesEditor !== null) { if (titlesEditor !== null) {
const toolbar = DomEditor.getToolbar(titlesEditor); const toolbar = DomEditor.getToolbar(titlesEditor)
} }
return () => { return () => {
if (titlesEditor === null) return; if (titlesEditor === null) return
titlesEditor.destroy(); titlesEditor.destroy()
setTitlesEditor(null); setTitlesEditor(null)
}; }
}, [titlesEditor]); }, [titlesEditor])
const submitForm = async (obj) => { const submitForm = async obj => {
let ilen = 0; let ilen = 0
let obj2 = { ...obj }; let obj2 = { ...obj }
if ([1, 2, 3].includes(parseInt(obj.question_style))) { if ([1, 2, 3].includes(parseInt(obj.question_style))) {
obj.question_list.forEach((item, index) => { obj.question_list.forEach((item, index) => {
if (item.correct && item.correct === true) { if (item.correct && item.correct === true) {
ilen++; ilen++
} }
}); })
if ([1, 3].includes(parseInt(obj.question_style))) { if ([1, 3].includes(parseInt(obj.question_style))) {
if (ilen > 1 || ilen === 0) { if (ilen > 1 || ilen === 0) {
form.setFields([ form.setFields([
{ {
name: ['question_list', obj.question_list.length - 1, 'correct'], name: ['question_list', obj.question_list.length - 1, 'correct'],
errors: [ errors: [`${parseInt(obj.question_style) === 3 ? '判断题' : '单选题'}有且仅有一个正确答案!`]
`${parseInt(obj.question_style) === 3 ? '判断题' : '单选题'}有且仅有一个正确答案!`, }
], ])
}, return false
]);
return false;
} else { } else {
form.setFields([ form.setFields([{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] }])
{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] },
]);
} }
} else { } else {
if (ilen <= 1) { if (ilen <= 1) {
form.setFields([ form.setFields([
{ {
name: ['question_list', obj.question_list.length - 1, 'correct'], name: ['question_list', obj.question_list.length - 1, 'correct'],
errors: ['多选题需要2个及以上正确答案!'], errors: ['多选题需要2个及以上正确答案!']
}, }
]); ])
return false; return false
} else { } else {
form.setFields([ form.setFields([{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] }])
{ name: ['question_list', obj.question_list.length - 1, 'correct'], errors: [''] },
]);
} }
} }
obj2['question_list'] = JSON.stringify(quesList); obj2['question_list'] = JSON.stringify(quesList)
} else { } else {
obj2['answers'] = edierVal; obj2['answers'] = edierVal
} }
setShowAddClass(true); setShowAddClass(true)
let bool = null; let bool = null
if (isadd) { if (isadd) {
bool = await questionAdd({ bool = await questionAdd({
...obj2, ...obj2
}); })
} else { } else {
bool = await questionEdit({ bool = await questionEdit({
...obj2, ...obj2,
id: topicData.id, id: topicData.id
}); })
} }
setShowAddClass(false); setShowAddClass(false)
if (!bool) return; if (!bool) return
setShowModal(false); setShowModal(false)
init(); init()
}; }
// 校验 // 校验
const vaildaterHtml = (_, value) => { const vaildaterHtml = (_, value) => {
if (value === '<p><br></p>') { if (value === '<p><br></p>') {
return Promise.reject('问题内容不能为空'); return Promise.reject('问题内容不能为空')
} else if (!value.trim()) { } else if (!value.trim()) {
return Promise.reject(new Error('请输入正确的内容')); return Promise.reject(new Error('请输入正确的内容'))
} else { } else {
return Promise.resolve(); return Promise.resolve()
}
} }
};
return ( return (
<div className='practice_customer'> <div className="practice_customer">
<Form <Form
form={form} form={form}
initialValues={initialValues} initialValues={initialValues}
onFinish={submitForm} onFinish={submitForm}
labelCol={{ span: 5 }} labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }} wrapperCol={{ span: 19 }}>
> <Form.Item name="book_id" label="书籍名称" rules={[{ required: true, message: '请选择书籍名称' }]}>
<Form.Item
name='book_id'
label='书籍名称'
rules={[{ required: true, message: '请选择书籍名称' }]}
>
<Select <Select
onChange={(ev) => { onChange={ev => {
setShowList(true); setShowList(true)
}} }}
style={{ width: 260 }} style={{ width: 260 }}
placeholder='请选择书籍名称' placeholder="请选择书籍名称"
showSearch //下拉框出现搜素,并可以输入 showSearch //下拉框出现搜素,并可以输入
optionFilterProp='children' // 使搜索匹配子节点的文本内容 optionFilterProp="children" // 使搜索匹配子节点的文本内容
> >
{bookIdList && {bookIdList &&
bookIdList.length && bookIdList.length &&
...@@ -348,21 +321,16 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -348,21 +321,16 @@ const CustomerTopic = forwardRef((props, ref) => {
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item name="question_style" label="题目类型" rules={[{ required: true, message: '请选择题目类型' }]}>
name='question_style'
label='题目类型'
rules={[{ required: true, message: '请选择题目类型' }]}
>
<Select <Select
onChange={(ev) => { onChange={ev => {
setShowList(true); setShowList(true)
// setinitialValues({ ...initialValues, question_style: ev }); // setinitialValues({ ...initialValues, question_style: ev });
// form.setFieldValue('question_style', ev); // form.setFieldValue('question_style', ev);
setQuestionStyle(ev); setQuestionStyle(ev)
}} }}
style={{ width: 260 }} style={{ width: 260 }}
placeholder='请选择题目类型' placeholder="请选择题目类型">
>
<Select.Option value={1}>单选题</Select.Option> <Select.Option value={1}>单选题</Select.Option>
<Select.Option value={2}>多选题</Select.Option> <Select.Option value={2}>多选题</Select.Option>
<Select.Option value={3}>判断题</Select.Option> <Select.Option value={3}>判断题</Select.Option>
...@@ -370,26 +338,21 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -370,26 +338,21 @@ const CustomerTopic = forwardRef((props, ref) => {
<Select.Option value={5}>简答题</Select.Option> <Select.Option value={5}>简答题</Select.Option>
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item label="题目分类" name="type_id" rules={[{ required: true, message: '请选择题目分类' }]}>
label='题目分类'
name='type_id'
rules={[{ required: true, message: '请选择题目分类' }]}
>
{!showAddClass ? ( {!showAddClass ? (
<> <>
<Select <Select
onChange={(ev) => { onChange={ev => {
form.setFieldValue('type_id', ev); form.setFieldValue('type_id', ev)
setSelectedTypeId(ev); setSelectedTypeId(ev)
}} }}
style={{ width: 220 }} style={{ width: 220 }}
placeholder='请选择题目分类' placeholder="请选择题目分类"
value={selectedTypeId} value={selectedTypeId}>
>
{typeDate && {typeDate &&
typeDate.length && typeDate.length &&
typeDate.map((item) => ( typeDate.map(item => (
<Select.Option key={item.id} value={item.id}> <Select.Option key={item.id} value={item.id}>
{item.typename} {item.typename}
</Select.Option> </Select.Option>
...@@ -397,12 +360,11 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -397,12 +360,11 @@ const CustomerTopic = forwardRef((props, ref) => {
</Select> </Select>
<Button <Button
onClick={() => { onClick={() => {
setShowAddClass(true); setShowAddClass(true)
form.setFieldsValue({ type_id: '' }); form.setFieldsValue({ type_id: '' })
}} }}
type='link' type="link"
style={{ textDecoration: 'underline', color: '#1672EC' }} style={{ textDecoration: 'underline', color: '#1672EC' }}>
>
添加分类 添加分类
</Button> </Button>
</> </>
...@@ -411,23 +373,17 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -411,23 +373,17 @@ const CustomerTopic = forwardRef((props, ref) => {
<Input <Input
style={{ width: 200 }} style={{ width: 200 }}
value={addClassVal} value={addClassVal}
onChange={(e) => setaddClassVal(e.target.value)} onChange={e => setaddClassVal(e.target.value)}
autoComplete='off' autoComplete="off"
placeholder='请输入题目分类' placeholder="请输入题目分类"></Input>
></Input>
<Space> <Space>
<Button <Button onClick={sureFn} type="link" style={{ textDecoration: 'underline', color: '#1672EC' }}>
onClick={sureFn}
type='link'
style={{ textDecoration: 'underline', color: '#1672EC' }}
>
添加 添加
</Button> </Button>
<Button <Button
type='link' type="link"
onClick={() => setShowAddClass(false)} onClick={() => setShowAddClass(false)}
style={{ textDecoration: 'underline', color: '#AA1941', marginLeft: -30 }} style={{ textDecoration: 'underline', color: '#AA1941', marginLeft: -30 }}>
>
取消 取消
</Button> </Button>
</Space> </Space>
...@@ -435,20 +391,19 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -435,20 +391,19 @@ const CustomerTopic = forwardRef((props, ref) => {
)} )}
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name='titles' name="titles"
label='题干名称' label="题干名称"
rules={[ rules={[
{ required: true, message: '请输入题干名称' }, { required: true, message: '请输入题干名称' },
{ validator: vaildaterHtml, validateTrigger: 'onChange' }, { validator: vaildaterHtml, validateTrigger: 'onChange' }
]} ]}
extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''} extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''}>
>
<Spin spinning={formLoading}> <Spin spinning={formLoading}>
<div style={{ border: '1px solid #ccc', zIndex: 100 }}> <div style={{ border: '1px solid #ccc', zIndex: 100 }}>
<Toolbar <Toolbar
editor={titlesEditor} editor={titlesEditor}
defaultConfig={toolbarConfig} defaultConfig={toolbarConfig}
mode='default' mode="default"
style={{ borderBottom: '1px solid #ccc' }} style={{ borderBottom: '1px solid #ccc' }}
/> />
{ossClient && ( {ossClient && (
...@@ -456,40 +411,40 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -456,40 +411,40 @@ const CustomerTopic = forwardRef((props, ref) => {
defaultConfig={editorConfig} defaultConfig={editorConfig}
value={initialValues.titles} value={initialValues.titles}
onCreated={setTitlesEditor} onCreated={setTitlesEditor}
onChange={(editor) => { onChange={editor => {
form.setFieldValue('titles', editor.getHtml()); form.setFieldValue('titles', editor.getHtml())
// setHtml(editor.getHtml()) // setHtml(editor.getHtml())
}} }}
config={{ config={{
uploadImgServer: 'your_upload_server_address', uploadImgServer: 'your_upload_server_address'
// other config options // other config options
}} }}
mode='default' mode="default"
style={{ height: '200px', overflowY: 'hidden' }} style={{ height: '200px', overflowY: 'hidden' }}
/> />
)} )}
</div> </div>
</Spin> </Spin>
</Form.Item> </Form.Item>
<Form.Item name='analysis' label='题目解析'> <Form.Item name="analysis" label="题目解析">
<Input.TextArea <Input.TextArea
placeholder='请输入题目解析' placeholder="请输入题目解析"
autoSize={{ autoSize={{
minRows: 5, minRows: 5,
maxRows: 8, maxRows: 8
}} }}
name='analysis' name="analysis"
/> />
</Form.Item> </Form.Item>
{(questionStyle === 1 || questionStyle === 2 || questionStyle === 3) && ( {(questionStyle === 1 || questionStyle === 2 || questionStyle === 3) && (
<Form.List name='question_list'> <Form.List name="question_list">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<Form.Item label='题目选项'> <Form.Item label="题目选项">
{fields.map(({ key, name, ...restField }, index) => ( {fields.map(({ key, name, ...restField }, index) => (
<Row gutter={4} key={key}> <Row gutter={4} key={key}>
<Col span={14} className='form_inside-out'> <Col span={14} className="form_inside-out">
<Form.Item className='inside-it'> <Form.Item className="inside-it">
<QuestionEditr <QuestionEditr
editorValue={quesList && quesList[index] && quesList[index].option} editorValue={quesList && quesList[index] && quesList[index].option}
quesList={quesList} quesList={quesList}
...@@ -507,18 +462,17 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -507,18 +462,17 @@ const CustomerTopic = forwardRef((props, ref) => {
validator: (_, value) => { validator: (_, value) => {
if (value !== '') { if (value !== '') {
if (value === '<p><br></p>') { if (value === '<p><br></p>') {
return Promise.reject(new Error('请输入正确的内容')); return Promise.reject(new Error('请输入正确的内容'))
} else { } else {
return Promise.resolve(); return Promise.resolve()
} }
} else { } else {
return Promise.reject(new Error('')); return Promise.reject(new Error(''))
}
}
} }
},
},
]} ]}
className='form_inside-out-none' className="form_inside-out-none">
>
<Input.TextArea /> <Input.TextArea />
</Form.Item> </Form.Item>
</Col> </Col>
...@@ -527,28 +481,26 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -527,28 +481,26 @@ const CustomerTopic = forwardRef((props, ref) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'correct']} name={[name, 'correct']}
valuePropName='checked' valuePropName="checked"
initialValue={restField.correct || false} initialValue={restField.correct || false}>
>
<Checkbox <Checkbox
onChange={(e) => { onChange={e => {
// if (quesList.length && temp[index]) { // if (quesList.length && temp[index]) {
if (quesList.length) { if (quesList.length) {
let temp = JSON.parse(JSON.stringify(quesList)); let temp = JSON.parse(JSON.stringify(quesList))
if (questionStyle === 1 || questionStyle === 3) { if (questionStyle === 1 || questionStyle === 3) {
if (e.target.checked) { if (e.target.checked) {
temp.forEach((item) => { temp.forEach(item => {
item.correct = false; item.correct = false
}); })
} }
} }
temp[index].correct = e.target.checked; temp[index].correct = e.target.checked
setQuesList(temp); setQuesList(temp)
form.setFieldValue('question_list', temp); form.setFieldValue('question_list', temp)
} }
}} }}>
>
正确答案 正确答案
</Checkbox> </Checkbox>
</Form.Item> </Form.Item>
...@@ -556,45 +508,42 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -556,45 +508,42 @@ const CustomerTopic = forwardRef((props, ref) => {
<Col span={3}> <Col span={3}>
<Button <Button
onClick={async () => { onClick={async () => {
let temp = JSON.parse(JSON.stringify(quesList)); let temp = JSON.parse(JSON.stringify(quesList))
temp.splice(index, 1); temp.splice(index, 1)
setQuesList(temp); setQuesList(temp)
await remove(name); await remove(name)
}} }}
icon={<MinusOutlined />} icon={<MinusOutlined />}></Button>
></Button>
</Col> </Col>
</Row> </Row>
))} ))}
{quesList.length < 2 && questionStyle === 3 && ( {quesList.length < 2 && questionStyle === 3 && (
<Form.Item> <Form.Item>
<Button <Button
type='dashed' type="dashed"
onClick={async () => { onClick={async () => {
let tempQuestion = JSON.parse(JSON.stringify(quesList)); let tempQuestion = JSON.parse(JSON.stringify(quesList))
tempQuestion.push({ option: '', correct: false }); tempQuestion.push({ option: '', correct: false })
setQuesList(tempQuestion); setQuesList(tempQuestion)
await add(); await add()
}} }}
icon={<PlusOutlined />} icon={<PlusOutlined />}></Button>
></Button>
</Form.Item> </Form.Item>
)} )}
{[1, 2].includes(questionStyle) && ( {[1, 2].includes(questionStyle) && (
<Form.Item> <Form.Item>
<Button <Button
type='dashed' type="dashed"
onClick={async () => { onClick={async () => {
let tempQuestion = JSON.parse(JSON.stringify(quesList)); let tempQuestion = JSON.parse(JSON.stringify(quesList))
tempQuestion.push({ option: '', correct: false }); tempQuestion.push({ option: '', correct: false })
setQuesList(tempQuestion); setQuesList(tempQuestion)
await add(); await add()
}} }}
icon={<PlusOutlined />} icon={<PlusOutlined />}></Button>
></Button>
</Form.Item> </Form.Item>
)} )}
</Form.Item> </Form.Item>
...@@ -625,28 +574,23 @@ const CustomerTopic = forwardRef((props, ref) => { ...@@ -625,28 +574,23 @@ const CustomerTopic = forwardRef((props, ref) => {
</Form.Item> </Form.Item>
)} */} )} */}
{(questionStyle === 5 || questionStyle === 4) && ( {(questionStyle === 5 || questionStyle === 4) && (
<Form.Item name='answers' label='正确答案'> <Form.Item name="answers" label="正确答案">
<QuestionEditr <QuestionEditr editorValue={edierVal} setedierVal={setedierVal} form={form} name="answers" />
editorValue={edierVal}
setedierVal={setedierVal}
form={form}
name='answers'
/>
</Form.Item> </Form.Item>
)} )}
<Form.Item wrapperCol={{ offset: 11, span: 16 }}> <Form.Item wrapperCol={{ offset: 11, span: 16 }}>
<Space size={20}> <Space size={20}>
<Button className='cancel' onClick={() => setShowModal(false)}> <Button className="cancel" onClick={() => setShowModal(false)}>
取消 取消
</Button> </Button>
<Button className='submit' disabled={showAddClass} htmlType='submit'> <Button className="submit" disabled={showAddClass} htmlType="submit">
提交 提交
</Button> </Button>
</Space> </Space>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>
); )
}); }
export default CustomerTopic; export default forwardRef(CustomerTopic)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论