370 lines
11 KiB
JavaScript
370 lines
11 KiB
JavaScript
import React, { useEffect, useCallback, useState } from 'react';
|
||
import { Button, Checkbox, Form, Icon, Radio, Input, message } from 'antd';
|
||
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
|
||
import DelModal from './components/ModalFun';
|
||
import { weekModal, monthModal } from './components/config';
|
||
import { getWiki, wikiPages, addWiki, updateWiki, markdownToTree, treeToMd } from './api';
|
||
import './Index.scss';
|
||
import { Base64 } from 'js-base64';
|
||
|
||
|
||
export default Form.create()(({ form, history, showNotification, projectDetail, match, project }) => {
|
||
const {location:{pathname, search}} = history;
|
||
const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter";
|
||
|
||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||
let projectsId = match.params.projectsId;
|
||
let owner = match.params.owner;
|
||
let wikiName = ''
|
||
let key = '';
|
||
if (!pathname.endsWith('/wiki/add')) {
|
||
wikiName = pathname.split('/')[4];
|
||
key = pathname.split('/')[5];
|
||
}else{
|
||
key = search.split('=').pop();
|
||
}
|
||
|
||
const [fileArrInit, setFileArrInit] = useState(null);
|
||
const [content, setContent] = useState("欢迎来到Wiki");
|
||
const [modal, setModal] = useState(false);
|
||
const [operateFlag, setOperateFlag ] = useState(false);
|
||
const [modalType, setModalType] = useState();
|
||
const [sidebar, setSidebar] = useState(undefined);
|
||
const [menuList, setMenuList] = useState(undefined);
|
||
|
||
useEffect(()=>{
|
||
if(projectDetail){
|
||
const { author, name} = projectDetail;
|
||
if(wikiName){
|
||
document.title = `编辑${wikiName}-维基-${author.name}/${name}`;
|
||
}else{
|
||
document.title = `新建维基-${author.name}/${name}`;
|
||
}
|
||
}
|
||
}, [projectDetail, wikiName])
|
||
|
||
useEffect(() => {
|
||
wikiName && project && getWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
pageName: wikiName,
|
||
projectId: project.id
|
||
}).then(res => {
|
||
if (res && res.data) {
|
||
const content = Base64.decode(res.data.md_content);
|
||
setContent(content);
|
||
setFieldsValue({
|
||
title: search === "?copy" ? `${res.data.name}(复制)` : res.data.name,
|
||
md_content: content,
|
||
});
|
||
}
|
||
});
|
||
}, [owner, wikiName]);
|
||
|
||
// 加载wiki列表
|
||
useEffect(() => {
|
||
project && wikiPages({
|
||
owner: owner,
|
||
repo: projectsId,
|
||
projectId: project.id
|
||
}).then(res => {
|
||
if (res && res.message === "200" && Array.isArray(res.data)) {
|
||
setFileArrInit(res.data);
|
||
// 仓库存在没有创建过wiki的情况
|
||
if(res.data.length){
|
||
// 获取sidebar文件内容
|
||
getWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
pageName: '_Sidebar',
|
||
projectId: project.id
|
||
}).then(res => {
|
||
if (res && res.data) {
|
||
const sidebarDecode = Base64.decode(res.data.md_content);
|
||
setSidebar(sidebarDecode);
|
||
key && setMenuList(markdownToTree(sidebarDecode))
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
setFileArrInit([]);
|
||
}
|
||
});
|
||
}, [project]);
|
||
|
||
const helper = useCallback(
|
||
(label, name, rules, widget, initialValue, rightComponent) => (
|
||
<Form.Item label={label} className="mb0">
|
||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||
{rightComponent}
|
||
</Form.Item>
|
||
), []);
|
||
|
||
|
||
function onContentChange(value) {
|
||
setContent(value);
|
||
setFieldsValue({
|
||
md_content: value
|
||
});
|
||
};
|
||
|
||
// 保存wiki文件,包括新增和修改
|
||
function saveFile() {
|
||
if(operateFlag) {
|
||
setOperateFlag(true);
|
||
return;
|
||
};
|
||
validateFields((err, values) => {
|
||
if (!err) {
|
||
const {md_content, title} = values;
|
||
if (wikiName && search!== "?copy") {
|
||
updateWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
projectId: project.id,
|
||
pageName: wikiName,
|
||
title,
|
||
message: '',
|
||
content_base64: Base64.encode(md_content)
|
||
}).then(res => dealRes(res, title));
|
||
} else {
|
||
// 由于wiki在底层是由wikiname标识的md文件,所以对于所有的页面,都不能重名
|
||
if (Array.isArray(fileArrInit)) {
|
||
for (const item of fileArrInit) {
|
||
if (item.name === title) {
|
||
message.error('不能与已有文件标题相同');
|
||
setOperateFlag(false);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
addWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
projectId: project.id,
|
||
pageName: title,
|
||
title,
|
||
message: '',
|
||
content_base64: Base64.encode(md_content)
|
||
}).then(res => dealRes(res, title));
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
function dealRes(res, title) {
|
||
if (res && (res.message === "201" || res.message === "200")) {
|
||
if(wikiName && search!== "?copy"){
|
||
// 如果有更改wiki文件名,则修改sidebar
|
||
if(wikiName === title){
|
||
message.success("操作成功");
|
||
goBack();
|
||
}else{
|
||
// 找到相同的key值node修改title参数,再保存sidebar
|
||
const newMenuList = menuList;
|
||
editTitleByKey(newMenuList, key, title);
|
||
updateSidebar(treeToMd(newMenuList), title);
|
||
}
|
||
}else{
|
||
// 根据路由判断是新增的一级页面还是子页面
|
||
if(search === "?copy"){
|
||
// 截断key的前几位,获取父元素的key值
|
||
const keyArr = key.split('-');
|
||
keyArr.pop();
|
||
const list = menuList;
|
||
addChildrenByKey(list, keyArr.join('-'), title);
|
||
updateSidebar(treeToMd(list), title);
|
||
}else if(search.includes("?key")){
|
||
// 遍历menuList找到相同key的节点,children push[[页面]]
|
||
const list = menuList;
|
||
addChildrenByKey(list, key, title);
|
||
updateSidebar(treeToMd(list), title);
|
||
}else{
|
||
if(fileArrInit.length){
|
||
updateSidebar(`${sidebar}\n[[${title}]]`, title);
|
||
}else{
|
||
// 仓库第一次创建wiki文件
|
||
addWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
projectId: project.id,
|
||
pageName: "_Sidebar",
|
||
title: "_Sidebar",
|
||
message: '',
|
||
content_base64: Base64.encode(`[[${title}]]`)
|
||
}).then(res => {
|
||
if(res && res.message === "201"){
|
||
message.success("操作成功");
|
||
goBack();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
} else if (res && res.message === "500") {
|
||
setOperateFlag(false);
|
||
message.error('请检查格式是否正确或文件名是否重复');
|
||
} else {
|
||
setOperateFlag(false);
|
||
showNotification(res.data || "操作失败");
|
||
}
|
||
}
|
||
|
||
function updateSidebar(content, newTitle){
|
||
updateWiki({
|
||
owner,
|
||
repo: projectsId,
|
||
projectId: project.id,
|
||
pageName: '_Sidebar',
|
||
title: '_Sidebar',
|
||
message: '',
|
||
content_base64: Base64.encode(content)
|
||
}).then(res => {
|
||
if (res && res.message === "200") {
|
||
message.success("操作成功");
|
||
if(newTitle){
|
||
// 用户修改了wiki名称
|
||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(newTitle)}/${key}`)
|
||
return;
|
||
}
|
||
goBack();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 递归menuList, 找到相同key值修改title名称
|
||
function editTitleByKey(list, key, newTitle){
|
||
for (let index = 0; index < list.length; index++) {
|
||
const element = list[index];
|
||
if (element.key == key) {
|
||
const {title} = element;
|
||
element.title = `${title.substring(0, title.indexOf('[['))}[[${newTitle}]]`;
|
||
return true;
|
||
}else if (element.children.length) {
|
||
let result = editTitleByKey(element.children, key, newTitle);
|
||
if (result) {
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 递归menuList 创建子页面
|
||
function addChildrenByKey(list, key, name){
|
||
for (let index = 0; index < list.length; index++) {
|
||
const element = list[index];
|
||
if (element.key == key) {
|
||
const {title} = element;
|
||
element.children.push({
|
||
title: `\t${title.substring(0, title.indexOf('- '))}[[${name}]]`,
|
||
children: []
|
||
});
|
||
return true;
|
||
}else if (element.children.length) {
|
||
let result = addChildrenByKey(element.children, key, name);
|
||
if (result) {
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function goBack() {
|
||
history.go(-1);
|
||
}
|
||
|
||
function changeModal(e) {
|
||
setModal(e.target.checked);
|
||
if (!e.target.checked) {
|
||
setModalType();
|
||
}
|
||
}
|
||
|
||
function changeModalType(e) {
|
||
let value = e.target.value;
|
||
if (!content) {
|
||
setModalContent(value);
|
||
return;
|
||
}
|
||
DelModal({
|
||
title: '添加模版',
|
||
contentTitle: `您确定要添加“${value}”模板吗`,
|
||
content: `此操作会将“${value}”模板替换编辑栏内所有内容,请确认以防文件的丢失`,
|
||
okText: '确认添加',
|
||
onOk: () => {
|
||
setModalType(value);
|
||
setModal(true);
|
||
setModalContent(value);
|
||
}
|
||
});
|
||
}
|
||
|
||
function setModalContent(value) {
|
||
if (value === '周报') {
|
||
setContent(weekModal);
|
||
setFieldsValue({
|
||
md_content: weekModal
|
||
});
|
||
} else if (value === '月报') {
|
||
setContent(monthModal);
|
||
setFieldsValue({
|
||
md_content: monthModal
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
return (
|
||
<div className="wiki-main">
|
||
<div className="wiki-head">
|
||
<span className="head-title"><span className="back-wiki" onClick={goBack}>Wiki</span> <Icon type="right" /> {wikiName ? search === "?copy" ? '复制' : '编辑' : '新增'}页面</span>
|
||
</div>
|
||
|
||
<div >
|
||
<h4 className="mt20 mb0">标题</h4>
|
||
{helper(
|
||
"",
|
||
"title",
|
||
[
|
||
{ required: true, message: "请输入标题" },
|
||
{ pattern: /^(?!-).*$/, message: '不能以-开头' }
|
||
],
|
||
<Input
|
||
placeholder={"请输入标题"}
|
||
className="contact-input"
|
||
maxLength={50}
|
||
autoFocus
|
||
/>
|
||
)}
|
||
|
||
<Form.Item className="mb0 wiki-md">
|
||
<MDEditor
|
||
placeholder={"请输入wiki内容"}
|
||
height={500}
|
||
mdID={"order-new-description"}
|
||
initValue={content}
|
||
onChange={onContentChange}
|
||
className="mt20 wikiMEDEditor"
|
||
isFocus={false}
|
||
></MDEditor>
|
||
{getFieldDecorator('md_content', {
|
||
rules: [{ required: true, message: "请输入wiki内容" }],
|
||
validateFirst: true,
|
||
initialValue: "欢迎来到Wiki"
|
||
})(<Input style={{ display: 'none' }} />)}
|
||
</Form.Item>
|
||
|
||
<Checkbox checked={modal} onChange={changeModal} className='mt10'>添加模版</Checkbox>
|
||
|
||
<Radio.Group onChange={changeModalType} value={modalType}>
|
||
<Radio value='周报'>周报</Radio>
|
||
<Radio value='月报'>月报</Radio>
|
||
</Radio.Group>
|
||
|
||
</div>
|
||
|
||
{permission && <Button className="mt25" type="primary" onClick={saveFile}>保存</Button>}
|
||
</div>
|
||
|
||
)
|
||
}) |