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

chore: update

上级 6737d2b7
...@@ -7053,6 +7053,7 @@ ...@@ -7053,6 +7053,7 @@
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz",
"integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.9", "@babel/runtime": "^7.23.9",
"@rc-component/portal": "^1.1.1", "@rc-component/portal": "^1.1.1",
...@@ -7326,6 +7327,7 @@ ...@@ -7326,6 +7327,7 @@
"version": "2.13.0", "version": "2.13.0",
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz", "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz",
"integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==", "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.10.1", "@babel/runtime": "^7.10.1",
"classnames": "^2.2.5", "classnames": "^2.2.5",
......
...@@ -53,28 +53,6 @@ dd { ...@@ -53,28 +53,6 @@ dd {
min-width: 475px; min-width: 475px;
} }
.submit {
background: #aa1941;
border-radius: 4px;
color: #ffffff;
font-size: 14px;
&:hover {
color: #ffffff !important;
background: #aa194283 !important;
}
}
// .cancel {
// background: #ffffff;
// border-radius: 4px;
// border: 1px solid #aa1941;
// font-size: 14px;
// color: #aa1941;
// &:hover {
// background: #ffffff7c !important;
// border-color: #aa194283 !important;
// color: #aa194283 !important;
// }
// }
.ant-input-number .ant-input-number-input { .ant-input-number .ant-input-number-input {
text-align: center; text-align: center;
} }
...@@ -84,9 +62,6 @@ dd { ...@@ -84,9 +62,6 @@ dd {
.ant-form-inline .ant-form-item { .ant-form-inline .ant-form-item {
margin-inline-end: 20px; margin-inline-end: 20px;
} }
// .inline,.ant-space-item{
// display: inline-block !important;
// }
.inline { .inline {
display: inline-block !important; display: inline-block !important;
} }
...@@ -110,31 +85,6 @@ dd { ...@@ -110,31 +85,6 @@ dd {
} }
} }
// @font-face {
// font-family: "思源黑体";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710838306427-vhs7ha8w5jj.ttf") format('truetype');
// }
// @font-face {
// font-family: "思源宋体";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710848430762-z2hb59oxz4h.ttf") format('truetype');
// }
// @font-face {
// font-family: "楷体";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710838338781-dxbppd4g6va.ttf") format('truetype');
// }
// @font-face {
// font-family: "仿宋";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710838378832-blsljc5hycd.ttf") format('truetype');
// }
// @font-face {
// font-family: "宋体";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710838324940-8vqbbw0lotx.ttf") format('truetype');
// }
// @font-face {
// font-family: "黑体";
// src: url("https://zxts-common-file.zijingebook.com/2024/03/19/video-1710838356409-40podr4vede.ttf") format('truetype');
// }
@font-face { @font-face {
font-family: '思源黑体'; font-family: '思源黑体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131326219-q886x58lgm.ttf') format('truetype'); src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131326219-q886x58lgm.ttf') format('truetype');
......
...@@ -20,3 +20,13 @@ export function aiGenerateImage(data) { ...@@ -20,3 +20,13 @@ export function aiGenerateImage(data) {
export function baiduAIChat(data) { export function baiduAIChat(data) {
return axios.post('/api/ai/baidubce/chat', data) return axios.post('/api/ai/baidubce/chat', data)
} }
// 题目分类自动添加(名称存在则返回数据,不存在则创建)
export function addType(data) {
return axios.post('/api/type/autoAdd', data)
}
// 创建试题
export function addQuestion(data) {
return axios.post('/api/question/add', data)
}
...@@ -153,7 +153,7 @@ const tabsMenu = [ ...@@ -153,7 +153,7 @@ const tabsMenu = [
storageChange() storageChange()
const WangEditorCustomer = (props, ref) => { const WangEditorCustomer = (props, ref) => {
const { chapterId, bookId, contentId, html, setHtml, saveContent, gData, nowTitle, disabled } = props const { chapterId, bookId, contentId, html, setHtml, saveContent, gData, nowTitle, disabled, isView = false } = props
const dispatch = useDispatch() const dispatch = useDispatch()
// 自动保存时间 // 自动保存时间
...@@ -444,6 +444,7 @@ const WangEditorCustomer = (props, ref) => { ...@@ -444,6 +444,7 @@ const WangEditorCustomer = (props, ref) => {
const toolSettingReplace = () => { const toolSettingReplace = () => {
setTimeout(() => { setTimeout(() => {
const editorToolbar = document.querySelector('.editor-toolbar-container') const editorToolbar = document.querySelector('.editor-toolbar-container')
if (!editorToolbar) return
// 设置菜单模块标题 // 设置菜单模块标题
const dividerElements = editorToolbar.querySelectorAll('.w-e-bar-divider') const dividerElements = editorToolbar.querySelectorAll('.w-e-bar-divider')
const dividerTitles = ['常用格式', '媒体资源', '高级模块', 'AI文本辅助', 'AI试题辅助', '更多AI功能'] const dividerTitles = ['常用格式', '媒体资源', '高级模块', 'AI文本辅助', 'AI试题辅助', '更多AI功能']
...@@ -638,7 +639,9 @@ const WangEditorCustomer = (props, ref) => { ...@@ -638,7 +639,9 @@ const WangEditorCustomer = (props, ref) => {
// 预览 // 预览
const previewIt = async () => { const previewIt = async () => {
await saveContent() if (!isView) {
await saveContent()
}
setPreviewVisible(true) setPreviewVisible(true)
} }
...@@ -677,33 +680,39 @@ const WangEditorCustomer = (props, ref) => { ...@@ -677,33 +680,39 @@ const WangEditorCustomer = (props, ref) => {
</div> </div>
<div className="right"> <div className="right">
<Space> <Space>
<div className="save-time"> {!isView && (
<div className="img"> <>
<img src={timesave} /> <span>自动保存</span> <div className="save-time">
</div> <div className="img">
<span className="time"> <img src={timesave} /> <span>自动保存</span>
{autosaveTime > 0 ? `上次保存发生在 ${dayjs(autosaveTime).format('YYYY-MM-DD HH:mm:ss')}` : ''} </div>
</span> <span className="time">
</div> {autosaveTime > 0 ? `上次保存发生在 ${dayjs(autosaveTime).format('YYYY-MM-DD HH:mm:ss')}` : ''}
<Button </span>
type="primary" </div>
icon={<SaveOutlined />} <Button
className="view" type="primary"
onClick={saveContent} icon={<SaveOutlined />}
style={{ color: '#fff' }} className="view"
disabled={disabled || !contentId}> onClick={saveContent}
保存 style={{ color: '#fff' }}
</Button> disabled={disabled || !contentId}>
保存
</Button>
</>
)}
<Button icon={<EyeOutlined />} className="history" onClick={previewIt} disabled={!contentId}> <Button icon={<EyeOutlined />} className="history" onClick={previewIt} disabled={!contentId}>
预览 预览
</Button> </Button>
<Button {!isView && (
icon={<HistoryOutlined />} <Button
className="history" icon={<HistoryOutlined />}
onClick={historyIt} className="history"
disabled={disabled || !contentId}> onClick={historyIt}
历史 disabled={disabled || !contentId}>
</Button> 历史
</Button>
)}
</Space> </Space>
</div> </div>
</div> </div>
...@@ -717,55 +726,56 @@ const WangEditorCustomer = (props, ref) => { ...@@ -717,55 +726,56 @@ const WangEditorCustomer = (props, ref) => {
style={{ height: 'calc(100vh - 250px)', overflowY: 'hidden' }} style={{ height: 'calc(100vh - 250px)', overflowY: 'hidden' }}
/> />
</div> </div>
{!isView && (
<div className="menu-tabs-key"> <div className="menu-tabs-key">
<div className="tabs"> <div className="tabs">
{tabsMenu && {tabsMenu &&
tabsMenu.length && tabsMenu.length &&
tabsMenu.map(item => { tabsMenu.map(item => {
return ( return (
<div <div
className={`tabs-item ${item.key === tabKey ? 'active' : ''}`} className={`tabs-item ${item.key === tabKey ? 'active' : ''}`}
key={item.key} key={item.key}
onClick={() => tabKeyChange(item.key)}> onClick={() => tabKeyChange(item.key)}>
{item.title} {item.title}
<span></span> <span></span>
</div> </div>
) )
})} })}
</div> </div>
<div className="menu-tabs-content"> <div className="menu-tabs-content">
{tabKey === 'text' && ( {tabKey === 'text' && (
<div ref={toolbarRef} className="toolbox-parent"> <div ref={toolbarRef} className="toolbox-parent">
<Toolbar <Toolbar
editor={editor} editor={editor}
defaultConfig={toolbarConfig} defaultConfig={toolbarConfig}
mode="default" mode="default"
className="editor-toolbar-container"></Toolbar> className="editor-toolbar-container"></Toolbar>
</div> </div>
)} )}
{tabKey === 'style' && ( {tabKey === 'style' && (
<div className="styletem"> <div className="styletem">
<p>样式模板</p> <p>样式模板</p>
<ul> <ul>
{colorList.map(item => { {colorList.map(item => {
return ( return (
<li key={item.color}> <li key={item.color}>
<div className="left"> <div className="left">
<span className="color" style={{ backgroundColor: item.color }}></span> <span className="color" style={{ backgroundColor: item.color }}></span>
<b className="type">{item.name}</b> <b className="type">{item.name}</b>
</div> </div>
<Button type="link" className="use" onClick={() => setColor(item.color)}> <Button type="link" className="use" onClick={() => setColor(item.color)}>
使用 使用
</Button> </Button>
</li> </li>
) )
})} })}
</ul> </ul>
</div> </div>
)} )}
</div>
</div> </div>
</div> )}
<Modal <Modal
open={imageVisible} open={imageVisible}
footer={null} footer={null}
......
...@@ -9,7 +9,7 @@ class AIContentInspect extends BaseModalMenu { ...@@ -9,7 +9,7 @@ class AIContentInspect extends BaseModalMenu {
this.iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M11.5 13.5q.525 0 .988-.137t.912-.413l1.525 1.575q.2.225.513.213t.537-.213q.225-.225.238-.537T16 13.45l-1.55-1.55q.275-.425.413-.9T15 10q0-1.475-1.038-2.488T11.5 6.5T9.037 7.513T8 10t1.038 2.488T11.5 13.5m0-1.5q-.825 0-1.412-.587T9.5 10t.588-1.412T11.5 8q.8 0 1.4.588T13.5 10t-.587 1.413T11.5 12M2 21q-.425 0-.712-.288T1 20t.288-.712T2 19h20q.425 0 .713.288T23 20t-.288.713T22 21zm2-3q-.825 0-1.412-.587T2 16V5q0-.825.588-1.412T4 3h16q.825 0 1.413.588T22 5v11q0 .825-.587 1.413T20 18zm0-2h16V5H4zm0 0V5z"/></svg>` this.iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M11.5 13.5q.525 0 .988-.137t.912-.413l1.525 1.575q.2.225.513.213t.537-.213q.225-.225.238-.537T16 13.45l-1.55-1.55q.275-.425.413-.9T15 10q0-1.475-1.038-2.488T11.5 6.5T9.037 7.513T8 10t1.038 2.488T11.5 13.5m0-1.5q-.825 0-1.412-.587T9.5 10t.588-1.412T11.5 8q.8 0 1.4.588T13.5 10t-.587 1.413T11.5 12M2 21q-.425 0-.712-.288T1 20t.288-.712T2 19h20q.425 0 .713.288T23 20t-.288.713T22 21zm2-3q-.825 0-1.412-.587T2 16V5q0-.825.588-1.412T4 3h16q.825 0 1.413.588T22 5v11q0 .825-.587 1.413T20 18zm0-2h16V5H4zm0 0V5z"/></svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="contentInspect"></AIModal> return <AIModal key={Date.now()} editor={editor} action="contentInspect"></AIModal>
} }
} }
......
...@@ -15,7 +15,7 @@ class AIExpand extends BaseModalMenu { ...@@ -15,7 +15,7 @@ class AIExpand extends BaseModalMenu {
</svg>` </svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="expand"></AIModal> return <AIModal key={Date.now()} editor={editor} action="expand"></AIModal>
} }
} }
......
...@@ -20,7 +20,7 @@ class AIPolishing extends BaseModalMenu { ...@@ -20,7 +20,7 @@ class AIPolishing extends BaseModalMenu {
</svg>` </svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="abbreviate"></AIModal> return <AIModal key={Date.now()} editor={editor} action="abbreviate"></AIModal>
} }
} }
......
...@@ -9,7 +9,7 @@ class AIPunctuation extends BaseModalMenu { ...@@ -9,7 +9,7 @@ class AIPunctuation extends BaseModalMenu {
this.iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1024 1024"><path fill="currentColor" d="M920 416H616c-4.4 0-8 3.6-8 8v112c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-56h60v320h-46c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h164c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8h-46V480h60v56c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V424c0-4.4-3.6-8-8-8M656 296V168c0-4.4-3.6-8-8-8H104c-4.4 0-8 3.6-8 8v128c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-64h168v560h-92c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h264c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-92V232h168v64c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8"/></svg>` this.iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1024 1024"><path fill="currentColor" d="M920 416H616c-4.4 0-8 3.6-8 8v112c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-56h60v320h-46c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h164c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8h-46V480h60v56c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V424c0-4.4-3.6-8-8-8M656 296V168c0-4.4-3.6-8-8-8H104c-4.4 0-8 3.6-8 8v128c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-64h168v560h-92c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h264c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-92V232h168v64c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8"/></svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="punctuation"></AIModal> return <AIModal key={Date.now()} editor={editor} action="punctuation"></AIModal>
} }
} }
......
// Extend menu import BaseModalMenu from './common/BaseModalMenu'
class AIQuestionJudge { import AIQuestionModal from './common/AIQuestionModal'
class AIQuestionJudge extends BaseModalMenu {
constructor() { constructor() {
super()
this.title = '判断题' this.title = '判断题'
this.iconSvg = `<svg t="1729144923785" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="713" width="200" height="200"><path d="M804.672 27.968H219.328A182.528 182.528 0 0 0 36.672 210.624v585.408a182.528 182.528 0 0 0 182.656 182.592h585.408a182.528 182.528 0 0 0 182.656-182.656V210.624A182.144 182.144 0 0 0 804.672 27.968z m110.08 768a109.952 109.952 0 0 1-110.08 110.08H219.328a109.952 109.952 0 0 1-110.08-110.08V210.624a109.952 109.952 0 0 1 110.08-110.08h585.408a109.952 109.952 0 0 1 110.08 110.08z m-172.096-573.632l-511.04 511.04-4.096 5.248a37.248 37.248 0 0 0 4.096 46.848 36.736 36.736 0 0 0 51.2 0l511.04-511.04 4.096-5.248a37.248 37.248 0 0 0-4.096-46.848 35.712 35.712 0 0 0-51.2 0z m-4.672 468.288l56.192-56.192 4.096-4.672a30.336 30.336 0 0 0-46.848-38.08l-56.192 56.192-56.192-56.192-4.672-4.096a30.336 30.336 0 0 0-38.08 46.848l56.192 56.192-56.192 56.192-4.096 4.672a30.336 30.336 0 0 0 46.848 38.08l56.192-56.192 56.192 56.192 4.672 4.096a30.336 30.336 0 0 0 38.08-46.848z m-459.52-255.36a32.704 32.704 0 0 0 22.272 11.136h1.152a34.496 34.496 0 0 0 22.848-9.344l148.032-148.608 2.368-2.944a35.968 35.968 0 0 0 0-43.328 28.544 28.544 0 0 0-22.272-11.136 36.288 36.288 0 0 0-24 9.344L309.568 359.296l-38.4-62.656-2.368-2.944a30.4 30.4 0 0 0-42.432-4.032 35.392 35.392 0 0 0-8.768 46.272l58.56 96.576 2.368 2.944z" fill="#999999" p-id="714"></path></svg>` this.iconSvg = `<svg t="1729144923785" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="713" width="200" height="200"><path d="M804.672 27.968H219.328A182.528 182.528 0 0 0 36.672 210.624v585.408a182.528 182.528 0 0 0 182.656 182.592h585.408a182.528 182.528 0 0 0 182.656-182.656V210.624A182.144 182.144 0 0 0 804.672 27.968z m110.08 768a109.952 109.952 0 0 1-110.08 110.08H219.328a109.952 109.952 0 0 1-110.08-110.08V210.624a109.952 109.952 0 0 1 110.08-110.08h585.408a109.952 109.952 0 0 1 110.08 110.08z m-172.096-573.632l-511.04 511.04-4.096 5.248a37.248 37.248 0 0 0 4.096 46.848 36.736 36.736 0 0 0 51.2 0l511.04-511.04 4.096-5.248a37.248 37.248 0 0 0-4.096-46.848 35.712 35.712 0 0 0-51.2 0z m-4.672 468.288l56.192-56.192 4.096-4.672a30.336 30.336 0 0 0-46.848-38.08l-56.192 56.192-56.192-56.192-4.672-4.096a30.336 30.336 0 0 0-38.08 46.848l56.192 56.192-56.192 56.192-4.096 4.672a30.336 30.336 0 0 0 46.848 38.08l56.192-56.192 56.192 56.192 4.672 4.096a30.336 30.336 0 0 0 38.08-46.848z m-459.52-255.36a32.704 32.704 0 0 0 22.272 11.136h1.152a34.496 34.496 0 0 0 22.848-9.344l148.032-148.608 2.368-2.944a35.968 35.968 0 0 0 0-43.328 28.544 28.544 0 0 0-22.272-11.136 36.288 36.288 0 0 0-24 9.344L309.568 359.296l-38.4-62.656-2.368-2.944a30.4 30.4 0 0 0-42.432-4.032 35.392 35.392 0 0 0-8.768 46.272l58.56 96.576 2.368 2.944z" fill="#999999" p-id="714"></path></svg>`
this.tag = 'button' this.tag = 'button'
} }
getValue() { getValue(editor) {
return 'hello, 音频' return <AIQuestionModal key={Date.now()} editor={editor} action="3"></AIQuestionModal>
}
isActive() {
return false
}
isDisabled() {
return true
}
exec() {
return
} }
} }
......
// Extend menu import BaseModalMenu from './common/BaseModalMenu'
class AIQuestionMultiple { import AIQuestionModal from './common/AIQuestionModal'
class AIQuestionMultiple extends BaseModalMenu {
constructor() { constructor() {
super()
this.title = '多选题' this.title = '多选题'
this.iconSvg = `<svg t="1729144537633" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4530" width="200" height="200"><path d="M358.4 256h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 1 1 0-102.4zM204.8 358.4a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m0 204.8a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m153.6-102.4h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z m0 204.8h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z" fill="#4C4C4C" p-id="4531"></path><path d="M204.8 51.2a153.6 153.6 0 0 0-153.6 153.6v614.4a153.6 153.6 0 0 0 153.6 153.6h614.4a153.6 153.6 0 0 0 153.6-153.6V204.8a153.6 153.6 0 0 0-153.6-153.6H204.8z m0-51.2h614.4a204.8 204.8 0 0 1 204.8 204.8v614.4a204.8 204.8 0 0 1-204.8 204.8H204.8a204.8 204.8 0 0 1-204.8-204.8V204.8a204.8 204.8 0 0 1 204.8-204.8z" fill="#4C4C4C" p-id="4532"></path></svg>` this.iconSvg = `<svg t="1729144537633" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4530" width="200" height="200"><path d="M358.4 256h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 1 1 0-102.4zM204.8 358.4a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m0 204.8a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m153.6-102.4h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z m0 204.8h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z" fill="#4C4C4C" p-id="4531"></path><path d="M204.8 51.2a153.6 153.6 0 0 0-153.6 153.6v614.4a153.6 153.6 0 0 0 153.6 153.6h614.4a153.6 153.6 0 0 0 153.6-153.6V204.8a153.6 153.6 0 0 0-153.6-153.6H204.8z m0-51.2h614.4a204.8 204.8 0 0 1 204.8 204.8v614.4a204.8 204.8 0 0 1-204.8 204.8H204.8a204.8 204.8 0 0 1-204.8-204.8V204.8a204.8 204.8 0 0 1 204.8-204.8z" fill="#4C4C4C" p-id="4532"></path></svg>`
this.tag = 'button' this.tag = 'button'
} }
getValue() { getValue(editor) {
return 'hello, 音频' return <AIQuestionModal key={Date.now()} editor={editor} action="2"></AIQuestionModal>
}
isActive() {
return false
}
isDisabled() {
return true
}
exec() {
return
} }
} }
......
// Extend menu import BaseModalMenu from './common/BaseModalMenu'
class AIQuestionSingle { import AIQuestionModal from './common/AIQuestionModal'
class AIQuestionSingle extends BaseModalMenu {
constructor() { constructor() {
super()
this.title = '单选题' this.title = '单选题'
this.iconSvg = `<svg t="1729144945895" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="860" width="200" height="200"><path d="M358.4 256h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 1 1 0-102.4zM204.8 358.4a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m153.6 102.4h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z m0 204.8h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z" fill="#4C4C4C" p-id="861"></path><path d="M204.8 51.2a153.6 153.6 0 0 0-153.6 153.6v614.4a153.6 153.6 0 0 0 153.6 153.6h614.4a153.6 153.6 0 0 0 153.6-153.6V204.8a153.6 153.6 0 0 0-153.6-153.6H204.8z m0-51.2h614.4a204.8 204.8 0 0 1 204.8 204.8v614.4a204.8 204.8 0 0 1-204.8 204.8H204.8a204.8 204.8 0 0 1-204.8-204.8V204.8a204.8 204.8 0 0 1 204.8-204.8z" fill="#4C4C4C" p-id="862"></path></svg>` this.iconSvg = `<svg t="1729144945895" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="860" width="200" height="200"><path d="M358.4 256h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 1 1 0-102.4zM204.8 358.4a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4z m153.6 102.4h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z m0 204.8h460.8a51.2 51.2 0 0 1 0 102.4H358.4a51.2 51.2 0 0 1 0-102.4z" fill="#4C4C4C" p-id="861"></path><path d="M204.8 51.2a153.6 153.6 0 0 0-153.6 153.6v614.4a153.6 153.6 0 0 0 153.6 153.6h614.4a153.6 153.6 0 0 0 153.6-153.6V204.8a153.6 153.6 0 0 0-153.6-153.6H204.8z m0-51.2h614.4a204.8 204.8 0 0 1 204.8 204.8v614.4a204.8 204.8 0 0 1-204.8 204.8H204.8a204.8 204.8 0 0 1-204.8-204.8V204.8a204.8 204.8 0 0 1 204.8-204.8z" fill="#4C4C4C" p-id="862"></path></svg>`
this.tag = 'button' this.tag = 'button'
} }
getValue() { getValue(editor) {
return 'hello, 音频' return <AIQuestionModal key={Date.now()} editor={editor} action="1"></AIQuestionModal>
}
isActive() {
return false
}
isDisabled() {
return true
}
exec() {
return
} }
} }
......
...@@ -19,7 +19,7 @@ class AIRewrite extends BaseModalMenu { ...@@ -19,7 +19,7 @@ class AIRewrite extends BaseModalMenu {
this.tag = 'button' this.tag = 'button'
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="rewrite"></AIModal> return <AIModal key={Date.now()} editor={editor} action="rewrite"></AIModal>
} }
} }
......
...@@ -19,7 +19,7 @@ class AISummary extends BaseModalMenu { ...@@ -19,7 +19,7 @@ class AISummary extends BaseModalMenu {
</svg>` </svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="summary"></AIModal> return <AIModal key={Date.now()} editor={editor} action="summary"></AIModal>
} }
} }
......
...@@ -9,7 +9,7 @@ class AITranslate extends BaseModalMenu { ...@@ -9,7 +9,7 @@ class AITranslate extends BaseModalMenu {
this.iconSvg = `<svg fill="#000000" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><defs><style>.cls-1{fill:none;}</style></defs><title>translate</title><path d="M27.85,29H30L24,14H21.65l-6,15H17.8l1.6-4h6.85ZM20.2,23l2.62-6.56L25.45,23Z"></path><path d="M18,7V5H11V2H9V5H2V7H12.74a14.71,14.71,0,0,1-3.19,6.18A13.5,13.5,0,0,1,7.26,9H5.16a16.47,16.47,0,0,0,3,5.58A16.84,16.84,0,0,1,3,18l.75,1.86A18.47,18.47,0,0,0,9.53,16a16.92,16.92,0,0,0,5.76,3.84L16,18a14.48,14.48,0,0,1-5.12-3.37A17.64,17.64,0,0,0,14.8,7Z"></path><rect id="_Transparent_Rectangle_" data-name="<Transparent Rectangle>" class="cls-1" width="32" height="32"></rect></g></svg>` this.iconSvg = `<svg fill="#000000" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><defs><style>.cls-1{fill:none;}</style></defs><title>translate</title><path d="M27.85,29H30L24,14H21.65l-6,15H17.8l1.6-4h6.85ZM20.2,23l2.62-6.56L25.45,23Z"></path><path d="M18,7V5H11V2H9V5H2V7H12.74a14.71,14.71,0,0,1-3.19,6.18A13.5,13.5,0,0,1,7.26,9H5.16a16.47,16.47,0,0,0,3,5.58A16.84,16.84,0,0,1,3,18l.75,1.86A18.47,18.47,0,0,0,9.53,16a16.92,16.92,0,0,0,5.76,3.84L16,18a14.48,14.48,0,0,1-5.12-3.37A17.64,17.64,0,0,0,14.8,7Z"></path><rect id="_Transparent_Rectangle_" data-name="<Transparent Rectangle>" class="cls-1" width="32" height="32"></rect></g></svg>`
} }
getValue(editor) { getValue(editor) {
return <AIModal key={Date.now()} editor={editor} docAction="translate"></AIModal> return <AIModal key={Date.now()} editor={editor} action="translate"></AIModal>
} }
} }
......
...@@ -38,34 +38,34 @@ const actionMap = { ...@@ -38,34 +38,34 @@ const actionMap = {
} }
} }
export default function AIModal({ editor, docAction }) { export default function AIModal({ editor, action }) {
const [isModalOpen, setIsModalOpen] = useState(true) const [isModalOpen, setIsModalOpen] = useState(true)
const [content, setContent] = useState('') const [content, setContent] = useState('')
const { text, fetch, isLoading } = useAIEdit() const { text, fetch, isLoading } = useAIEdit()
const actionText = actionMap[docAction]?.name const actionText = actionMap[action]?.name
const [selectionText, setSelectionText] = useState('') const [selectionText, setSelectionText] = useState('')
useEffect(() => { useEffect(() => {
const selection = editor.getSelectionText() const selection = editor.getSelectionText()
if (selection) { if (selection) {
setSelectionText(selection) setSelectionText(selection)
setContent(selection) setContent(selection)
fetch({ messages: [{ role: 'user', content: actionMap[docAction].prompt + selection }] }) fetch({ messages: [{ role: 'user', content: actionMap[action].prompt + selection }] })
} }
}, [docAction, editor, fetch]) }, [action, editor, fetch])
useEffect(() => { useEffect(() => {
setContent(text) setContent(text)
}, [text]) }, [text])
const handleFetch = () => { const handleFetch = () => {
fetch({ messages: [{ role: 'user', content: actionMap[docAction].prompt + selectionText }] }) fetch({ messages: [{ role: 'user', content: actionMap[action].prompt + selectionText }] })
} }
const handlePrimary = () => { const handlePrimary = () => {
let result = content.trim() let result = content.trim()
// 标点校对结果判断 // 标点校对结果判断
if (docAction === 'punctuation') { if (action === 'punctuation') {
if (result.includes('该内容标点符号正常')) { if (result.includes('该内容标点符号正常')) {
setIsModalOpen(false) setIsModalOpen(false)
return return
...@@ -76,7 +76,7 @@ export default function AIModal({ editor, docAction }) { ...@@ -76,7 +76,7 @@ export default function AIModal({ editor, docAction }) {
} }
} }
// 内容检查结果判断 // 内容检查结果判断
if (docAction === 'contentInspect') { if (action === 'contentInspect') {
if (result.includes('该内容正常,无敏感词和错别字')) { if (result.includes('该内容正常,无敏感词和错别字')) {
setIsModalOpen(false) setIsModalOpen(false)
return return
...@@ -87,7 +87,7 @@ export default function AIModal({ editor, docAction }) { ...@@ -87,7 +87,7 @@ export default function AIModal({ editor, docAction }) {
} }
} }
// 翻译结果判断 // 翻译结果判断
if (docAction === 'translate') { if (action === 'translate') {
const match = result.match(/翻译结果[::]?\s?([\s\S]*)/) const match = result.match(/翻译结果[::]?\s?([\s\S]*)/)
if (match) { if (match) {
result = match[1].trim() result = match[1].trim()
...@@ -111,11 +111,6 @@ export default function AIModal({ editor, docAction }) { ...@@ -111,11 +111,6 @@ export default function AIModal({ editor, docAction }) {
title={`以下是AI${actionText}结果:`} title={`以下是AI${actionText}结果:`}
open={isModalOpen} open={isModalOpen}
footer={null} footer={null}
classNames={{
header: 'editor-header-customer',
body: 'editor-body-customer',
wrapper: 'editor-wrapper-customer'
}}
onOk={handlePrimary} onOk={handlePrimary}
onCancel={() => setIsModalOpen(false)}> onCancel={() => setIsModalOpen(false)}>
<Spin spinning={isLoading}> <Spin spinning={isLoading}>
...@@ -123,14 +118,12 @@ export default function AIModal({ editor, docAction }) { ...@@ -123,14 +118,12 @@ export default function AIModal({ editor, docAction }) {
</Spin> </Spin>
<br /> <br />
<Flex gap="small" justify="center"> <Flex gap="small" justify="center">
<Button type="primary" onClick={handlePrimary}> <Button onClick={() => setIsModalOpen(false)}>取消</Button>
替换内容
</Button>
<Button type="primary" onClick={handleFetch}> <Button type="primary" onClick={handleFetch}>
重新{actionText} 重新{actionText}
</Button> </Button>
<Button type="primary" onClick={() => setIsModalOpen(false)}> <Button type="primary" onClick={handlePrimary}>
取消 替换内容
</Button> </Button>
</Flex> </Flex>
</Modal> </Modal>
......
import { useEffect, useState } from 'react'
import { Modal, Input, Button, Flex, Spin, Form, App } from 'antd'
import { useAIEdit } from '@/hooks/useBaiduAI'
import { addType, addQuestion } from '@/api/ai'
import store from '@/store/index'
const { TextArea } = Input
const actionMap = {
1: {
name: '单选题',
prompt: `请根据以下内容,理解之后,出一道单选题,要求如下:
1、包含四个选项。
2、给出正确答案。
输出的内容包含:
1、题目类型:
2、分类:
3、题干:
4、题目解析:
5、题目选项_1:
6、题目选项答案_1:正确为“是”,错误为“否”
7、题目选项_2:
8、题目选项答案_2:正确为“是”,错误为“否”
9、题目选项_3:
10、题目选项答案_3:正确为“是”,错误为“否”
11、题目选项_4:
12、题目选项答案_1:正确为“是”,错误为“否”
待理解内容:`
},
2: {
name: '多选题',
prompt: `请根据以下内容,理解之后,出一道多选题,要求如下:
1、包含四个选项。
2、给出正确答案。
输出的内容包含:
1、题目类型:
2、分类:
3、题干:
4、题目解析:
5、题目选项_1:
6、题目选项答案_1:正确为“是”,错误为“否”
7、题目选项_2:
8、题目选项答案_2:正确为“是”,错误为“否”
9、题目选项_3:
10、题目选项答案_3:正确为“是”,错误为“否”
11、题目选项_4:
12、题目选项答案_1:正确为“是”,错误为“否”
待理解内容:`
},
3: {
name: '判断题',
prompt: `请根据以下内容,理解之后,出一道判断题,要求如下:
1、包含四个选项。
2、给出正确答案。
输出的内容包含:
1、题目类型:
2、分类:
3、题干:
4、题目解析:
5、题目选项_1:
6、题目选项答案_1:正确为“是”,错误为“否”
7、题目选项_2:
8、题目选项答案_2:正确为“是”,错误为“否”
待理解内容:`
}
}
export default function AIQuestionModal({ editor, action }) {
const { message } = App.useApp()
const [isModalOpen, setIsModalOpen] = useState(true)
const [content, setContent] = useState('')
const { text, fetch, isLoading } = useAIEdit()
const actionText = actionMap[action]?.name
const [selectionText, setSelectionText] = useState('')
useEffect(() => {
const selection = editor.getSelectionText()
if (selection) {
setSelectionText(selection)
setContent(selection)
fetch({ messages: [{ role: 'user', content: actionMap[action].prompt + selection }] })
}
}, [action, editor, fetch])
useEffect(() => {
if (text) setQuestion(generateQuestionData(text))
}, [text])
const handleFetch = () => {
fetch({ messages: [{ role: 'user', content: actionMap[action].prompt + selectionText }] })
}
const [question, setQuestion] = useState({
question_style: action,
titles: '',
analysis: '',
question_list: []
})
// 获取A-Z的字母
function getAlphabet(i) {
return String.fromCharCode(65 + i)
}
// 生成试题数据
function generateQuestionData(str) {
// 初始化返回对象
const result = {
titles: '',
analysis: '',
answers: '',
question_list: []
}
// 使用正则表达式提取各个部分
const titleMatch = str.match(/题干:(.+?)\s/)
const analysisMatch = str.match(/题目解析:(.+?)\s/)
// 设置基本信息
if (titleMatch) result.titles = titleMatch[1]
if (analysisMatch) result.analysis = analysisMatch[1]
// 提取选项和答案
const options = []
let currentIndex = 1
// eslint-disable-next-line no-constant-condition
while (true) {
const optionMatch = str.match(new RegExp(`题目选项_${currentIndex}:(.+?)\\s`))
const answerMatch = str.match(new RegExp(`题目选项答案_${currentIndex}:(是|否)`))
console.log(optionMatch, answerMatch, currentIndex)
if (!optionMatch || !answerMatch) break
const option = { option: optionMatch[1], correct: answerMatch[1] === '是', abc: getAlphabet(currentIndex - 1) }
if (option.correct) result.answers += option.abc
options.push(option)
currentIndex++
}
result.question_list = options
return result
}
const { user } = store.getState()
// 提交
const handlePrimary = async () => {
const { data } = await addType({ name: `${user.treeChapter.book_name}/${user.treeChapter.chapter_name}` })
const res = await addQuestion({
...question,
book_id: user.treeChapter.book_id,
type_id: data.type_id,
question_style: action,
question_list: JSON.stringify(question.question_list)
})
message.success(res.message)
setIsModalOpen(false)
}
return (
<Modal
title="AI创建试题"
open={isModalOpen}
footer={null}
width={800}
onOk={handlePrimary}
onCancel={() => setIsModalOpen(false)}>
<Spin spinning={isLoading}>
<Form labelCol={{ span: 2 }}>
<Form.Item label="题目类型">{actionText}</Form.Item>
<Form.Item label="参考内容">
<TextArea autoSize={{ minRows: 4 }} value={content} onChange={e => setContent(e.target.value)} />
</Form.Item>
<Form.Item label="题干">
<div style={{ lineHeight: '32px' }}>
{question.titles}
{question.question_list.map(item => {
return (
<div key={item.abc}>
{item.abc}.{item.option}
</div>
)
})}
</div>
</Form.Item>
<Form.Item label="正确答案">{question.answers}</Form.Item>
<Form.Item label="题目解析">
<div style={{ lineHeight: '32px' }}>{question.analysis}</div>
</Form.Item>
</Form>
</Spin>
<br />
<Flex gap="small" justify="center">
<Button onClick={() => setIsModalOpen(false)}>取消</Button>
<Button type="primary" onClick={handleFetch}>
重新出题
</Button>
<Button type="primary" onClick={handlePrimary}>
确定
</Button>
</Flex>
</Modal>
)
}
...@@ -498,7 +498,7 @@ const CustomerTopic = (props, ref) => { ...@@ -498,7 +498,7 @@ const CustomerTopic = (props, ref) => {
)} )}
<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 type="primary" disabled={showAddClass} loading={loading} htmlType="submit">
提交 提交
</Button> </Button>
</Space> </Space>
......
import React,{useEffect, useState} from "react"; import React, { useEffect, useState } from 'react'
import { Table,Row,DatePicker,Form,Modal ,Switch} from "antd"; import { Table, Row, DatePicker, Form, Modal, Switch } from 'antd'
const {RangePicker}=DatePicker const { RangePicker } = DatePicker
import PaginationCom from '@/common/Pagination' import PaginationCom from '@/common/Pagination'
import {getPositionList,changeStatus} from './request' import { getPositionList, changeStatus } from './request'
import TableCom from "@/common/TableCom/index"; import TableCom from '@/common/TableCom/index'
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux'
const Adsense=()=>{ const Adsense = () => {
const [data,setData]=useState([]) const [data, setData] = useState([])
const [page_size,setpage_size]=useState(10) const [page_size, setpage_size] = useState(10)
const [page,setPage]=useState(1) const [page, setPage] = useState(1)
const [total,setTotal]=useState(0) const [total, setTotal] = useState(0)
const [loading,setLoading]=useState(true) const [loading, setLoading] = useState(true)
const [isEdit,setIsEdit]=useState(false) const [isEdit, setIsEdit] = useState(false)
const [delMoadal,setDelModal]=useState(false) const [delMoadal, setDelModal] = useState(false)
const [form]=Form.useForm() const [form] = Form.useForm()
const [swichDisabled, setSwichDisabled] = useState(false); const [swichDisabled, setSwichDisabled] = useState(false)
// 获取操作权限 // 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user); const { operationPermissionsList } = useSelector(state => state.user)
const handleStatus=async (status,id)=>{ const handleStatus = async (status, id) => {
const bool=await changeStatus({id,status:status?'1':'0'}) const bool = await changeStatus({ id, status: status ? '1' : '0' })
bool&&init() bool && init()
} }
const onClose=()=>{ const onClose = () => {
setIsEdit(false) setIsEdit(false)
} }
const submitForm=(obj)=>{ const submitForm = obj => {
console.log(obj); console.log(obj)
} }
const delSuccess=()=>{ const delSuccess = () => {
setDelModal(false) setDelModal(false)
} }
const init=async(obj={})=>{ const init = async (obj = {}) => {
setLoading(true) setLoading(true)
const {total,list}=await getPositionList({page,page_size,...obj}) const { total, list } = await getPositionList({ page, page_size, ...obj })
setTotal(total) setTotal(total)
setData(list); setData(list)
setLoading(false) setLoading(false)
} }
useEffect(() => { useEffect(() => {
setSwichDisabled(!operationPermissionsList.includes('/advertisement/adsense/changeStatus')) setSwichDisabled(!operationPermissionsList.includes('/advertisement/adsense/changeStatus'))
}); })
const columns=[ const columns = [
{ {
title:'广告位位置', title: '广告位位置',
key:'position_name', key: 'position_name',
dataIndex:'position_name' dataIndex: 'position_name'
}, },
{ {
title:'广告位大小', title: '广告位大小',
key:'pic_size', key: 'pic_size',
dataIndex:'pic_size' dataIndex: 'pic_size'
}, },
{ {
title:'状态', title: '状态',
key:'status', key: 'status',
dataIndex:'status', dataIndex: 'status',
render(_,{status,id}){ render(_, { status, id }) {
return ( return <Switch defaultChecked={status} onChange={ev => handleStatus(ev, id)} disabled={swichDisabled} />
<Switch defaultChecked={status} onChange={(ev)=>handleStatus(ev,id)} disabled={swichDisabled}/>
)
} }
}, }
] ]
return ( return (
<div className="classify"> <div className="classify">
{TableCom({columns,data,loading})} {TableCom({ columns, data, loading })}
<Modal mask={false} centered open={delMoadal} onOk={delSuccess} onCancel={()=>setDelModal(false)} footer={(_,{ OkBtn, CancelBtn })=>{ <Modal
return ( mask={false}
<Row justify={'center'} className="delModal"> centered
<Space> open={delMoadal}
<CancelBtn className="cancel" /> onOk={delSuccess}
<OkBtn className="true" /> onCancel={() => setDelModal(false)}
</Space> footer={(_, { OkBtn, CancelBtn }) => {
</Row> return (
) <Row justify={'center'} className="delModal">
}} okText="确认"> <Space>
<p style={{textAlign:'center',padding: "50px 0 30px",fontSize:16}}>分类将永久删除,是否继续?</p> <CancelBtn />
<OkBtn />
</Space>
</Row>
)
}}
okText="确认">
<p style={{ textAlign: 'center', padding: '50px 0 30px', fontSize: 16 }}>分类将永久删除,是否继续?</p>
</Modal> </Modal>
<br /> <br />
<PaginationCom total={total} <PaginationCom
total={total}
page_size={page_size} page_size={page_size}
setpage_size={setpage_size} setpage_size={setpage_size}
page={page} page={page}
...@@ -92,4 +97,4 @@ const Adsense=()=>{ ...@@ -92,4 +97,4 @@ const Adsense=()=>{
) )
} }
export default Adsense; export default Adsense
\ No newline at end of file
...@@ -91,7 +91,9 @@ const Audit = () => { ...@@ -91,7 +91,9 @@ const Audit = () => {
const parser = new DOMParser() const parser = new DOMParser()
const doc = parser.parseFromString(content, 'text/html') const doc = parser.parseFromString(content, 'text/html')
$(doc.body) $(doc.body)
.find(".chapter-gallery-container, .chapter-expand, .chapter-practice, .chapter-item-link, .chapter-item-tooltip, div[data-w-e-type='video']") .find(
".chapter-gallery-container, .chapter-expand, .chapter-practice, .chapter-item-link, .chapter-item-tooltip, div[data-w-e-type='video']"
)
.remove() .remove()
const data = await exportToPdf({ name, content: $(doc.body).html() }) const data = await exportToPdf({ name, content: $(doc.body).html() })
...@@ -272,15 +274,17 @@ const Audit = () => { ...@@ -272,15 +274,17 @@ const Audit = () => {
</Button> </Button>
)} )}
{isAdminOrCreator && operationPermissionsList.includes('/books/management/release') && audit_status === 1 && ( {isAdminOrCreator &&
<Button operationPermissionsList.includes('/books/management/release') &&
onClick={() => { audit_status === 1 && (
setId(id) <Button
setShowAudit(true) onClick={() => {
}}> setId(id)
发布审核 setShowAudit(true)
</Button> }}>
)} 发布审核
</Button>
)}
</Space> </Space>
) )
} }
...@@ -324,7 +328,10 @@ const Audit = () => { ...@@ -324,7 +328,10 @@ const Audit = () => {
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label="创建时间"> <Form.Item label="创建时间">
<RangePicker value={dateVal} onChange={ev => handleFilter('startandend', ev)} id="createTime"></RangePicker> <RangePicker
value={dateVal}
onChange={ev => handleFilter('startandend', ev)}
id="createTime"></RangePicker>
</Form.Item> </Form.Item>
<Space> <Space>
<Button <Button
...@@ -441,8 +448,8 @@ const Audit = () => { ...@@ -441,8 +448,8 @@ const Audit = () => {
return ( return (
<Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}> <Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}>
<Space size={20}> <Space size={20}>
<CancelBtn className="cancel" /> <CancelBtn />
<OkBtn className="true" /> <OkBtn />
</Space> </Space>
</Row> </Row>
) )
...@@ -461,16 +468,25 @@ const Audit = () => { ...@@ -461,16 +468,25 @@ const Audit = () => {
return ( return (
<Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}> <Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}>
<Space size={20}> <Space size={20}>
<CancelBtn className="cancel" /> <CancelBtn />
<OkBtn className="true" /> <OkBtn />
</Space> </Space>
</Row> </Row>
) )
}} }}
okText="确认"> okText="确认">
<p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>只能导出文本部分,画廊、音频、视频不支持</p> <p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>
只能导出文本部分,画廊、音频、视频不支持
</p>
</Modal> </Modal>
<Drawer mask={false} centered open={importModal} onCancel={() => setImportModal(false)} onClose={() => setImportModal(false)} footer={null} okText="确认"> <Drawer
mask={false}
centered
open={importModal}
onCancel={() => setImportModal(false)}
onClose={() => setImportModal(false)}
footer={null}
okText="确认">
<Spin spinning={uploading}> <Spin spinning={uploading}>
<Form labelCol={{ span: 8 }} onFinish={importSuccess}> <Form labelCol={{ span: 8 }} onFinish={importSuccess}>
<Form.Item label="下载模板" style={{ marginBottom: 10 }}> <Form.Item label="下载模板" style={{ marginBottom: 10 }}>
...@@ -498,7 +514,10 @@ const Audit = () => { ...@@ -498,7 +514,10 @@ const Audit = () => {
<p style={{ color: '#999999' }}>{bookFile?.name}</p> <p style={{ color: '#999999' }}>{bookFile?.name}</p>
</Form.Item> </Form.Item>
<Form.Item label="目录结构等级" name="catalog_level" rules={[{ required: true, message: '请选择目录结构等级' }]}> <Form.Item
label="目录结构等级"
name="catalog_level"
rules={[{ required: true, message: '请选择目录结构等级' }]}>
<Select placeholder="请选择目录结构的等级" style={{ width: 260 }}> <Select placeholder="请选择目录结构的等级" style={{ width: 260 }}>
<Select.Option value={1}>标题1</Select.Option> <Select.Option value={1}>标题1</Select.Option>
<Select.Option value={2}>标题2</Select.Option> <Select.Option value={2}>标题2</Select.Option>
...@@ -534,13 +553,12 @@ const Audit = () => { ...@@ -534,13 +553,12 @@ const Audit = () => {
<Form.Item wrapperCol={{ offset: 10, span: 16 }}> <Form.Item wrapperCol={{ offset: 10, span: 16 }}>
<Space size={20}> <Space size={20}>
<Button <Button
className="cancel"
onClick={() => { onClick={() => {
setShowAudit(false) setShowAudit(false)
}}> }}>
取消 取消
</Button> </Button>
<Button className="submit" htmlType="submit"> <Button type="primary" htmlType="submit">
发布 发布
</Button> </Button>
</Space> </Space>
...@@ -550,7 +568,15 @@ const Audit = () => { ...@@ -550,7 +568,15 @@ const Audit = () => {
<br /> <br />
{TableCom({ columns, loading, data })} {TableCom({ columns, loading, data })}
<br /> <br />
<PaginationCom total={total} page_size={page_size} setpage_size={setpage_size} page={page} setPage={setPage} init={init} filterObj={filterObj} /> <PaginationCom
total={total}
page_size={page_size}
setpage_size={setpage_size}
page={page}
setPage={setPage}
init={init}
filterObj={filterObj}
/>
</> </>
) )
} }
......
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react' import { 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, Row, Col, Checkbox } from 'antd'
import { MinusOutlined, PlusOutlined } from '@ant-design/icons' import { MinusOutlined, PlusOutlined } from '@ant-design/icons'
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, typeList, questionAddType, questionEdit, bookNameList } from '@/pages/books/question-bank/request' import { questionAdd, questionAddType, questionEdit } from '@/pages/books/question-bank/request'
import { uploadFiles } from '@/utils/upload'
import QuestionEditr from '@/pages/books/question-bank/questionEditr' import QuestionEditr from '@/pages/books/question-bank/questionEditr'
import './index.less' import './index.less'
import dayjs from 'dayjs' import dayjs from 'dayjs'
...@@ -15,7 +13,7 @@ import AliOSS from 'ali-oss' ...@@ -15,7 +13,7 @@ import AliOSS from 'ali-oss'
import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet' import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet'
const CustomerTopic = (props, ref) => { const CustomerTopic = (props, ref) => {
const { topicData, isadd, init, getTypeList, typeDate, setShowModal, bookNameData, bookIdList, typeId } = props const { topicData, isadd, init, getTypeList, typeDate, setShowModal, 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 过期设置
...@@ -59,12 +57,10 @@ const CustomerTopic = (props, ref) => { ...@@ -59,12 +57,10 @@ const CustomerTopic = (props, ref) => {
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 [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,
question_style: '', question_style: '',
...@@ -77,9 +73,6 @@ const CustomerTopic = (props, ref) => { ...@@ -77,9 +73,6 @@ const CustomerTopic = (props, ref) => {
const [selectedTypeId, setSelectedTypeId] = useState([]) const [selectedTypeId, setSelectedTypeId] = useState([])
useEffect(() => { useEffect(() => {
// console.log('typeId', typeId); //书的typeid
// 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 : ''
...@@ -122,10 +115,10 @@ const CustomerTopic = (props, ref) => { ...@@ -122,10 +115,10 @@ const CustomerTopic = (props, ref) => {
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])
...@@ -133,10 +126,8 @@ const CustomerTopic = (props, ref) => { ...@@ -133,10 +126,8 @@ const CustomerTopic = (props, ref) => {
// 显示不同类型的选项函数 // 显示不同类型的选项函数
const [edierVal, setedierVal] = useState('') const [edierVal, setedierVal] = useState('')
// 是否显示选项 // 是否显示选项
const [showList, setShowList] = 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('')
// 分类 // 分类
...@@ -145,8 +136,8 @@ const CustomerTopic = (props, ref) => { ...@@ -145,8 +136,8 @@ const CustomerTopic = (props, ref) => {
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)
} }
} }
...@@ -189,9 +180,6 @@ const CustomerTopic = (props, ref) => { ...@@ -189,9 +180,6 @@ const CustomerTopic = (props, ref) => {
console.log('result', result) console.log('result', result)
insertFn(result.url, '题库图片') insertFn(result.url, '题库图片')
// const { url } = await uploadFiles({ file, file_type: 'question' });
// insertFn(url, '题库图片');
} }
} }
}, },
...@@ -304,9 +292,6 @@ const CustomerTopic = (props, ref) => { ...@@ -304,9 +292,6 @@ const CustomerTopic = (props, ref) => {
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 => {
setShowList(true)
}}
style={{ width: 260 }} style={{ width: 260 }}
placeholder="请选择书籍名称" placeholder="请选择书籍名称"
showSearch //下拉框出现搜素,并可以输入 showSearch //下拉框出现搜素,并可以输入
...@@ -324,9 +309,6 @@ const CustomerTopic = (props, ref) => { ...@@ -324,9 +309,6 @@ const CustomerTopic = (props, ref) => {
<Form.Item name="question_style" label="题目类型" rules={[{ required: true, message: '请选择题目类型' }]}> <Form.Item name="question_style" label="题目类型" rules={[{ required: true, message: '请选择题目类型' }]}>
<Select <Select
onChange={ev => { onChange={ev => {
setShowList(true)
// setinitialValues({ ...initialValues, question_style: ev });
// form.setFieldValue('question_style', ev);
setQuestionStyle(ev) setQuestionStyle(ev)
}} }}
style={{ width: 260 }} style={{ width: 260 }}
...@@ -373,7 +355,7 @@ const CustomerTopic = (props, ref) => { ...@@ -373,7 +355,7 @@ const CustomerTopic = (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="请输入题目分类"></Input> placeholder="请输入题目分类"></Input>
<Space> <Space>
...@@ -398,33 +380,29 @@ const CustomerTopic = (props, ref) => { ...@@ -398,33 +380,29 @@ const CustomerTopic = (props, ref) => {
{ validator: vaildaterHtml, validateTrigger: 'onChange' } { validator: vaildaterHtml, validateTrigger: 'onChange' }
]} ]}
extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''}> extra={questionType === 4 ? '请在需要填空的位置使用2个或以上的下划线进行区分!' : ''}>
<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"
style={{ borderBottom: '1px solid #ccc' }}
/>
{ossClient && (
<Editor
defaultConfig={editorConfig}
value={initialValues.titles}
onCreated={setTitlesEditor}
onChange={editor => {
form.setFieldValue('titles', editor.getHtml())
}}
config={{
uploadImgServer: 'your_upload_server_address'
}}
mode="default" mode="default"
style={{ borderBottom: '1px solid #ccc' }} style={{ height: '200px', overflowY: 'hidden' }}
/> />
{ossClient && ( )}
<Editor </div>
defaultConfig={editorConfig}
value={initialValues.titles}
onCreated={setTitlesEditor}
onChange={editor => {
form.setFieldValue('titles', editor.getHtml())
// setHtml(editor.getHtml())
}}
config={{
uploadImgServer: 'your_upload_server_address'
// other config options
}}
mode="default"
style={{ height: '200px', overflowY: 'hidden' }}
/>
)}
</div>
</Spin>
</Form.Item> </Form.Item>
<Form.Item name="analysis" label="题目解析"> <Form.Item name="analysis" label="题目解析">
<Input.TextArea <Input.TextArea
...@@ -485,7 +463,6 @@ const CustomerTopic = (props, ref) => { ...@@ -485,7 +463,6 @@ const CustomerTopic = (props, ref) => {
initialValue={restField.correct || false}> initialValue={restField.correct || false}>
<Checkbox <Checkbox
onChange={e => { onChange={e => {
// 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) {
...@@ -550,29 +527,6 @@ const CustomerTopic = (props, ref) => { ...@@ -550,29 +527,6 @@ const CustomerTopic = (props, ref) => {
)} )}
</Form.List> </Form.List>
)} )}
{/* {questionStyle === 3 && (
<Form.Item name='question_list' label='正确答案'>
<Radio.Group
onChange={(e) => {
let val = e.target.value;
if (val === '正确') {
setQuesList([
{ option: '正确', correct: true },
{ option: '错误', correct: false },
]);
} else {
setQuesList([
{ option: '正确', correct: false },
{ option: '错误', correct: true },
]);
}
}}
>
<Radio value='正确'>√</Radio>
<Radio value='错误'>×</Radio>
</Radio.Group>
</Form.Item>
)} */}
{(questionStyle === 5 || questionStyle === 4) && ( {(questionStyle === 5 || questionStyle === 4) && (
<Form.Item name="answers" label="正确答案"> <Form.Item name="answers" label="正确答案">
<QuestionEditr editorValue={edierVal} setedierVal={setedierVal} form={form} name="answers" /> <QuestionEditr editorValue={edierVal} setedierVal={setedierVal} form={form} name="answers" />
...@@ -580,10 +534,8 @@ const CustomerTopic = (props, ref) => { ...@@ -580,10 +534,8 @@ const CustomerTopic = (props, ref) => {
)} )}
<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 onClick={() => setShowModal(false)}>取消</Button>
取消 <Button type="primary" disabled={showAddClass} htmlType="submit">
</Button>
<Button className="submit" disabled={showAddClass} htmlType="submit">
提交 提交
</Button> </Button>
</Space> </Space>
......
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论