This commit is contained in:
caicai8 2020-03-19 16:10:42 +08:00
parent 78ba918514
commit 7dbcdd7b77
11 changed files with 207 additions and 76 deletions

View File

@ -25,7 +25,7 @@ class IndexItem extends Component{
<img className="p-r-photo" alt="" src={getImageUrl(`images/${item.author && item.author.image_url}`)} ></img>
<div className="p-r-Infos">
<div className="p-r-name">
<a onClick={()=>this.TurnToDetail(`${item.author && item.author.login}`,`/projects/${item.identifier}/coder`)} className="hide-1 font-16 color-grey-3" style={{whiteSpace:"wrap"}}>{item.name}</a>
<a onClick={()=>this.TurnToDetail(`${item.author && item.author.login}`,`/projects/${item.id}/coder`)} className="hide-1 font-16 color-grey-3" style={{whiteSpace:"wrap"}}>{item.name}</a>
</div>
<div className="p-r-content">
<p className="break_word task-hide flex1" style={{maxHeight:"40px"}}>{item.description}</p>

View File

@ -90,19 +90,14 @@ class Detail extends Component{
})
return;
}
let _html = '';
try {
_html = new QuillDeltaToHtmlConverter(quillValue.ops, {}).convert();
} catch (error) {
console.log(error);
}
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
const { data, page, limit, fileList } = this.state;
const url = `/issues/${data.id}/journals.json`;
axios.post(url,{
...values,
content:_html,
content:JSON.stringify(quillValue),
issue_id:data.id,
attachment_ids:fileList
}).then(result=>{
@ -313,10 +308,29 @@ class Detail extends Component{
}
}
handleShowImage=(value)=>{
console.log("imgOnclick",value);
}
commentCtx = (ctx) => {
let _ctx = null;
try {
_ctx = JSON.parse(ctx);
} catch (e) {
_ctx = ctx;
}
return (
<QuillForEditor
readOnly={true}
value={_ctx}
showUploadImage={this.handleShowImage}
/>
)
};
render(){
const { projectsId,orderId} = this.props.match.params;
const { data,journalsdata, page, limit, search_count, isSpin, isedit, showFiles , quillValue , quillFlag } = this.state;
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const Paginations = (
<React.Fragment>
@ -336,7 +350,7 @@ class Detail extends Component{
return(
<li key={key}>
<div className="df">
<Link to={``}><img className="user_img" src={getImageUrl(`images/${item.user_picture && item.user_picture}`)} alt=""/></Link>
<img className="user_img" src={getImageUrl(`images/${item.user_picture && item.user_picture}`)} alt=""/>
<div className="detail_context" >
<div className="topWrapper_detali">
<p className="ml6 detail_p lineH40">
@ -356,11 +370,8 @@ class Detail extends Component{
<div className="detail_ptitlecount">
<div style={{display: (isedit && isedit === item.id) ? "none" : "block"}} >
{
item.content ?
<QuillForEditor
readOnly={true}
value={item.content}
/>
item.content ?
this.commentCtx(item.content)
:
<div>
{this.renderJournalList(item.journal_details)}
@ -448,10 +459,11 @@ class Detail extends Component{
<Link to={``}><img className="user_img" src={getImageUrl(`images/${data && data.author_picture}`)} alt=""/></Link>
<div className="detail_context">
<div className="detail_p">
<QuillForEditor
{/* <QuillForEditor
readOnly={true}
value={ data && data.description}
/>
/> */}
{this.commentCtx(data && data.description)}
</div>
{
data && data.attachments && data.attachments.length > 0 ?
@ -473,11 +485,11 @@ class Detail extends Component{
{ Paginations }
<div className="df">
<Link to={``}><img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/></Link>
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/>
<div className="new_context">
<div className="quillContent">
<QuillForEditor
imgAttrs={{ width: '60px', height: '30px' }}
imgAttrs={{ width: '30px' }}
wrapStyle={{
height: '220px',
opacity:1,
@ -488,7 +500,7 @@ class Detail extends Component{
options={options}
value={quillValue}
onContentChange={this.onContentChange}
// showUploadImage={handleShowImage}
showUploadImage={this.handleShowImage}
// onContentChange={handleContentChange}
/>
<p className="quillFlag">

View File

@ -104,15 +104,10 @@ class New extends Component{
values.issue_tag_ids = [values.issue_tag_ids]
}
const { description } = this.state;
let _html = '';
try {
_html = new QuillDeltaToHtmlConverter(description.ops, {}).convert();
} catch (error) {
console.log(error);
}
axios.post(url,{
...values,
description:_html,
description:JSON.stringify(description),
attachment_ids:fileList
}).then(result=>{
if(result){

View File

@ -159,17 +159,12 @@ class UpdateDetail extends Component{
values.assigned_to_id = ""
}
const { textcount } = this.state;
let _html = '';
try {
_html = new QuillDeltaToHtmlConverter(textcount.ops, {}).convert();
} catch (error) {
console.log(error);
}
axios.put(url,{
project_id:projectsId,
subject:subject,
id: orderId,
description:_html,
description:JSON.stringify(textcount),
attachment_ids:fileList,
...values
}).then(result=>{

View File

@ -8,19 +8,15 @@
*/
import Quill from 'quill';
let Inline = Quill.import('blots/inline');
// const BlockEmbed = Quill.import('blots/embed');
class FillBlot extends Inline {
static create (value) {
static create(value) {
const node = super.cerate(value);
// node.classList.add('icon icon-bianji2');
// node.setAttribute('data-fill', 'fill');
console.log('编辑器值===》》》》》', value);
node.setAttribute('data_index', value.data_index);
node.nodeValue = value.text;
node.nodeValue = value.text;
return node;
}
static value (node) {
static value(node) {
return {
// dataSet: node.getAttribute('data-fill'),
data_index: node.getAttribute('data_index')

View File

@ -1,7 +1,7 @@
/*
* @Description: 重写图片
* @Author: tangjiang
* @Github:
* @Github:
* @Date: 2019-12-16 15:50:45
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-31 13:59:02
@ -17,10 +17,14 @@ export default class ImageBlot extends BlockEmbed {
const node = super.create();
node.setAttribute('alt', value.alt);
node.setAttribute('src', value.url);
// console.log('~~~~~~~~~~~', node, value);
console.log('~~~~~~~~~~~', node, value);
node.addEventListener('click', function () {
value.onclick(value.url);
}, false);
try {
value.onclick(value.url);
}catch (e) {
}
}, false);
if (value.width) {
node.setAttribute('width', value.width);
}
@ -33,7 +37,6 @@ export default class ImageBlot extends BlockEmbed {
}
// 宽度和高度都不存在时,
if (!value.width && !value.height) {
// node.setAttribute('display', 'block');
node.setAttribute('width', '100%');
}
@ -51,7 +54,7 @@ export default class ImageBlot extends BlockEmbed {
}
// 获取节点值
static value (node) {
static value(node) {
return {
alt: node.getAttribute('alt'),
@ -61,10 +64,9 @@ export default class ImageBlot extends BlockEmbed {
height: node.height,
display: node.getAttribute('display'),
id: node.id,
// style: node.style
};
}
}
ImageBlot.blotName = 'image';
ImageBlot.tagName = 'img';
ImageBlot.tagName = 'img';

View File

@ -0,0 +1,66 @@
@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;
}

View File

@ -11,6 +11,7 @@ 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';
@ -19,16 +20,17 @@ import { fetchUploadImage } from '../../services/ojService.js';
import { getImageUrl } from 'educoder'
import ImageBlot from './ImageBlot';
import FillBlot from './FillBlot';
const Size = Quill.import('attributors/style/size');
const Font = Quill.import('formats/font');
// const Color = Quill.import('attributes/style/color');
Size.whitelist = ['12px', '14px', '16px', '18px', '20px', false];
Font.whitelist = ['SimSun', 'SimHei','Microsoft-YaHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif'];
import LinkBlot from './link-blot'
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({
@ -37,7 +39,7 @@ Quill.register({
// Quill.register(Color);
function QuillForEditor ({
function QuillForEditor({
placeholder,
readOnly,
autoFocus = false,
@ -50,16 +52,16 @@ function QuillForEditor ({
onContentChange,
addFill, // 点击填空成功的回调
deleteFill // 删除填空,返回删除的下标
// getQuillContent
}) {
// toolbar 默认值
const defaultConfig = [
'bold', 'italic', 'underline',
{size: ['12px', '14px', '16px', '18px', '20px']},
{align: []}, {list: 'ordered'}, {list: 'bullet'}, // 列表
{script: 'sub'}, {script: 'super'},
{ size: ['14px', '16px', '18px', '20px'] },
{ align: [] }, { list: 'ordered' }, { list: 'bullet' }, // 列表
{ script: 'sub' }, { script: 'super' },
{ 'color': [] }, { 'background': [] },
{header: [1,2,3,4,5,false]},
{ 'font': [] },
{ header: [1, 2, 3, 4, 5, false] },
'blockquote', 'code-block',
'link', 'image', 'video',
'formula',
@ -75,7 +77,6 @@ function QuillForEditor ({
// 文本内容变化时
const handleOnChange = content => {
// getQuillContent && getQuillContent(quill);
onContentChange && onContentChange(content, quill);
};
@ -84,9 +85,7 @@ function QuillForEditor ({
const bindings = {
tab: {
key: 9,
handler: function () {
console.log('调用了tab=====>>>>');
}
handler: function () { }
},
backspace: {
key: 'Backspace',
@ -99,14 +98,13 @@ function QuillForEditor ({
*/
handler: function (range, context) {
/**
* index: 删除元素的位置
* index: 删除元素的位置
* length: 删除元素的个数
*/
const {index, length} = range;
const { index, length } = range;
const _start = length === 0 ? index - 1 : index;
const _length = length || 1;
let delCtx = this.quill.getText(_start, _length); // 删除的元素
// aa
const reg = /▁/g;
const delArrs = delCtx.match(reg);
if (delArrs) {
@ -123,7 +121,7 @@ function QuillForEditor ({
let delIndexs = [];
// 获取删除元素的下标
delArrs.forEach((item, i) => {
leaveLen === 0 ? delIndexs.push(i) : delIndexs.push(leaveLen + i);
leaveLen === 0 ? delIndexs.push(i) : delIndexs.push(leaveLen + i);
});
deleteFill && deleteFill(delIndexs); // 调用删除回调, 返回删除的元素下标[]
return true
@ -177,7 +175,7 @@ function QuillForEditor ({
const result = await fetchUploadImage(formData);
// 获取上传图片的url
if (result.data && result.data.id) {
fileUrl = getImageUrl(`api/attachments/${result.data.id}`);
fileUrl = (`http://123.59.135.93:56666/api/attachments/${result.data.id}`);
}
// 根据id获取文件路径
const { width, height } = imgAttrs;
@ -214,7 +212,7 @@ function QuillForEditor ({
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)});
item.insert['image'] = Object.assign({}, item.insert['image'], { style: { cursor: 'pointer' }, onclick: (url) => showUploadImage(url) });
}
});
}
@ -223,7 +221,7 @@ function QuillForEditor ({
if (!deepEqual(previous, current)) {
setSelection(quill.getSelection())
if (typeof value === 'string' && value) {
// debugger
// debugger
quill.clipboard.dangerouslyPasteHTML(value, 'api');
if (autoFocus) {
quill.focus();
@ -271,9 +269,9 @@ function QuillForEditor ({
// 返回结果
return (
<div className='quill_editor_for_react_area' style={wrapStyle}>
<div ref={editorRef} style={style}></div>
</div>
<div className='quill_editor_for_react_area' style={wrapStyle}>
<div ref={editorRef} style={style}></div>
</div>
);
}

View File

@ -0,0 +1,21 @@
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'

View File

@ -0,0 +1,18 @@
.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";
}

View File

@ -0,0 +1,28 @@
.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";
}