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

chore: update

上级 a29212a5
# VITE_API_URL_WORD = http://ebook-pc.ezijing.com:7419
# VITE_API_URL_WORD = https://book-admin-web.ezijing.com/api
VITE_API_URL_WORD = https://zijingebook.ezijing.com/api
VITE_API_BASE_API_PREFFIX = /api
......
......@@ -36,7 +36,8 @@
"react-router-dom": "^6.23.1",
"redux-persist": "^6.0.0",
"snabbdom": "^3.6.2",
"xml-formatter": "^3.6.2"
"xml-formatter": "^3.6.2",
"zustand": "^4.5.5"
},
"devDependencies": {
"@types/react": "^18.3.5",
......@@ -10077,6 +10078,34 @@
"dependencies": {
"tslib": "2.3.0"
}
},
"node_modules/zustand": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz",
"integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==",
"license": "MIT",
"dependencies": {
"use-sync-external-store": "1.2.2"
},
"engines": {
"node": ">=12.7.0"
},
"peerDependencies": {
"@types/react": ">=16.8",
"immer": ">=9.0.6",
"react": ">=16.8"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"immer": {
"optional": true
},
"react": {
"optional": true
}
}
}
}
}
......@@ -39,7 +39,8 @@
"react-router-dom": "^6.23.1",
"redux-persist": "^6.0.0",
"snabbdom": "^3.6.2",
"xml-formatter": "^3.6.2"
"xml-formatter": "^3.6.2",
"zustand": "^4.5.5"
},
"devDependencies": {
"@types/react": "^18.3.5",
......
......@@ -141,7 +141,7 @@ const tabsMenu = [
storageChange()
const WangEditorCustomer = (props, ref) => {
const { chapterId, bookId, contentId, html, setHtml, saveContent, gData, nowTitle } = props
const { chapterId, bookId, contentId, html, setHtml, saveContent, gData, nowTitle, disabled } = props
const dispatch = useDispatch()
// 自动保存时间
......@@ -428,6 +428,7 @@ const WangEditorCustomer = (props, ref) => {
}, 50)
}
editorConfig.onFocus = () => {
clearTimeout(saveRef.current)
}
......@@ -582,13 +583,13 @@ const WangEditorCustomer = (props, ref) => {
useEffect(() => {
if (editor) {
if (gData.length > 0) {
if (gData.length > 0 && !disabled) {
editor.enable()
} else {
editor.disable()
}
}
}, [gData, editor])
}, [gData, editor, disabled])
const tabKeyChange = key => {
if (key === 'text') {
......@@ -645,19 +646,13 @@ const WangEditorCustomer = (props, ref) => {
</div>
<span className="time">{autosaveTime > 0 ? `上次保存发生在 ${dayjs(autosaveTime).format('YYYY-MM-DD HH:mm:ss')}` : ''}</span>
</div>
<Button
type="primary"
icon={<SaveOutlined />}
className="view"
onClick={saveContent}
style={{ color: '#fff' }}
disabled={bookId && contentId ? false : true}>
<Button type="primary" icon={<SaveOutlined />} className="view" onClick={saveContent} style={{ color: '#fff' }} disabled={disabled}>
保存
</Button>
<Button icon={<EyeOutlined />} className="history" onClick={previewIt} disabled={bookId && contentId ? false : true}>
<Button icon={<EyeOutlined />} className="history" onClick={previewIt}>
预览
</Button>
<Button icon={<HistoryOutlined />} className="history" onClick={historyIt} disabled={bookId && contentId ? false : true}>
<Button icon={<HistoryOutlined />} className="history" onClick={historyIt} disabled={disabled}>
历史
</Button>
</Space>
......
......@@ -118,7 +118,6 @@
.layout-content {
background-color: #fff;
border-radius: 5px;
box-shadow: 0px 0px 20px 1px rgba(123, 123, 123, 0.2);
height: calc(100vh - 120px);
padding: 20px;
}
......
......@@ -36,7 +36,9 @@ const BookAddEdit = () => {
const onFinish = async values => {
const editors = values.editors?.map(item => item.value) || []
const res = isEdit ? await updateBook({ id: location.state.id, ...values, img, editors }) : await addBook({ ...values, img, editors })
const params = { ...values, img, editors }
if (editors.length === 0) delete params.editors
const res = isEdit ? await updateBook({ id: location.state.id, ...params }) : await addBook(params)
message.success(res.message)
navigate(-1)
}
......
import axios from '@/utils/axios'
// 获取书籍详情
export function getBook(data) {
return axios.post('/api/book/teacher/getInfoById', data)
}
// 获取章节列表
export function getChapterList(data) {
return axios.post('/api/book/teacher/chapter/getAllList', data)
}
// 获取章节详情
export function getChapter(data) {
return axios.post('/api/book/teacher/chapter/getInfoById', data)
}
// 添加章节
export function addChapter(data) {
return axios.post('/api/book/teacher/chapter/add', data)
}
// 修改章节
export function updateChapter(data) {
return axios.post('/api/book/teacher/chapter/edit', data)
}
// 删除章节
export function delChapter(data) {
return axios.post('/api/book/teacher/chapter/del', data)
}
// 章节排序
export function sortChapter(data) {
return axios.post('/api/book/teacher/chapter/dragOrder', data)
}
// 获取章节编辑者信息
export function getChapterEditors(data) {
return axios.post('/api/book/teacher/chapter/getEditors', data)
......
......@@ -21,11 +21,11 @@ const EditChapterEditors = ({ chapter = {}, onChange, ...props }) => {
}
return (
<Modal title="设置章节编写者" {...props} onOk={handleSubmit}>
<Modal title="设置章节编写者" centered {...props} onOk={handleSubmit}>
<Form labelCol={{ span: 8 }}>
<Form.Item label="当前章节">{chapter.title}</Form.Item>
<Form.Item label="编写者">
<Radio.Group value={value} onChange={e => setValue(e.target.value)}>
<Radio.Group value={value} onChange={e => setValue(e.target.value)} style={{ marginTop: '6px' }}>
<Space direction="vertical">
{editors.map(item => {
return (
......
import { useState, useEffect, useRef } from 'react'
import { Divider, Button, Row, Col, Descriptions, Tree, Dropdown, Space, Modal, Spin } from 'antd'
import { Button, Row, Col, Descriptions, Tree, Dropdown, Modal, Spin, App } from 'antd'
import { EllipsisOutlined, DiffOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
import WangEditorCustomer from '@/common/wangeditor-customer'
import { useLocation, useNavigate } from 'react-router-dom'
......@@ -12,23 +12,22 @@ import { get } from 'lodash-es'
import md5 from 'js-md5'
import { convertToAntdTreeData, findTreeElementByKey, findFirstNotHasChildren, findParentLevelOne, findTreeToIndex, findNodeById } from '@/utils/common'
import { getAllList, getInfoByChapterId, sectionEdit, chapterDel, dragOrder, getRecordList, getUserInfo, getPowerByRoleId } from './request'
import { getAllList, getInfoByChapterId, sectionEdit, chapterDel, dragOrder } from './request'
import './index.less'
const Examine = () => {
const { modal } = App.useApp()
const location = useLocation()
const id = get(location, 'state.id', '')
const { treeChapter } = useSelector(state => state.user)
const { treeChapter, userInfo } = useSelector(state => state.user)
const navigate = useNavigate()
const dispatch = useDispatch()
const [gData, setGData] = useState([])
const [chapterId, setChapterId] = useState(0)
const [bookId, setBookId] = useState(0)
const [openDel, setOpenDel] = useState(false)
const [delNode, setDelNode] = useState({})
const [recordList, setRecordList] = useState([])
// 树节点设置
const [expandedKeys, setExpandedKeys] = useState([])
......@@ -40,9 +39,7 @@ const Examine = () => {
const [parentId, setParentId] = useState(null)
const [editValue, setEditValue] = useState('')
const [loading, setLoading] = useState(false)
const [delLoading, setDelLoading] = useState(false)
const [contentMd5, setContentMd5] = useState('')
const [quanXian, setQuanXian] = useState(false)
// 设置编者
const [currentChapter, setCurrentChapter] = useState(null)
......@@ -107,15 +104,6 @@ const Examine = () => {
setLoading(false)
}
//选中了章节管理才展示编辑
const getQuanXian = async () => {
const data = await getUserInfo()
const data1 = await getPowerByRoleId({ role_id: data.id })
if (!data1.includes(37)) {
setQuanXian(true)
}
}
const newChapterChange = (id, title) => {
setChapterId(parseInt(id))
setCheckedKeys([parseInt(id)])
......@@ -132,11 +120,12 @@ const Examine = () => {
})
return keys
}
const [disabled, setDisabled] = useState(false)
// 获取内容
const getChapterVal = async () => {
setLoading(true)
const data = await getInfoByChapterId({ chapter_id: chapterId })
setDisabled(!data.selected_editor_ids.includes(userInfo.id))
dispatch(setTreeChapter({ saveBookId: id, saveChapterId: chapterId }))
const { content, id: cId } = data
......@@ -198,7 +187,6 @@ const Examine = () => {
useEffect(() => {
getChapterTreeList()
getQuanXian()
}, [])
useEffect(() => {
if (chapterId) {
......@@ -226,29 +214,15 @@ const Examine = () => {
return
} else {
setContentMd5(newMd5)
autoSaveContent(newMd5)
dispatch(setAutosaveTime(Date.now()))
}
}
}
}
// 定时器轮询
const autoSaveContent = newMd5 => {
// clearInterval(saveInterRef.current);
// saveInterRef.current = setInterval(async () => {
// if (!contentMd5 || (newMd5 !== contentMd5 && contentMd5)) {
// // console.log('save', newMd5, '不一样的');
// await saveContent();
// } else {
// // console.log('save', newMd5, '一样的');
// }
// }, 5000);
}
useEffect(() => {
if (!loading && contentId) {
let newMd5 = md5(html)
clearInterval(saveInterRef.current)
autoSaveContent(newMd5)
} else {
clearInterval(saveInterRef.current)
}
......@@ -261,7 +235,6 @@ const Examine = () => {
}
const delChapter = async node => {
setDelLoading(true)
const childInKey = findParentLevelOne(gData, 'key', node.key)
let current = null
if (childInKey && childInKey.children && childInKey.children.length > 0) {
......@@ -297,11 +270,8 @@ const Examine = () => {
const data = await chapterDel({ id: node.key })
if (data) {
await dispatch(setTreeChapter({ saveBookId: id, saveChapterId: current ? current.key : null }))
setDelNode({})
setOpenDel(false)
await getChapterTreeList()
}
setDelLoading(false)
}
useEffect(() => {
......@@ -344,8 +314,13 @@ const Examine = () => {
setEditValue(node.title)
setParentId(false)
} else if (parseInt(e.key) === 4) {
setDelNode(node)
setOpenDel(true)
await modal.confirm({
title: '删除确认',
content: `确认删除子节【${node.title}】?`,
onOk() {
delChapter(node)
}
})
} else if (e.key == 5) {
setEditChapterEditorsIsOpen(true)
}
......@@ -431,15 +406,13 @@ const Examine = () => {
{
key: '1',
label: (
<>
<Row gutter={5} justify={'space-between'} style={{ alignItems: 'center' }}>
<Col>章节目录</Col>
<Col>
<Button type="text" icon={<DiffOutlined />} onClick={addChapterParent}></Button>
<Button type="text" icon={<MenuFoldOutlined />} onClick={() => setisCollapse(true)}></Button>
</Col>
</Row>
</>
<Row gutter={5} justify={'space-between'} style={{ alignItems: 'center' }}>
<Col>章节目录</Col>
<Col>
<Button type="text" icon={<DiffOutlined />} onClick={addChapterParent}></Button>
<Button type="text" icon={<MenuFoldOutlined />} onClick={() => setisCollapse(true)}></Button>
</Col>
</Row>
)
}
]}
......@@ -471,13 +444,11 @@ const Examine = () => {
{
key: '1',
label: (
<>
<Row gutter={5} justify={'space-between'} style={{ alignItems: 'center' }}>
<Col>
<Button type="text" icon={<MenuUnfoldOutlined />} onClick={() => setisCollapse(false)}></Button>
</Col>
</Row>
</>
<Row gutter={5} justify={'space-between'} style={{ alignItems: 'center' }}>
<Col>
<Button type="text" icon={<MenuUnfoldOutlined />} onClick={() => setisCollapse(false)}></Button>
</Col>
</Row>
)
}
]}
......@@ -498,7 +469,7 @@ const Examine = () => {
saveContent={saveContent}
gData={gData}
nowTitle={nowTitle}
recordList={recordList}
disabled={disabled}
/>
</Spin>
</div>
......@@ -534,38 +505,6 @@ const Examine = () => {
/>
</Modal>
<Modal
open={openDel}
footer={null}
centered
destroyOnClose
title={'删除确认'}
maskClosable={false}
mask={true}
closeIcon={false} // 添加这一行以隐藏关闭按钮
onCancel={() => setOpenDel(false)}
classNames={{
wrapper: 'chapter-title-modal'
}}>
<Divider />
<div>确认删除子节【{delNode.title}】?</div>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Space>
<Button type="primary" danger loading={delLoading} onClick={() => delChapter(delNode)}>
确定
</Button>
<Button
type="default"
onClick={() => {
setDelNode({})
setOpenDel(false)
}}>
取消
</Button>
</Space>
</div>
</Modal>
{/* 设置章节编写者 */}
{currentChapter && editChapterEditorsIsOpen && (
<EditChapterEditors
......
.examine {
height: 100%;
.content-box {
padding-top: 14px;
height: 100%;
box-sizing: border-box;
overflow: hidden;
......
import { create } from 'zustand'
const useUserStore = create((set, get) => ({
user: {},
token: '',
permissions: [],
updateUser: user => set({ user }),
updateToken: token => set({ token }),
updatePermissions: permissions => set({ permissions }),
checkPermissions: permission => {
const { permissions } = get()
return permissions.includes(permission)
}
}))
export default useUserStore
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论