提交 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 React, { useEffect, useState } from 'react';
import {
Table,
Input,
Button,
Row,
Col,
Space,
DatePicker,
Image,
Drawer,
Form,
Select,
Modal,
Upload,
InputNumber,
Spin,
} from 'antd';
const { RangePicker } = DatePicker;
const { TextArea } = Input;
import { useNavigate } from 'react-router-dom';
import PaginationCom from '@/common/Pagination';
import { getList, delUser, exportBook, releaseExamine, importBook, exportToPdf } from '../request';
import reset from '@/assets/images/icon/reset.png';
import filter from '@/assets/images/icon/filter.png';
import add from '@/assets/images/icon/add.png';
import imports from '@/assets/images/icon/import.png';
import reload from '@/assets/images/icon/reload.png';
import dayjs from 'dayjs';
import TableCom from '@/common/TableCom/index';
import { useSelector } from 'react-redux';
import { downloadFile } from '@/utils/common';
import $ from 'jquery';
import { useState } from 'react'
import { Input, Button, Row, Col, Space, DatePicker, Image, Drawer, Form, Select, Modal, Upload, Spin } from 'antd'
const { RangePicker } = DatePicker
const { TextArea } = Input
import { useNavigate } from 'react-router-dom'
import PaginationCom from '@/common/Pagination'
import { getList, delUser, exportBook, releaseExamine, importBook, exportToPdf } from '../request'
import reset from '@/assets/images/icon/reset.png'
import filter from '@/assets/images/icon/filter.png'
import add from '@/assets/images/icon/add.png'
import imports from '@/assets/images/icon/import.png'
import reload from '@/assets/images/icon/reload.png'
import dayjs from 'dayjs'
import TableCom from '@/common/TableCom/index'
import { useSelector } from 'react-redux'
import { downloadFile } from '@/utils/common'
import $ from 'jquery'
const Audit = () => {
const [data, setData] = useState([]);
const navigate = useNavigate();
const [page_size, setpage_size] = useState(10);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(true);
const [isEdit, setIsEdit] = useState(false);
const [delMoadal, setDelModal] = useState(false);
const [exportMoadal, setExportModal] = useState(false);
const [importMoadal, setImportMoadal] = useState(false);
const [bookFile, setBookFile] = useState('');
const [showaudit, setshowaudit] = useState(false);
const [form] = Form.useForm();
const [id, setId] = useState(0);
const [filterObj, setfilterObj] = useState({
const [data, setData] = useState([])
const navigate = useNavigate()
const [page_size, setpage_size] = useState(10)
const [page, setPage] = useState(1)
const [total, setTotal] = useState(0)
const [loading, setLoading] = useState(true)
const [delModal, setDelModal] = useState(false)
const [exportModal, setExportModal] = useState(false)
const [importModal, setImportModal] = useState(false)
const [bookFile, setBookFile] = useState('')
const [showAudit, setShowAudit] = useState(false)
const [id, setId] = useState(0)
const [filterObj, setFilterObj] = useState({
name: '',
authors: '',
audit_status: null,
start_time: '',
end_time: '',
});
const [dateVal, setDateVal] = useState('');
end_time: ''
})
const [dateVal, setDateVal] = useState('')
// 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user);
const { operationPermissionsList } = useSelector(state => state.user)
const { userInfo } = useSelector(state => state.user)
// 重置
const handleReset = () => {
setfilterObj({ name: '', authors: '', audit_status: null });
setDateVal('');
init();
};
setFilterObj({ name: '', authors: '', audit_status: null })
setDateVal('')
init()
}
const init = async (obj = {}) => {
setLoading(true);
const { total, list } = await getList({ page, page_size, ...obj });
setTotal(total);
setData(list);
setLoading(false);
};
setLoading(true)
const { total, list } = await getList({ page, page_size, ...obj })
setTotal(total)
setData(list)
setLoading(false)
}
// 过滤
const handleFilter = (flag, val) => {
if (flag == 'startandend') {
let val2 = val || [];
filterObj['start_time'] = parseInt(
new Date(dayjs(val2[0]).format('YYYY-MM-DD') + ' 00:00:00').getTime() / 1000,
);
const endDate = new Date(dayjs(val2[1])).getDate();
const endTime = parseInt(
new Date(dayjs(val2[1]).format('YYYY-MM-') + endDate + ' 23:59:59').getTime() / 1000,
);
filterObj['end_time'] = endTime;
setDateVal(val);
let val2 = val || []
filterObj['start_time'] = parseInt(new Date(dayjs(val2[0]).format('YYYY-MM-DD') + ' 00:00:00').getTime() / 1000)
const endDate = new Date(dayjs(val2[1])).getDate()
const endTime = parseInt(new Date(dayjs(val2[1]).format('YYYY-MM-') + endDate + ' 23:59:59').getTime() / 1000)
filterObj['end_time'] = endTime
setDateVal(val)
if (!val2.length) {
delete filterObj['start_time'];
delete filterObj['end_time'];
delete filterObj['start_time']
delete filterObj['end_time']
}
} else {
filterObj[flag] = val;
filterObj[flag] = val
}
for (const key in filterObj) {
if (!filterObj[key]) {
delete filterObj[key];
delete filterObj[key]
}
}
setfilterObj({ ...filterObj });
if (!val) init(filterObj);
};
setFilterObj({ ...filterObj })
if (!val) init(filterObj)
}
const delSuccess = async () => {
const bool = await delUser({ id });
bool && init();
setDelModal(false);
};
const bool = await delUser({ id })
bool && init()
setDelModal(false)
}
const exportSuccess = async () => {
setExportModal(false);
setLoading(true);
const { name, content } = await exportBook({ id });
if (!name) return;
setExportModal(false)
setLoading(true)
const { name, content } = await exportBook({ id })
if (!name) return
const parser = new DOMParser();
const doc = parser.parseFromString(content, "text/html");
$(doc.body).find(".chapter-gallery-container, .chapter-expand, .chapter-practice, .chapter-item-link, .chapter-item-tooltip, div[data-w-e-type='video']").remove();
const parser = new DOMParser()
const doc = parser.parseFromString(content, 'text/html')
$(doc.body)
.find(".chapter-gallery-container, .chapter-expand, .chapter-practice, .chapter-item-link, .chapter-item-tooltip, div[data-w-e-type='video']")
.remove()
const data = await exportToPdf({ name, content: $(doc.body).html()});
setLoading(false);
downloadFile(`temp/${data.name}`);
};
const importSuccess = async (obj) => {
setuploading(true);
const bool = await importBook({ ...obj, file: bookFile });
const data = await exportToPdf({ name, content: $(doc.body).html() })
setLoading(false)
downloadFile(`temp/${data.name}`)
}
const importSuccess = async obj => {
setUploading(true)
const bool = await importBook({ ...obj, file: bookFile })
// if (!bool) return;
if (bool) {
window.location.replace(window.location.href);
window.location.replace(window.location.href)
}
setImportMoadal(false);
setuploading(false);
};
setImportModal(false)
setUploading(false)
}
const UploadProps = {
name: 'file',
accept: '.doc , .docx',
showUploadList: false,
beforeUpload (file) {
const suffixArr = ['doc', 'docx'];
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
beforeUpload(file) {
const suffixArr = ['doc', 'docx']
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1)
if (!suffixArr.includes(suffix)) {
message.error(`请上传以${suffixArr.join('、')}格式的书籍`);
return false;
message.error(`请上传以${suffixArr.join('、')}格式的书籍`)
return false
}
setBookFile(file);
return false;
},
};
const handleReleaseExamine = async (obj) => {
const bool = await releaseExamine({ ...obj, id });
setBookFile(file)
return false
}
}
const handleReleaseExamine = async obj => {
const bool = await releaseExamine({ ...obj, id })
if (bool) {
window.location.replace(window.location.href); // 几乎完美
window.location.replace(window.location.href) // 几乎完美
}
// location.replace(location.pathname + location.search); // 还可以
// document.location.reload(); //页面刷新效果明显
// window.location.reload(); //有加载效果
// window.location.assign(window.location.href); //直接重载页面
// location.href = location.href; // 不推荐,卡顿效果重
if (!bool) return;
setshowaudit(false);
init();
};
if (!bool) return
setShowAudit(false)
init()
}
// 下载模板
const handleDownload = async () => {
downloadFile('书籍导入示例.docx');
};
downloadFile('书籍导入示例.docx')
}
const [flag, setFlag] = useState(true);
const [uploading, setuploading] = useState(false);
const [uploading, setUploading] = useState(false)
const columns = [
{
title: '书籍名称',
key: 'name',
align: 'center',
dataIndex: 'name',
dataIndex: 'name'
},
{
title: '书籍图片',
......@@ -182,15 +157,15 @@ const Audit = () => {
width={80}
height={80}
src={img}
fallback='data:image/png;base64,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'
fallback="data:image/png;base64,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"
/>
),
)
},
{
title: '作者',
key: 'authors',
align: 'center',
dataIndex: 'authors',
dataIndex: 'authors'
},
{
title: '审核状态',
......@@ -201,182 +176,159 @@ const Audit = () => {
switch (audit_status) {
case 1:
return (
<Button type='link' style={{ color: '#000', cursor: 'initial' }}>
<Button type="link" style={{ color: '#000', cursor: 'initial' }}>
待发布
</Button>
);
)
case 2:
return (
<Button type='link' style={{ color: '#000', cursor: 'initial' }}>
<Button type="link" style={{ color: '#000', cursor: 'initial' }}>
审核中
</Button>
);
)
case 3:
return (
<Button type='link' style={{ cursor: 'initial' }} danger>
<Button type="link" style={{ cursor: 'initial' }} danger>
审核未通过
</Button>
);
)
case 4:
return (
<Button type='link' style={{ color: '#000', cursor: 'initial' }}>
<Button type="link" style={{ color: '#000', cursor: 'initial' }}>
审核通过
</Button>
);
)
}
},
}
},
{
title: '发布次数',
key: 'release_num',
dataIndex: 'release_num',
width: 150,
align: 'center',
align: 'center'
},
{
title: '创建时间',
key: 'create_time',
align: 'center',
dataIndex: 'create_time',
dataIndex: 'create_time'
},
{
title: '更新时间',
key: 'update_time',
align: 'center',
dataIndex: 'update_time',
dataIndex: 'update_time'
},
{
title: '操作',
key: 'handle',
dataIndex: 'handle',
// align:'center',
width: 400,
render: (_, { audit_status, id }) => {
const showButtons = !(
operationPermissionsList.includes('/books/management/release') && audit_status === 2
);
render: (_, { audit_status, id, user_id }) => {
// 审核中
if (audit_status === 2) return
// 创建者或者管理员
const hasButton = userInfo.id === user_id || userInfo.type === 1
return (
<Space>
{showButtons && operationPermissionsList.includes('/books/management/getAllList') && (
{hasButton && operationPermissionsList.includes('/books/management/getAllList') && (
<Button
onClick={() => {
navigate('/books/management/add-edit', {
state: {
id: id,
},
});
navigate('/books/management/add-edit', { state: { id: id } })
}}
type='primary'
ghost
>
type="primary"
ghost>
基本信息
</Button>
)}
{showButtons && operationPermissionsList.includes('/books/management/getInfoById') && (
{operationPermissionsList.includes('/books/management/getInfoById') && (
<Button
onClick={() => {
navigate('/books/management/chapter', {
state: {
id,
},
});
}}
>
navigate('/books/management/chapter', { state: { id } })
}}>
编辑
</Button>
)}
{showButtons && operationPermissionsList.includes('/books/management/export') && (
{hasButton && operationPermissionsList.includes('/books/management/export') && (
<Button
onClick={() => {
setId(id);
setExportModal(true);
}}
>
setId(id)
setExportModal(true)
}}>
导出
</Button>
)}
{showButtons && operationPermissionsList.includes('/books/management/del') && (
{hasButton && operationPermissionsList.includes('/books/management/del') && (
<Button
onClick={() => {
setId(id);
setDelModal(true);
}}
>
setId(id)
setDelModal(true)
}}>
删除
</Button>
)}
{showButtons &&
operationPermissionsList.includes('/books/management/release') &&
audit_status === 1 && (
<Button
onClick={() => {
setId(id);
setshowaudit(true);
}}
>
发布审核
</Button>
)}
{hasButton && operationPermissionsList.includes('/books/management/release') && audit_status === 1 && (
<Button
onClick={() => {
setId(id)
setShowAudit(true)
}}>
发布审核
</Button>
)}
</Space>
);
},
},
];
)
}
}
]
return (
<>
<Row justify={'space-between'}>
<Col span={21} className='form-devices-inline'>
<Form layout='inline'>
<Form.Item label='书籍名称'>
<Col span={21} className="form-devices-inline">
<Form layout="inline">
<Form.Item label="书籍名称">
<Input
autoComplete='off'
autoComplete="off"
allowClear
value={filterObj.name}
onChange={(ev) => handleFilter('name', ev.target.value)}
placeholder='请输入书籍名称'
id='name'
></Input>
onChange={ev => handleFilter('name', ev.target.value)}
placeholder="请输入书籍名称"
id="name"></Input>
</Form.Item>
<Form.Item label='作者'>
<Form.Item label="作者">
<Input
autoComplete='off'
autoComplete="off"
allowClear
value={filterObj.authors}
onChange={(ev) => handleFilter('authors', ev.target.value)}
placeholder='请输入作者'
id='author'
></Input>
onChange={ev => handleFilter('authors', ev.target.value)}
placeholder="请输入作者"
id="author"></Input>
</Form.Item>
<Form.Item label='审核状态'>
<Form.Item label="审核状态">
<Select
style={{ width: 160 }}
allowClear
value={filterObj.audit_status}
onChange={(ev) => handleFilter('audit_status', ev)}
placeholder='请选择审核状态'
id='status'
>
<Select.Option value='1'>待发布</Select.Option>
<Select.Option value='2'>审核中</Select.Option>
<Select.Option value='3'>审核未通过</Select.Option>
<Select.Option value='4'>审核通过</Select.Option>
onChange={ev => handleFilter('audit_status', ev)}
placeholder="请选择审核状态"
id="status">
<Select.Option value="1">待发布</Select.Option>
<Select.Option value="2">审核中</Select.Option>
<Select.Option value="3">审核未通过</Select.Option>
<Select.Option value="4">审核通过</Select.Option>
</Select>
</Form.Item>
<Form.Item label='创建时间'>
<RangePicker
value={dateVal}
onChange={(ev) => handleFilter('startandend', ev)}
id='createTime'
></RangePicker>
<Form.Item label="创建时间">
<RangePicker value={dateVal} onChange={ev => handleFilter('startandend', ev)} id="createTime"></RangePicker>
</Form.Item>
<Space>
<Button
type='primary'
type="primary"
// ghost={flag}
ghost
icon={
......@@ -385,44 +337,37 @@ const Audit = () => {
display: 'inline-block',
width: '11px',
height: '10px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={reset} />
</span>
}
// onMouseOver={() => {
// setFlag(!flag);
// }}
onClick={handleReset}
>
onClick={handleReset}>
重置
</Button>
<Button
type='primary'
type="primary"
icon={
<span
style={{
display: 'inline-block',
width: '13px',
height: '12px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={filter} />
</span>
}
ghost
onClick={() => {
setPage(1);
console.log(filterObj);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init();
}}
>
setPage(1)
console.log(filterObj)
Object.values(filterObj).some(item => item) ? init(filterObj) : init()
}}>
筛选
</Button>
<Button
type='primary'
type="primary"
ghost
icon={
<span
......@@ -430,16 +375,14 @@ const Audit = () => {
display: 'inline-block',
width: '10px',
height: '12px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={reload} />
</span>
}
onClick={() => {
Object.values(filterObj).some((item) => item) ? init(filterObj) : init();
}}
>
Object.values(filterObj).some(item => item) ? init(filterObj) : init()
}}>
刷新
</Button>
</Space>
......@@ -449,43 +392,39 @@ const Audit = () => {
<Space>
{operationPermissionsList.includes('/books/management/import') && (
<Button
type='primary'
type="primary"
icon={
<span
style={{
display: 'inline-block',
width: '11px',
height: '12px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={imports} />
</span>
}
ghost
onClick={() => setImportMoadal(true)}
>
onClick={() => setImportModal(true)}>
导入
</Button>
)}
{operationPermissionsList.includes('/books/management/add') && (
<Button
type='primary'
type="primary"
icon={
<span
style={{
display: 'inline-block',
width: '13px',
height: '12px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={add} />
</span>
}
ghost
onClick={() => navigate('/books/management/add-edit')}
>
onClick={() => navigate('/books/management/add-edit')}>
添加
</Button>
)}
......@@ -495,76 +434,63 @@ const Audit = () => {
<Modal
mask={false}
centered
open={delMoadal}
open={delModal}
onOk={delSuccess}
onCancel={() => setDelModal(false)}
footer={(_, { OkBtn, CancelBtn }) => {
return (
<Row justify={'center'} className='delModal' style={{ marginBottom: '30px' }}>
<Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}>
<Space size={20}>
<CancelBtn className='cancel' />
<OkBtn className='true' />
<CancelBtn className="cancel" />
<OkBtn className="true" />
</Space>
</Row>
);
)
}}
okText='确认'
ghost
>
okText="确认"
ghost>
<p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>确认删除书籍?</p>
</Modal>
<Modal
mask={false}
centered
open={exportMoadal}
open={exportModal}
onOk={exportSuccess}
onCancel={() => setExportModal(false)}
footer={(_, { OkBtn, CancelBtn }) => {
return (
<Row justify={'center'} className='delModal' style={{ marginBottom: '30px' }}>
<Row justify={'center'} className="delModal" style={{ marginBottom: '30px' }}>
<Space size={20}>
<CancelBtn className='cancel' />
<OkBtn className='true' />
<CancelBtn className="cancel" />
<OkBtn className="true" />
</Space>
</Row>
);
)
}}
okText='确认'
>
<p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>
只能导出文本部分,画廊、音频、视频不支持
</p>
okText="确认">
<p style={{ textAlign: 'center', padding: '30px 0 18px', fontSize: 16 }}>只能导出文本部分,画廊、音频、视频不支持</p>
</Modal>
<Drawer
mask={false}
centered
open={importMoadal}
onCancel={() => setImportMoadal(false)}
onClose={() => setImportMoadal(false)}
footer={null}
okText='确认'
>
<Drawer mask={false} centered open={importModal} onCancel={() => setImportModal(false)} onClose={() => setImportModal(false)} footer={null} okText="确认">
<Spin spinning={uploading}>
<Form labelCol={{ span: 8 }} onFinish={importSuccess}>
<Form.Item label='下载模板' style={{ marginBottom: 10 }}>
<Button ghost type='primary' onClick={handleDownload}>
<Form.Item label="下载模板" style={{ marginBottom: 10 }}>
<Button ghost type="primary" onClick={handleDownload}>
下载模板
</Button>
</Form.Item>
<p
className='linetext'
className="linetext"
style={{
fontWeight: 400,
color: '#999999',
fontSize: 12,
marginBottom: 30,
paddingLeft: 75,
}}
>
paddingLeft: 75
}}>
目录需设置为word中的标题样式或按照示例编写,防止导入失败
</p>
<Form.Item label='选择书籍' required>
<Form.Item name='file' rules={[{ required: true, message: '请上传书籍' }]} noStyle>
<Form.Item label="选择书籍" required>
<Form.Item name="file" rules={[{ required: true, message: '请上传书籍' }]} noStyle>
<Upload {...UploadProps}>
<Button>点击上传</Button>
</Upload>
......@@ -572,12 +498,8 @@ const Audit = () => {
<p style={{ color: '#999999' }}>{bookFile?.name}</p>
</Form.Item>
<Form.Item
label='目录结构等级'
name='catalog_level'
rules={[{ required: true, message: '请选择目录结构等级' }]}
>
<Select placeholder='请选择目录结构的等级' style={{ width: 260 }}>
<Form.Item label="目录结构等级" name="catalog_level" rules={[{ required: true, message: '请选择目录结构等级' }]}>
<Select placeholder="请选择目录结构的等级" style={{ width: 260 }}>
<Select.Option value={1}>标题1</Select.Option>
<Select.Option value={2}>标题2</Select.Option>
<Select.Option value={3}>标题3</Select.Option>
......@@ -586,14 +508,10 @@ const Audit = () => {
</Select>
</Form.Item>
<Form.Item>
<Row
justify={'center'}
className='delModal'
style={{ marginBottom: '30px', marginTop: '0px' }}
>
<Row justify={'center'} className="delModal" style={{ marginBottom: '30px', marginTop: '0px' }}>
<Space size={20}>
<Button onClick={() => setImportMoadal(false)}>取消</Button>
<Button type='primary' htmlType='submit'>
<Button onClick={() => setImportModal(false)}>取消</Button>
<Button type="primary" htmlType="submit">
确认
</Button>
</Space>
......@@ -602,32 +520,27 @@ const Audit = () => {
</Form>
</Spin>
</Drawer>
<Drawer placement='right' onClose={() => setshowaudit(false)} open={showaudit} mask={false}>
<Drawer placement="right" onClose={() => setShowAudit(false)} open={showAudit} mask={false}>
<Form labelCol={{ span: 5 }} onFinish={handleReleaseExamine}>
<Form.Item
label='发布信息'
name='release_mess'
rules={[{ max: 255, message: '最大255字符' }]}
>
<Form.Item label="发布信息" name="release_mess" rules={[{ max: 255, message: '最大255字符' }]}>
<TextArea
placeholder='请输入发布信息'
placeholder="请输入发布信息"
autoSize={{
minRows: 5,
maxRows: 8,
maxRows: 8
}}
/>
</Form.Item>
<Form.Item wrapperCol={{ offset: 10, span: 16 }}>
<Space size={20}>
<Button
className='cancel'
className="cancel"
onClick={() => {
setshowaudit(false);
}}
>
setShowAudit(false)
}}>
取消
</Button>
<Button className='submit' htmlType='submit'>
<Button className="submit" htmlType="submit">
发布
</Button>
</Space>
......@@ -637,17 +550,9 @@ const Audit = () => {
<br />
{TableCom({ columns, loading, data })}
<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} />
</>
);
};
)
}
export default Audit;
export default Audit
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论