update
This commit is contained in:
parent
738d23ca9d
commit
d899c14bad
@ -3,6 +3,7 @@ import '@/App.less'
|
||||
import {BrowserRouter, Navigate, Route, Routes} from "react-router-dom";
|
||||
import TextPage from "./pages/quill/text.tsx";
|
||||
import WangEditor from "./pages/wang/wang-editor.tsx";
|
||||
import {Test} from "./pages/Test.tsx";
|
||||
|
||||
|
||||
function App() {
|
||||
@ -12,6 +13,7 @@ function App() {
|
||||
<Route path="/" element={<Navigate to="/wang"/>}/>
|
||||
<Route path="/proofread" element={<TextPage />}/>
|
||||
<Route path="/wang" element={<WangEditor />}/>
|
||||
<Route path="/test" element={<Test />}/>
|
||||
|
||||
</Routes>
|
||||
</BrowserRouter>)
|
||||
|
45
src/pages/Test.tsx
Normal file
45
src/pages/Test.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import React, {useRef} from "react";
|
||||
import {Button, message, Space} from "antd";
|
||||
|
||||
export const Test: React.FC = () => {
|
||||
const div = useRef<HTMLDivElement>(null)
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
|
||||
const selectSpan = (selector: string) => {
|
||||
return () => {
|
||||
if (!div.current) {
|
||||
return;
|
||||
}
|
||||
const span = div.current.querySelector(selector);
|
||||
if (!span) return;
|
||||
const sel = window.getSelection();
|
||||
sel?.selectAllChildren(span);
|
||||
}
|
||||
}
|
||||
const showSelection = async () => {
|
||||
const sel = window.getSelection();
|
||||
if (sel) {
|
||||
const str = sel.toString();
|
||||
messageApi.info(str || '没有选区')
|
||||
}
|
||||
}
|
||||
return (<div ref={div} style={{width: '90%', margin: 'auto'}}>
|
||||
{contextHolder}
|
||||
<div style={{padding: 15}}>
|
||||
<Space>
|
||||
<Button type="primary" onClick={selectSpan('.js')}>select js</Button>
|
||||
<Button type="primary" onClick={selectSpan('.cq')}>select cq</Button>
|
||||
<Button type="primary" onClick={showSelection}>get selection</Button>
|
||||
</Space>
|
||||
</div>
|
||||
<div className="container">
|
||||
<div className="ql-editor" data-gramm="false" contentEditable="true">
|
||||
<p className="ql-align-justify">最近不少江苏的网友反馈网站无法反馈,其中包括主页、论坛、图床、会员商城等均无法访问。</p>
|
||||
<p className="ql-align-justify">经过调查,是由于 <span className="js">江苏</span> 、<span
|
||||
className="cq">重庆</span> 两个地区的反诈系统将本站域名拦截。</p>
|
||||
<p className="ql-align-justify">我在访问其他服务器在境外的其他网站时,也看到有江苏用户反馈被拦截,看来江苏反诈最近是拦截了一大批网站,这是要开启白名单的节奏。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -24,7 +24,7 @@ export function withProofread<T extends IDomEditor>(editor: T) {
|
||||
* @param children 元素子节点,void 元素可忽略 @param _editor 编辑器实例
|
||||
* @returns 节点(通过 snabbdom.js 的 h 函数生成)
|
||||
*/
|
||||
export function renderProofread(data: SlateElement, children: VNode[] | null) { // , _editor: IDomEditor
|
||||
export function renderProofread(data: SlateElement, children: VNode[] | null, _editor: IDomEditor) { // , _editor: IDomEditor
|
||||
const {proofread} = data as WangEditorProofreadElement;
|
||||
return h(
|
||||
'span',
|
||||
@ -33,14 +33,34 @@ export function renderProofread(data: SlateElement, children: VNode[] | null) {
|
||||
dataSlateId: '123123'
|
||||
}, // HTML 属性,驼峰式写法
|
||||
attrs: {
|
||||
'data-proofread-id': String(proofread.id)
|
||||
'data-proofread-id': String(proofread.id),
|
||||
'data-proofread-text': proofread.origin
|
||||
},
|
||||
attachData: {
|
||||
proofread
|
||||
},
|
||||
className: `data-proofread-item data-proofread-item-${proofread.id}`,
|
||||
className: `data-proofread-item data-proofread-item-${proofread.id} data-proofread-type-${proofread.type}`,
|
||||
style: { /* 其他... */}, // style ,驼峰式写法 display: 'inline-block', margin: '0 2px',
|
||||
on: {
|
||||
process() {
|
||||
// const path = DomEditor.getSelectedElems(_editor)
|
||||
// DomEditor.findPath(_editor,span)
|
||||
const path = DomEditor.findPath(_editor, data);
|
||||
_editor.select(path)
|
||||
_editor.insertText(proofread.text)
|
||||
const span = this.elm as HTMLSpanElement;
|
||||
span.classList.add('proofread-processed')
|
||||
// if(proofread.type == 'delete'){
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//console.log('proofread process', data, this);
|
||||
//Transforms.select(_editor, this.elm)
|
||||
//window.getSelection()?.selectAllChildren(span);
|
||||
|
||||
//
|
||||
// SlateTransforms.
|
||||
},
|
||||
click(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
|
@ -21,12 +21,24 @@
|
||||
.data-proofread-item {
|
||||
border-bottom: solid 3px #f00;
|
||||
display: inline;
|
||||
margin: 0 5px;
|
||||
//margin: 0 5px;
|
||||
cursor: pointer;
|
||||
|
||||
&.data-proofread-type-delete {
|
||||
&::after {
|
||||
content: attr(data-proofread-text);
|
||||
text-decoration: line-through;
|
||||
display: none;
|
||||
}
|
||||
&.proofread-processed::after{
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.data-proofread-item-selected {
|
||||
background-color: #fbbbbb;
|
||||
//outline: solid 1px #fbbbbb;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
@ -75,6 +87,10 @@
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.insert-text {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin: 0 6px;
|
||||
position: relative;
|
||||
|
@ -7,7 +7,7 @@ import '@wangeditor/editor/dist/css/style.css'
|
||||
import './style.less'
|
||||
import {PROOFREAD_TYPE_DESC, WangEditorContent, WangEditorProofreadElement} from "../../types/editor.ts";
|
||||
import {useMount} from "ahooks";
|
||||
import {Button} from "antd";
|
||||
import {Button, Space} from "antd";
|
||||
import * as classNames from "classnames";
|
||||
import IconArrowRight from "../../components/icons/IconArrowRight.tsx";
|
||||
import IconCheckFill from "../../components/icons/IconCheckFill.tsx";
|
||||
@ -66,14 +66,26 @@ const defaultData: WangEditorContent[] = [
|
||||
type: 'proofread',
|
||||
proofread: {
|
||||
origin: '安徒声',
|
||||
text: '安徒生',
|
||||
type: 'words',
|
||||
text: '汉斯·克里斯汀·安徒生',
|
||||
type: 'words', // (汉斯·克里斯汀·安徒生,通称安徒生,丹麦作家暨诗人。)
|
||||
},
|
||||
children: [
|
||||
{"text": "安徒声"},
|
||||
]
|
||||
},
|
||||
{"text": "的作品。", "fontFamily": "宋体"}
|
||||
{"text": "的作品", "fontFamily": "宋体"},
|
||||
{
|
||||
type: 'proofread',
|
||||
proofread: {
|
||||
origin: '作品',
|
||||
text: '',
|
||||
type: 'delete'
|
||||
},
|
||||
children: [
|
||||
{"text": "作品"},
|
||||
]
|
||||
},
|
||||
{"text": "。", "fontFamily": "宋体"},
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -83,7 +95,18 @@ const defaultData: WangEditorContent[] = [
|
||||
"text": "故事里有一个愚蠢的笨国王。他罕少关心国家,一昧追求的就是衣着入时。",
|
||||
},
|
||||
{
|
||||
"text": "有一天,王国里来了俩个骗子。",
|
||||
type: 'proofread',
|
||||
proofread: {
|
||||
origin: '有天',
|
||||
text: '有一天',
|
||||
type: 'words'
|
||||
},
|
||||
children: [
|
||||
{"text": "有一天"},
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": ",王国里来了俩个骗子。",
|
||||
"fontFamily": "宋体"
|
||||
}
|
||||
]
|
||||
@ -117,6 +140,12 @@ const WangEditor: React.FC = () => {
|
||||
if (divRef.current) {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.classList.contains('data-proofread-item')) {
|
||||
const originNode = divRef.current.querySelector('.data-proofread-item-selected')
|
||||
if(originNode && originNode == target) return;
|
||||
originNode?.classList.remove('data-proofread-item-selected')
|
||||
if(target.classList.contains('proofread-processed')){
|
||||
return;
|
||||
}
|
||||
target.classList.add('data-proofread-item-selected')
|
||||
return;
|
||||
}
|
||||
@ -157,6 +186,20 @@ const WangEditor: React.FC = () => {
|
||||
if (span.classList.contains('data-proofread-item-selected')) return;
|
||||
document.querySelector(`.data-proofread-item-selected`)?.classList.remove('data-proofread-item-selected')
|
||||
span.classList.add('data-proofread-item-selected')
|
||||
|
||||
// const sel = window.getSelection();
|
||||
// window.getSelection()?.selectAllChildren(span);
|
||||
}
|
||||
}
|
||||
const proofreadProcess = (type: 'confirm' | 'cancel', index: number) => {
|
||||
return () => {
|
||||
const span = document.querySelector(`.data-proofread-item-${index}`)
|
||||
if (span && span.classList.contains('data-proofread-item-selected')) {
|
||||
const e = new Event('process');
|
||||
console.log(type)
|
||||
span.dispatchEvent(e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,10 +232,18 @@ const WangEditor: React.FC = () => {
|
||||
<div className="operation-wrapper">
|
||||
<div className="operation-container h-full">
|
||||
<div style={{margin: 10}}>
|
||||
<Button onClick={() => {
|
||||
const elems = editor?.getElemsByTypePrefix('header')
|
||||
console.log(elems)
|
||||
}}>获取所有目录</Button>
|
||||
<Space>
|
||||
<Button onClick={() => {
|
||||
const elems = editor?.getElemsByTypePrefix('header')
|
||||
console.log(elems)
|
||||
}}>获取所有目录</Button>
|
||||
<Button onClick={() => {
|
||||
setContent(editor?.children)
|
||||
console.log(
|
||||
editor?.getHtml()
|
||||
)
|
||||
}}>获取内容</Button>
|
||||
</Space>
|
||||
</div>
|
||||
{ops.map((op, key) => (<div
|
||||
className={classNames('operation-proofread-item', {selected: op.proofread.id == currentIndex})}
|
||||
@ -201,18 +252,29 @@ const WangEditor: React.FC = () => {
|
||||
>
|
||||
<div className="proofread-item-container">
|
||||
<div className="proofread-data">
|
||||
<span className="origin">{op.proofread.origin}</span>
|
||||
<span className="icon"><IconArrowRight/></span>
|
||||
<span className="text">{op.proofread.text}</span>
|
||||
{
|
||||
op.proofread.type == 'delete' ? <>
|
||||
<span className="origin"><del>{op.proofread.origin}</del></span>
|
||||
</> : (op.proofread.type == 'insert' ? <>
|
||||
<span className="origin insert"><del>{op.proofread.text}</del></span>
|
||||
<span className="insert-text">(新增)</span>
|
||||
</> : <>
|
||||
<span className="origin">{op.proofread.origin}</span>
|
||||
<span className="icon"><IconArrowRight/></span>
|
||||
<span className="text">{op.proofread.text}</span>
|
||||
</>)
|
||||
}
|
||||
</div>
|
||||
<div className="proofread-description">{op.proofread.description}</div>
|
||||
</div>
|
||||
<div className="proofread-action">
|
||||
<ProofreadPopover content={<span>选用</span>}>
|
||||
<IconCheckFill className="process"/>
|
||||
<IconCheckFill onClick={proofreadProcess('confirm', Number(op.proofread.id))}
|
||||
className="process"/>
|
||||
</ProofreadPopover>
|
||||
<ProofreadPopover content={<span>忽略</span>}>
|
||||
<IconCancelFill className="cancel"/>
|
||||
<IconCancelFill onClick={proofreadProcess('cancel', Number(op.proofread.id))}
|
||||
className="cancel"/>
|
||||
</ProofreadPopover>
|
||||
</div>
|
||||
</div>))}
|
||||
|
Loading…
x
Reference in New Issue
Block a user