forked from Gitlink/forgeplus-react
remove some thing
This commit is contained in:
parent
dda52a80c5
commit
0606cb4267
|
@ -489,7 +489,7 @@ class Detail extends Component{
|
|||
|
||||
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
|
||||
render={
|
||||
(props) => (<UpdateMerge {...this.props} {...props} {...this.state}/>)
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@ import axios from 'axios';
|
|||
import{ Form , Table , Spin } from 'antd'
|
||||
import { getImageUrl } from 'educoder';
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
|
||||
|
||||
class MergeSubmit extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
@ -30,13 +27,12 @@ class MergeSubmit extends Component{
|
|||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
// this.getDetail();
|
||||
const { data } = this.props;
|
||||
const { page , limit } = this.state;
|
||||
this.setState({
|
||||
isSpin:true
|
||||
})
|
||||
this.getCommitList( data.pull_request.base , page , limit );
|
||||
this.getCommitList( data && data.pull_request.base , page , limit );
|
||||
}
|
||||
|
||||
getDetail=()=>{
|
||||
|
@ -89,10 +85,7 @@ class MergeSubmit extends Component{
|
|||
|
||||
|
||||
render(){
|
||||
// const { projectsId,mergeId } = this.props.match.params;
|
||||
const { titledata } = this.state;
|
||||
|
||||
|
||||
const columns=[{
|
||||
title:"作者",
|
||||
dataIndex: 'name',
|
||||
|
@ -130,54 +123,11 @@ class MergeSubmit extends Component{
|
|||
return(
|
||||
<div className="f-wrap-between" style={{alignItems:"center"}}>
|
||||
<span className="font-16">提交列表</span>
|
||||
{/* <div className="f-wrap-alignCenter">
|
||||
<Input placeholder="搜索提交历史" style={{width:"300px"}}/>
|
||||
<Checkbox className="ml15">所有分支</Checkbox>
|
||||
<a className="btn_32 ml15">搜索</a>
|
||||
</div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// const url = this.props.history.location.pathname;
|
||||
return(
|
||||
// <div className="main">
|
||||
// <div className="topWrapper">
|
||||
// <Nav {...this.props} {...this.state}/>
|
||||
// <Link to={`/projects/${projectsId}/merge/new`} className="topWrapper_btn">创建合并请求</Link>
|
||||
// </div>
|
||||
// <div>
|
||||
// <div className="detailContent">
|
||||
// <p>
|
||||
// {
|
||||
// data ?
|
||||
// <span className="font-20">【{ data.issue.issue_classify==='issue'?data.issue.tracker:"合并"}】</span>
|
||||
// :
|
||||
// ""
|
||||
// }
|
||||
// <span className="font-20" > { data && data.issue.subject }</span>
|
||||
|
||||
// </p>
|
||||
// <p className="mt10 color-grey-c">
|
||||
// <span className={data&&data.issue.issue_status==="关闭"?"closedetail":data&&data.pull_request.status===0?"opendetail":"prdetail"}>{data&&data.issue.issue_status==="关闭"?"关闭中":data&&data.pull_request.status===0?"开启中":"已合并"} </span>
|
||||
// <span className="ml10 lineH32">
|
||||
// 由 { data && data.issue.author_name} 于 { data && data.issue.created_at }创建{ data && data.issue.journals_count && data.issue.journals_count > 0 ?` · ${data.issue.journals_count} 条评论`:""}
|
||||
// </span>
|
||||
// <span className="pull-right lineH32">
|
||||
// <Link to={`/projects/${projectsId}/merge/${mergeId}/UpdateMerge`} className="color-blue fr">编辑</Link>
|
||||
// </span>
|
||||
// </p>
|
||||
// </div>
|
||||
|
||||
|
||||
// <div className="detailHeader-wrapper">
|
||||
// <div className="normal f-wrap-between">
|
||||
// <ul className="headerMenu-wrapper" style={{paddingTop:42,paddingLeft:15}}>
|
||||
// <li className={url.indexOf("Messagecount")>0? "active" : ""}><Link to={`/projects/${projectsId}/merge/${mergeId}/Messagecount`}>对话内容</Link></li>
|
||||
// <li className={url.indexOf("MergeSubmit")>0 ? "active" : ""}><Link to={`/projects/${projectsId}/merge/${mergeId}/MergeSubmit`}>代码提交</Link></li>
|
||||
// </ul>
|
||||
// </div>
|
||||
// </div>
|
||||
<Spin spinning={this.state.isSpin}>
|
||||
<Table
|
||||
className="mt20 wrap-commit-table"
|
||||
|
|
|
@ -15,14 +15,6 @@ import RenderHtml from '../../components/render-html';
|
|||
const Option = Select.Option;
|
||||
const TextArea = Input.TextArea;
|
||||
|
||||
const options = [
|
||||
['bold', 'italic', 'underline'],
|
||||
[{header: [1,2,3,false]}],
|
||||
['blockquote', 'code-block'],
|
||||
['link', 'image'],
|
||||
['formula']
|
||||
];
|
||||
|
||||
class MessageCount extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
@ -63,6 +55,12 @@ class MessageCount extends Component{
|
|||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
const url = this.props.history.location.pathname;
|
||||
if(url.indexOf("updatemerge")>-1){
|
||||
this.setState({
|
||||
editMerge:true
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
SpinFlag:true
|
||||
})
|
||||
|
@ -646,7 +644,7 @@ class MessageCount extends Component{
|
|||
""
|
||||
}
|
||||
|
||||
<div className="">
|
||||
<div>
|
||||
<div className="normal f-wrap-between">
|
||||
<ul className="headerMenu-wrapper" style={{paddingTop:15,paddingLeft:15}}>
|
||||
<li className={url.indexOf("Messagecount")>0? "active" : ""}><Link to={`/projects/${projectsId}/merge/${mergeId}/Messagecount`} className="color-grey">对话内容</Link></li>
|
||||
|
@ -663,7 +661,7 @@ class MessageCount extends Component{
|
|||
|
||||
</div>
|
||||
{
|
||||
url.indexOf("Messagecount")>0 ?
|
||||
(url.indexOf("Messagecount") > 0 || url.indexOf("updatemerge") > 0) ?
|
||||
<Spin spinning={this.state.SpinFlag}>
|
||||
<div className="f-wrap-between mt20" style={{alignItems:"flex-start"}}>
|
||||
<div className="item-list-right" >
|
||||
|
@ -677,18 +675,16 @@ class MessageCount extends Component{
|
|||
<div className="new_context">
|
||||
{
|
||||
data && data.issue.issue_status !== "关闭" &&
|
||||
<div>
|
||||
<p>该合并请求可以进行自动合并操作</p>
|
||||
<p style={{marginTop:15,display:this.state.mergekey==='rebase'?this.state.buttonshow==='none'?"block":"none":this.state.ismesrge==='none'?"block":"none"}}>
|
||||
|
||||
<Dropdown.Button overlay={menu} type="primary" onClick={this.submitmerge} icon={<Icon type="caret-down"/>}>
|
||||
{this.state.mergename}
|
||||
</Dropdown.Button>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>该合并请求可以进行自动合并操作</p>
|
||||
<p style={{marginTop:15,display:this.state.mergekey==='rebase'?this.state.buttonshow==='none'?"block":"none":this.state.ismesrge==='none'?"block":"none"}}>
|
||||
|
||||
<Dropdown.Button overlay={menu} type="primary" onClick={this.submitmerge} icon={<Icon type="caret-down"/>}>
|
||||
{this.state.mergename}
|
||||
</Dropdown.Button>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div style={{display:this.state.ismesrge,marginTop:15}}>
|
||||
<Input placeholder="标题" value={this.state.title} onChange={this.changtitlepr}/>
|
||||
<TextArea placeholder="请输入合并描述..." style={{height:"170px",marginTop:20}} value={this.state.body} onChange={this.changbodypr} />
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* @Description: 填空
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-06 09:02:29
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-02-05 10:44:01
|
||||
*/
|
||||
import Quill from 'quill';
|
||||
let Inline = Quill.import('blots/inline');
|
||||
class FillBlot extends Inline {
|
||||
static create(value) {
|
||||
const node = super.cerate(value);
|
||||
node.setAttribute('data_index', value.data_index);
|
||||
node.nodeValue = value.text;
|
||||
return node;
|
||||
}
|
||||
|
||||
static value(node) {
|
||||
return {
|
||||
// dataSet: node.getAttribute('data-fill'),
|
||||
data_index: node.getAttribute('data_index')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FillBlot.blotName = "fill";
|
||||
FillBlot.tagName = "span";
|
||||
|
||||
export default FillBlot;
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* @Description: 重写图片
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-16 15:50:45
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2019-12-31 13:59:02
|
||||
*/
|
||||
import Quill from "quill";
|
||||
|
||||
const BlockEmbed = Quill.import('blots/block/embed');
|
||||
|
||||
export default class ImageBlot extends BlockEmbed {
|
||||
|
||||
static create(value) {
|
||||
|
||||
const node = super.create();
|
||||
node.setAttribute('alt', value.alt);
|
||||
node.setAttribute('src', value.url);
|
||||
console.log('~~~~~~~~~~~', node, value);
|
||||
node.addEventListener('click', function () {
|
||||
try {
|
||||
value.onclick(value.url);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}, false);
|
||||
if (value.width) {
|
||||
node.setAttribute('width', value.width);
|
||||
}
|
||||
if (value.height) {
|
||||
node.setAttribute('height', value.height);
|
||||
}
|
||||
|
||||
if (value.id) {
|
||||
node.setAttribute('id', value.id);
|
||||
}
|
||||
// 宽度和高度都不存在时,
|
||||
if (!value.width && !value.height) {
|
||||
node.setAttribute('width', '100%');
|
||||
}
|
||||
|
||||
// node.setAttribute('style', { cursor: 'pointer' });
|
||||
|
||||
// if (node.onclick) {
|
||||
// console.log('image 有图片点击事件======》》》》》》');
|
||||
// // node.setAttribute('onclick', node.onCLick);
|
||||
// }
|
||||
// 给图片添加点击事件
|
||||
// node.onclick = () => {
|
||||
// value.onClick && value.onClick(value.url);
|
||||
// }
|
||||
return node;
|
||||
}
|
||||
|
||||
// 获取节点值
|
||||
static value(node) {
|
||||
|
||||
return {
|
||||
alt: node.getAttribute('alt'),
|
||||
url: node.getAttribute('src'),
|
||||
onclick: node.onclick,
|
||||
width: node.width,
|
||||
height: node.height,
|
||||
display: node.getAttribute('display'),
|
||||
id: node.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ImageBlot.blotName = 'image';
|
||||
ImageBlot.tagName = 'img';
|
|
@ -1,95 +0,0 @@
|
|||
<!--
|
||||
* @Description:
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2020-01-06 16:20:03
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-01-09 09:45:29
|
||||
-->
|
||||
## QuillForEditor 使用 [https://quilljs.com/]
|
||||
|
||||
### 导入
|
||||
|
||||
- 目录 src/common/quillForEditor (默认加载当前文件夹下的 index.js 文件)
|
||||
|
||||
### 参数
|
||||
|
||||
| 字段 | 描述 |
|
||||
| ----- | ----- |
|
||||
| placeholder | 提示信息 |
|
||||
| readOnly | 只读(只读取模式时,没有 工具栏且内容不可编辑,通常用于展示quill内容) |
|
||||
| autoFocus | 自动获得焦点 |
|
||||
| options | 配置参数, 指定工具栏内容 |
|
||||
| value | 文本编辑器内容 |
|
||||
| imgAttrs | 指定上传图片的尺寸 { width: 'xxpx}, height: 'xxpx'|
|
||||
| style | 指定quill容器样式 |
|
||||
| wrapStyle | 指定包裹quill容器的样式|
|
||||
| onContentChange | 当编辑器内容变化时调用此回调函数(注: 此时返回的内容为对象,提交到后台时需要格式成 JSON 字符串: JSON.stringify(xx)) |
|
||||
| showUploadImage | 点击放大上传成功后的图片, 返回上传成功后的图片 url, (评论时点击图片这么大)|
|
||||
|
||||
|
||||
|
||||
### 添加工具栏
|
||||
|
||||
- 默认所有的
|
||||
|
||||
```
|
||||
const options = [
|
||||
'bold', // 加粗
|
||||
'italic', // 斜体
|
||||
'underline', // 下划线
|
||||
{size: ['12px', '14px', '16px', '18px', '20px']}, // 字体大小
|
||||
{align: []}, // 对齐方式
|
||||
{list: 'ordered'}, // 有序列表
|
||||
{list: 'bullet'}, // 无序列表
|
||||
{script: 'sub'}, // 下标 x2
|
||||
{script: 'super'}, // 上标 平方 (x2)
|
||||
{ 'color': [] }, // 字体颜色
|
||||
{ 'background': [] }, // 背景色
|
||||
{header: [1,2,3,4,5,false]}, // H1,H2 ...
|
||||
'blockquote', // 文件左边加一个边框样式
|
||||
'code-block', // 块内容
|
||||
'link', // 链接
|
||||
'image', // 图片
|
||||
'video', // 视频
|
||||
'formula', // 数学公式
|
||||
'clean' // 清除
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
### 使用
|
||||
|
||||
````
|
||||
编辑模式是放不大图片的
|
||||
import QuillForEditor from 'xxx';
|
||||
|
||||
// 指定需要显示的工具栏信息, 不指定加载全部
|
||||
const options = [
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* @description 获取编辑器返回的内容
|
||||
* @params [Object] value 编辑器内容
|
||||
*/
|
||||
const handleCtxChange = (value) => {
|
||||
// 编辑器内容非空判断
|
||||
const _text = quill.getText();
|
||||
const reg = /^[\s\S]*.*[^\s][\s\S]*$/;
|
||||
if (!reg.test(_text)) {
|
||||
// 处理编辑器内容为空
|
||||
} else {
|
||||
// 提交到后台的内容需要处理一下;
|
||||
value = JSON.stringify(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<QuillForEditor
|
||||
options={options}
|
||||
onContentChange={handleCtxChange}
|
||||
>
|
||||
</QuillForEditor>
|
||||
````
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
function deepEqual (prev, current) {
|
||||
if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!prev && current)
|
||||
|| (prev && !current)
|
||||
|| (!prev && !current)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(prev)) {
|
||||
if (!Array.isArray(current)) return false;
|
||||
if (prev.length !== current.length) return false;
|
||||
|
||||
for (let i = 0; i < prev.length; i++) {
|
||||
if (!deepEqual(current[i], prev[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof current === 'object') {
|
||||
if (typeof prev !== 'object') return false;
|
||||
const prevKeys = Object.keys(prev);
|
||||
const curKeys = Object.keys(current);
|
||||
|
||||
if (prevKeys.length !== curKeys.length) return false;
|
||||
|
||||
prevKeys.sort();
|
||||
curKeys.sort();
|
||||
|
||||
for (let i = 0; i < prevKeys.length; i++) {
|
||||
if (prevKeys[i] !== curKeys[i]) return false;
|
||||
const key = prevKeys[i];
|
||||
if (!deepEqual(prev[key], current[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export default deepEqual;
|
|
@ -1,66 +0,0 @@
|
|||
@charset "utf-8";
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
|
||||
content: "宋体";
|
||||
font-family:SimSun !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
|
||||
content: "黑体";
|
||||
font-family:SimHei !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
|
||||
content: "微软雅黑";
|
||||
font-family:Microsoft YaHei !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
|
||||
content: "楷体";
|
||||
font-family:KaiTi !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
|
||||
content: "仿宋";
|
||||
font-family:FangSong !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
|
||||
content: "Arial";
|
||||
font-family:Arial !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
|
||||
content: "Times New Roman";
|
||||
font-family:Times New Roman !important;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
|
||||
content: "sans-serif";
|
||||
font-family:sans-serif !important;
|
||||
}
|
||||
|
||||
.ql-font-SimSun {
|
||||
font-family:SimSun !important;
|
||||
}
|
||||
.ql-font-SimHei {
|
||||
font-family:SimHei !important;
|
||||
}
|
||||
.ql-font-Microsoft-YaHei {
|
||||
font-family:Microsoft YaHei !important;
|
||||
}
|
||||
.ql-font-KaiTi {
|
||||
font-family:KaiTi !important;
|
||||
}
|
||||
.ql-font-FangSong {
|
||||
font-family:FangSong !important;
|
||||
}
|
||||
.ql-font-Arial {
|
||||
font-family:Arial !important;
|
||||
}
|
||||
.ql-font-Times-New-Roman {
|
||||
font-family:Times New Roman !important;
|
||||
}
|
||||
.ql-font-sans-serif {
|
||||
font-family:sans-serif !important;
|
||||
}
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* @Description: quill 编辑器
|
||||
* @Author: tangjiang
|
||||
* @Github:
|
||||
* @Date: 2019-12-18 08:49:30
|
||||
* @LastEditors : tangjiang
|
||||
* @LastEditTime : 2020-02-05 11:23:03
|
||||
*/
|
||||
import './index.scss';
|
||||
import 'quill/dist/quill.core.css'; // 核心样式
|
||||
import 'quill/dist/quill.snow.css'; // 有工具栏
|
||||
import 'quill/dist/quill.bubble.css'; // 无工具栏
|
||||
import 'katex/dist/katex.min.css'; // katex 表达式样式
|
||||
import './font.css'
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import Quill from 'quill';
|
||||
import katex from 'katex';
|
||||
import deepEqual from './deepEqual.js'
|
||||
import { fetchUploadImage } from '../../services/ojService.js';
|
||||
import ImageBlot from './ImageBlot';
|
||||
import FillBlot from './FillBlot';
|
||||
import LinkBlot from './link-blot';
|
||||
import { getImageUrl } from 'educoder';
|
||||
var Size = Quill.import('attributors/style/size');
|
||||
Size.whitelist = ['14px', '16px', '18px', '20px', false];
|
||||
var fonts = ['Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong'];
|
||||
var Font = Quill.import('formats/font');
|
||||
Font.whitelist = fonts; //将字体加入到白名单
|
||||
window.Quill = Quill;
|
||||
window.katex = katex;
|
||||
Quill.register(ImageBlot);
|
||||
Quill.register(Size);
|
||||
Quill.register(LinkBlot);
|
||||
Quill.register(Font, true);
|
||||
// Quill.register({'modules/toolbar': Toolbar});
|
||||
Quill.register({
|
||||
'formats/fill': FillBlot
|
||||
});
|
||||
// Quill.register(Color);
|
||||
|
||||
|
||||
function QuillForEditor({
|
||||
placeholder,
|
||||
readOnly,
|
||||
autoFocus = false,
|
||||
options,
|
||||
value,
|
||||
imgAttrs = {}, // 指定图片的宽高
|
||||
style = {},
|
||||
wrapStyle = {},
|
||||
showUploadImage,
|
||||
onContentChange,
|
||||
addFill, // 点击填空成功的回调
|
||||
deleteFill // 删除填空,返回删除的下标
|
||||
}) {
|
||||
// toolbar 默认值
|
||||
const defaultConfig = [
|
||||
'bold', 'italic', 'underline',
|
||||
{ size: ['14px', '16px', '18px', '20px'] },
|
||||
{ align: [] }, { list: 'ordered' }, { list: 'bullet' }, // 列表
|
||||
{ script: 'sub' }, { script: 'super' },
|
||||
{ 'color': [] }, { 'background': [] },
|
||||
{ 'font': [] },
|
||||
{ header: [1, 2, 3, 4, 5, false] },
|
||||
'blockquote', 'code-block',
|
||||
'link', 'image', 'video',
|
||||
'formula',
|
||||
'clean'
|
||||
];
|
||||
|
||||
const editorRef = useRef(null);
|
||||
// quill 实例
|
||||
const [quill, setQuill] = useState(null);
|
||||
const [selection, setSelection] = useState(null);
|
||||
const [fillCount, setFillCount] = useState(0);
|
||||
const [quillCtx, setQuillCtx] = useState({});
|
||||
|
||||
// 文本内容变化时
|
||||
const handleOnChange = content => {
|
||||
onContentChange && onContentChange(content, quill);
|
||||
};
|
||||
|
||||
const renderOptions = options || defaultConfig;
|
||||
|
||||
const bindings = {
|
||||
tab: {
|
||||
key: 9,
|
||||
handler: function () { }
|
||||
},
|
||||
backspace: {
|
||||
key: 'Backspace',
|
||||
/**
|
||||
* @param {*} range
|
||||
* { index, // 删除元素的位置
|
||||
* length // 删除元素的个数, 当删除一个时, length=0, 其它等于删除的元素的个数
|
||||
* }
|
||||
* @param {*} context 上下文
|
||||
*/
|
||||
handler: function (range, context) {
|
||||
/**
|
||||
* index: 删除元素的位置
|
||||
* length: 删除元素的个数
|
||||
*/
|
||||
const { index, length } = range;
|
||||
const _start = length === 0 ? index - 1 : index;
|
||||
const _length = length || 1;
|
||||
let delCtx = this.quill.getText(_start, _length); // 删除的元素
|
||||
const reg = /▁/g;
|
||||
const delArrs = delCtx.match(reg);
|
||||
if (delArrs) {
|
||||
const r = window.confirm('确定要删除吗?');
|
||||
if (r) {
|
||||
let leaveCtx; // 获取删除元素之前的内容
|
||||
if (length === 0) {
|
||||
leaveCtx = this.quill.getText(0, index - 1);
|
||||
} else {
|
||||
leaveCtx = this.quill.getText(0, index);
|
||||
}
|
||||
const leaveArrs = leaveCtx.match(reg);
|
||||
const leaveLen = (leaveArrs || []).length;
|
||||
let delIndexs = [];
|
||||
// 获取删除元素的下标
|
||||
delArrs.forEach((item, i) => {
|
||||
leaveLen === 0 ? delIndexs.push(i) : delIndexs.push(leaveLen + i);
|
||||
});
|
||||
deleteFill && deleteFill(delIndexs); // 调用删除回调, 返回删除的元素下标[]
|
||||
return true
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
// quill 配置信息
|
||||
const quillOption = {
|
||||
modules: {
|
||||
toolbar: renderOptions,
|
||||
keyboard: {
|
||||
bindings: bindings
|
||||
}
|
||||
// toolbar: {
|
||||
// container: renderOptions
|
||||
// }
|
||||
},
|
||||
readOnly,
|
||||
placeholder,
|
||||
theme: readOnly ? 'bubble' : 'snow',
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const quillNode = document.createElement('div');
|
||||
editorRef.current.appendChild(quillNode);
|
||||
const _quill = new Quill(editorRef.current, quillOption);
|
||||
|
||||
setQuill(_quill);
|
||||
// 处理图片上传功能
|
||||
_quill.getModule('toolbar').addHandler('image', (e) => {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('accept', 'image/*');
|
||||
input.click();
|
||||
|
||||
input.onchange = async (e) => {
|
||||
const file = input.files[0]; // 获取文件信息
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
const range = _quill.getSelection(true);
|
||||
let fileUrl = ''; // 保存上传成功后图片的url
|
||||
// 上传文件
|
||||
const result = await fetchUploadImage(formData);
|
||||
// 获取上传图片的url
|
||||
if (result.data && result.data.id) {
|
||||
fileUrl = (getImageUrl(`api/attachments/${result.data.id}`));
|
||||
}
|
||||
// 根据id获取文件路径
|
||||
const { width, height } = imgAttrs;
|
||||
// console.log('上传图片的url:', fileUrl);
|
||||
if (fileUrl) {
|
||||
_quill.insertEmbed(range.index, 'image', {
|
||||
url: fileUrl,
|
||||
alt: '图片信息',
|
||||
onClick: showUploadImage,
|
||||
width,
|
||||
height
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// 处理填空
|
||||
_quill.getModule('toolbar').addHandler('fill', (e) => {
|
||||
// alert(1111);
|
||||
setFillCount(fillCount + 1);
|
||||
const range = _quill.getSelection(true);
|
||||
_quill.insertText(range.index, '▁');
|
||||
addFill && addFill(); // 调用添加回调
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 设置值
|
||||
useEffect(() => {
|
||||
if (!quill) return
|
||||
|
||||
const previous = quill.getContents()
|
||||
|
||||
if (value && value.hasOwnProperty('ops')) {
|
||||
const ops = value.ops || [];
|
||||
ops.forEach((item, i) => {
|
||||
if (item.insert['image']) {
|
||||
item.insert['image'] = Object.assign({}, item.insert['image'], { style: { cursor: 'pointer' }, onclick: (url) => showUploadImage(url) });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const current = value
|
||||
if (!deepEqual(previous, current)) {
|
||||
setSelection(quill.getSelection())
|
||||
if (typeof value === 'string' && value) {
|
||||
// debugger
|
||||
quill.clipboard.dangerouslyPasteHTML(value, 'api');
|
||||
if (autoFocus) {
|
||||
quill.focus();
|
||||
} else {
|
||||
quill.blur();
|
||||
}
|
||||
} else {
|
||||
quill.setContents(value)
|
||||
if (autoFocus) quill.focus();
|
||||
}
|
||||
}
|
||||
}, [quill, value, setQuill, autoFocus]);
|
||||
|
||||
// 清除选择区域
|
||||
useEffect(() => {
|
||||
if (quill && selection) {
|
||||
quill.setSelection(selection)
|
||||
setSelection(null)
|
||||
}
|
||||
}, [quill, selection, setSelection]);
|
||||
|
||||
// 设置placeholder值
|
||||
useEffect(() => {
|
||||
if (!quill || !quill.root) return;
|
||||
quill.root.dataset.placeholder = placeholder;
|
||||
}, [quill, placeholder]);
|
||||
|
||||
// 处理内容变化
|
||||
useEffect(() => {
|
||||
if (!quill) return;
|
||||
if (typeof handleOnChange !== 'function') return;
|
||||
let handler;
|
||||
quill.on(
|
||||
'text-change',
|
||||
(handler = (delta, oldDelta, source) => {
|
||||
const _ctx = quill.getContents();
|
||||
setQuillCtx(_ctx);
|
||||
handleOnChange(quill.getContents()); // getContents: 检索编辑器内容
|
||||
})
|
||||
);
|
||||
return () => {
|
||||
quill.off('text-change', handler);
|
||||
}
|
||||
}, [quill, handleOnChange]);
|
||||
|
||||
// 返回结果
|
||||
return (
|
||||
<div className='quill_editor_for_react_area' style={wrapStyle}>
|
||||
<div ref={editorRef} style={style}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default QuillForEditor;
|
|
@ -1,132 +0,0 @@
|
|||
.quill_editor_for_react_area{
|
||||
// background: #fff;
|
||||
// margin: 0 15px;
|
||||
.ql-editing{
|
||||
left: 0 !important;
|
||||
}
|
||||
.ql-editor{
|
||||
img{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
|
||||
content: '12px';
|
||||
font-size: 12px;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
|
||||
content: '14px';
|
||||
font-size: 14px;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
|
||||
content: '16px';
|
||||
font-size: 16px;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
|
||||
content: '18px';
|
||||
font-size: 18px;
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
|
||||
content: '20px';
|
||||
font-size: 20px;
|
||||
}
|
||||
//默认的样式
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: '14px';
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
|
||||
content: "宋体";
|
||||
font-family: "SimSun";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
|
||||
content: "黑体";
|
||||
font-family: "SimHei";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
|
||||
content: "微软雅黑";
|
||||
font-family: "Microsoft YaHei";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
|
||||
content: "楷体";
|
||||
font-family: "KaiTi";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
|
||||
content: "仿宋";
|
||||
font-family: "FangSong";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
|
||||
content: "Arial";
|
||||
font-family: "Arial";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
|
||||
content: "Times New Roman";
|
||||
font-family: "Times New Roman";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
|
||||
content: "sans-serif";
|
||||
font-family: "sans-serif";
|
||||
}
|
||||
|
||||
.ql-font-SimSun {
|
||||
font-family: "SimSun";
|
||||
}
|
||||
.ql-font-SimHei {
|
||||
font-family: "SimHei";
|
||||
}
|
||||
.ql-font-Microsoft-YaHei {
|
||||
font-family: "Microsoft YaHei";
|
||||
}
|
||||
.ql-font-KaiTi {
|
||||
font-family: "KaiTi";
|
||||
}
|
||||
.ql-font-FangSong {
|
||||
font-family: "FangSong";
|
||||
}
|
||||
.ql-font-Arial {
|
||||
font-family: "Arial";
|
||||
}
|
||||
.ql-font-Times-New-Roman {
|
||||
font-family: "Times New Roman";
|
||||
}
|
||||
.ql-font-sans-serif {
|
||||
font-family: "sans-serif";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "微软雅黑";
|
||||
font-family: "Microsoft YaHei";
|
||||
}
|
||||
|
||||
// 填空图标
|
||||
.ql-snow .ql-fill{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: #05101A;
|
||||
// font-size: 18px;
|
||||
vertical-align: top;
|
||||
&::before{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -1px;
|
||||
content: '\e709';
|
||||
font-family: 'iconfont';
|
||||
margin-left: -7px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import Quill from "quill";
|
||||
const Inline = Quill.import('blots/inline');
|
||||
|
||||
export default class LinkBlot extends Inline {
|
||||
static create(value) {
|
||||
let node = super.create()
|
||||
let rs = value
|
||||
if (rs.indexOf('http://') < 0) {
|
||||
rs = 'http://' + rs
|
||||
}
|
||||
node.setAttribute('href', rs)
|
||||
node.setAttribute('target', '_blank')
|
||||
return node;
|
||||
}
|
||||
|
||||
static formats(node) {
|
||||
return node.getAttribute('href');
|
||||
}
|
||||
}
|
||||
LinkBlot.blotName = 'link'
|
||||
LinkBlot.tagName = 'a'
|
|
@ -1,18 +0,0 @@
|
|||
.ql-editor .ql-font-Microsoft-YaHei {
|
||||
font-family: "Microsoft YaHei";
|
||||
}
|
||||
.ql-editor .ql-font-SimSun {
|
||||
font-family: "SimSun";
|
||||
}
|
||||
.ql-editor .ql-font-SimHei {
|
||||
font-family: "SimHei";
|
||||
}
|
||||
.ql-editor .ql-font-KaiTi {
|
||||
font-family: "KaiTi";
|
||||
}
|
||||
.ql-editor .ql-font-Arial {
|
||||
font-family: "Arial";
|
||||
}
|
||||
.ql-editor .Times-New-Roman {
|
||||
font-family: "Times New Roman";
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: '微软雅黑';
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
|
||||
content: "微软雅黑";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
|
||||
content: "宋体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
|
||||
content: "黑体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
|
||||
content: "楷体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
|
||||
content: "Arial";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
|
||||
content: "Times New Roman";
|
||||
}
|
|
@ -661,15 +661,6 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
{...this.state}
|
||||
{...this.dialogObj}
|
||||
/> : ""}
|
||||
{
|
||||
mypath && mypath === "/problemset" ?
|
||||
""
|
||||
:
|
||||
<SiderBar
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
Headertop={Headertop} />
|
||||
}
|
||||
|
||||
<style>{
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue