Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wisdom-components
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
wisdom-components
Commits
61b4010f
Commit
61b4010f
authored
2 years ago
by
周宏民
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 删除rich
parent
69baad94
Pipeline
#53959
failed with stages
in 4 seconds
Changes
14
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
0 additions
and
1229 deletions
+0
-1229
CHANGELOG.md
packages/base-components/rich/CHANGELOG.md
+0
-27
README.md
packages/base-components/rich/README.md
+0
-11
rich.test.js
packages/base-components/rich/__tests__/rich.test.js
+0
-7
package.json
packages/base-components/rich/package.json
+0
-36
RichTextShow.js
packages/base-components/rich/src/RichTextShow.js
+0
-75
Basic.tsx
packages/base-components/rich/src/demos/Basic.tsx
+0
-69
demo.jsx
packages/base-components/rich/src/demos/demo.jsx
+0
-93
demo.less
packages/base-components/rich/src/demos/demo.less
+0
-18
fileListItem.js
packages/base-components/rich/src/fileListItem.js
+0
-100
icon_file.png
packages/base-components/rich/src/icon_file.png
+0
-0
index.js
packages/base-components/rich/src/index.js
+0
-558
index.less
packages/base-components/rich/src/index.less
+0
-211
rich.md
packages/base-components/rich/src/rich.md
+0
-24
wangEditor.js
packages/base-components/rich/src/wangEditor.js
+0
-0
No files found.
packages/base-components/rich/CHANGELOG.md
deleted
100644 → 0
View file @
69baad94
# Change Log
All notable changes to this project will be documented in this file. See
[
Conventional Commits
](
https://conventionalcommits.org
)
for commit guidelines.
## [0.1.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/rich@0.1.2...@wisdom-components/rich@0.1.3) (2022-06-27)
### Bug Fixes
-
修改 (
[
7f6ca58
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/7f6ca58c33a5f89d03c77489f5b51b46c9b6edec
)
)
## [0.1.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/rich@0.1.1...@wisdom-components/rich@0.1.2) (2022-06-27)
### Bug Fixes
-
修改 (
[
0f306d9
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/0f306d93916a2aec314f82aec71ba3ee2d1f6559
)
)
## [0.1.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/rich@0.1.0...@wisdom-components/rich@0.1.1) (2022-06-27)
### Bug Fixes
-
修改 (
[
11e7683
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/11e76837724cc6585c1bebee0fc86be9e4d16d33
)
)
# 0.1.0 (2022-06-27)
### Features
-
rich (
[
d4f782c
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/d4f782c428efa469b5f8c1d0c144bc3119a2ee8d
)
)
This diff is collapsed.
Click to expand it.
packages/base-components/rich/README.md
deleted
100644 → 0
View file @
69baad94
# `@wisdom-components/rich`
> TODO: description
## Usage
```
const rich = require('@wisdom-components/rich');
// TODO: DEMONSTRATE API
```
This diff is collapsed.
Click to expand it.
packages/base-components/rich/__tests__/rich.test.js
deleted
100644 → 0
View file @
69baad94
'use strict'
;
const
rich
=
require
(
'..'
);
describe
(
'@wisdom-components/rich'
,
()
=>
{
it
(
'needs tests'
);
});
This diff is collapsed.
Click to expand it.
packages/base-components/rich/package.json
deleted
100644 → 0
View file @
69baad94
{
"name"
:
"@wisdom-components/rich"
,
"version"
:
"0.1.3"
,
"description"
:
"> TODO: description"
,
"author"
:
"hongmye <1014185119@qq.com>"
,
"homepage"
:
""
,
"license"
:
"ISC"
,
"module"
:
"es/index.js"
,
"main"
:
"lib/index.js"
,
"sideEffects"
:
[
"*.less"
],
"directories"
:
{
"lib"
:
"lib"
,
"test"
:
"__tests__"
},
"files"
:
[
"lib"
,
"es"
,
"dist"
],
"publishConfig"
:
{
"registry"
:
"https://g.civnet.cn:4873/"
},
"repository"
:
{
"type"
:
"git"
,
"url"
:
"https://g.civnet.cn:8443/ReactWeb5/wisdom-components.git"
},
"scripts"
:
{
"test"
:
"echo
\"
Error: run tests from root
\"
&& exit 1"
},
"dependencies"
:
{
"@babel/runtime"
:
"^7.17.9"
,
"classnames"
:
"^2.2.6"
}
}
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/RichTextShow.js
deleted
100644 → 0
View file @
69baad94
/*
* @Title:富文本展示,可预览图片
* @Author: hongmye
* @Date: 2022-03-21 14:44:49
*/
/**
* 1.引入组件 import RichTextShow from '@/components/RichText/RichTextShow';
* 示例:<RichTextShow content={this.state.content} onClickImg={src => {}} />;
*
* 2.传递方法 onClickImg 点击图片回调(不需可不传)
*
* 3.传值接收 content 富文本内容
* fileList 附件列表
*
*
*/
import
{
Image
}
from
'antd'
;
import
{
useEffect
,
useState
}
from
'react'
;
import
FileListItem
from
'./fileListItem'
;
import
styles
from
'./index.less'
;
function
RichTextShow
(
props
)
{
const
[
imgVisible
,
setImgVisible
]
=
useState
(
false
);
const
[
imgPreviewSrc
,
setImgPreviewSrc
]
=
useState
(
''
);
const
[
fileList
,
setFileList
]
=
useState
([]);
const
onPreview
=
(
e
)
=>
{
e
.
stopPropagation
();
const
src
=
e
?.
target
?.
src
||
null
;
if
(
!
src
)
return
;
setImgPreviewSrc
(
src
);
setImgVisible
(
true
);
props
.
onClickImg
&&
props
.
onClickImg
(
src
,
e
.
target
);
};
useEffect
(()
=>
{
setFileList
(
props
.
fileList
);
},
[
props
.
fileList
]);
useEffect
(()
=>
{},
[
props
.
content
]);
return
(
<
div
style
=
{{
...
props
.
style
}}
>
<
div
className
=
{
styles
.
RichTextShow
}
onClick
=
{
onPreview
}
dangerouslySetInnerHTML
=
{{
__html
:
props
.
content
||
''
}}
/
>
{
fileList
&&
fileList
.
length
>
0
&&
(
<
div
className
=
{
styles
.
RichTextFileList
}
>
<
FileListItem
list
=
{
fileList
}
onDel
=
{(
val
)
=>
{
onDelFile
(
val
);
}}
onPreview
=
{(
val
)
=>
{
if
(
!
val
)
return
;
setImgPreviewSrc
(
val
.
path
);
setImgVisible
(
true
);
}}
/
>
<
/div
>
)}
<
Image
width
=
{
200
}
style
=
{{
display
:
'none'
}}
src
=
{
imgPreviewSrc
}
preview
=
{{
visible
:
imgVisible
,
src
:
imgPreviewSrc
,
onVisibleChange
:
(
value
)
=>
{
setImgVisible
(
value
);
if
(
!
value
)
setImgPreviewSrc
(
''
);
},
}}
/
>
<
/div
>
);
}
export
default
RichTextShow
;
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/demos/Basic.tsx
deleted
100644 → 0
View file @
69baad94
/*
* @Title:
* @Author: hongmye
* @Date: 2022-06-23 16:03:16
*/
// @ts-ignore
import
Empty
from
'@wisdom-components/empty'
;
import
{
useEffect
,
useState
}
from
'react'
;
// import BasicTable from '../index';
import
request
from
'umi-request'
;
const
Demo
=
()
=>
{
const
[
columns
,
setColumns
]
=
useState
([]);
const
[
dataSource
,
setDataSource
]
=
useState
([]);
useEffect
(()
=>
{
fetchData
();
},
[]);
const
fetchData
=
(
params
=
{})
=>
{
request
(
`
${
baseUrl
}
/AcrossTable/GetEquipmentDataReport`
,
{
method
:
'get'
,
params
:
{},
}).
then
(
function
(
response
)
{
const
data
=
response
.
data
;
let
column
=
data
.
map
((
item
,
index
)
=>
{
return
{
title
:
`
${
item
.
DName
+
item
.
DType
}
(
${
item
.
Unit
}
)`
,
dataIndex
:
`name
${
index
}
`
,
key
:
`name
${
index
}
`
,
};
});
column
.
unshift
({
title
:
'时间'
,
dataIndex
:
'time'
,
key
:
'time'
,
});
let
dataSource
=
data
[
0
].
NameDate
.
map
((
item
,
index
)
=>
({
key
:
index
,
time
:
item
.
Time
}));
data
.
forEach
((
item
,
index
)
=>
{
item
.
NameDate
.
forEach
((
child
)
=>
{
dataSource
.
forEach
((
v
)
=>
{
if
(
child
.
Time
===
v
.
time
)
v
[
`name
${
index
}
`
]
=
child
.
Value
;
});
});
});
setColumns
(
column
);
setDataSource
(
dataSource
);
});
};
// @ts-ignore
return
(
<
div
style=
{
{
height
:
'800px'
}
}
>
{
/* {!!dataSource.length && (
<BasicTable
dataSource={dataSource}
columns={columns}
bordered={false}
pagination={{ pageSize: 20, size: 'default' }}
/>
)} */
}
{
!
dataSource
.
length
&&
<
Empty
description=
{
'暂无数据'
}
/>
}
</
div
>
);
};
export
default
Demo
;
const
baseUrl
=
'https://www.fastmock.site/mock/162c15dca15c4dba9ba51e0a0b76929b/api'
;
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/demos/demo.jsx
deleted
100644 → 0
View file @
69baad94
/*
* @Title: 富文本编辑器demo
* @Author: hongmye
* @Date: 2022-03-07 14:44:32
*/
import
React
from
'react'
;
import
{
Button
}
from
'antd'
;
import
RichText
from
'../index'
;
import
RichTextShow
from
'../RichTextShow'
;
// import { projectManageService } from '@/api';
import
styles
from
'./demo.less'
;
class
RichTextDemo
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
myRichText
=
React
.
createRef
();
this
.
state
=
{
personList
:
[
{
userId
:
568
,
userName
:
'徐乐'
},
{
userId
:
569
,
userName
:
'余苏苏'
},
{
userId
:
572
,
userName
:
'周宏民'
},
],
content
:
''
,
fileList
:
[],
};
}
getData
=
async
()
=>
{
// const res = await projectManageService.GetWorkHourUserList({ projectId: 19 });
// this.setState({
// // personList: res.data || [],
// });
// const arr = [
// {
// name: '工时管理_工时日报 (1).xlsx',
// type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
// size: 8192,
// path:
// '/PandaWorkFlow/WorkFlow/AccountManage/DownloadFiles?filePath=b0422fdb-6c63-4b34-8021-b54102236bcb/工时管理_工时日报/(1).xlsx',
// },
// {
// name: '浊度.png',
// type: 'image/png',
// size: 6789,
// path:
// '/PandaWorkFlow/WorkFlow/AccountManage/DownloadFiles?filePath=fd00ce06-52c0-410a-bd30-8aed9131a616/浊度.png',
// },
// ];
// // this.setState({ fileList: arr });
// this.myRichText.current && this.myRichText.current.setHtml('');
};
componentDidMount
=
()
=>
{
this
.
getData
();
};
componentDidUpdate
=
(
propNev
,
stateNev
)
=>
{
};
componentWillUnmount
()
{
this
.
setState
=
()
=>
{
};
}
render
()
{
return
(
<
div
className=
{
styles
.
RichTextDemo
}
>
<
div
className=
{
styles
.
RichTextDemoContainer
}
>
<
RichText
// content={this.state.content}
personList=
{
this
.
state
.
personList
}
onChange=
{
val
=>
{
this
.
setState
({
content
:
val
});
}
}
onChangeFile=
{
arr
=>
{
this
.
setState
({
fileList
:
arr
});
}
}
fileList=
{
this
.
state
.
fileList
}
projectId=
{
19
}
ref=
{
this
.
myRichText
}
/>
</
div
>
{
/* <div className={styles.contentBox}>{this.state.content}</div> */
}
<
div
className=
{
styles
.
contentBox
}
>
<
RichTextShow
content=
{
this
.
state
.
content
}
onClickImg=
{
src
=>
{
}
}
fileList=
{
this
.
state
.
fileList
}
/>
</
div
>
<
div
className=
{
styles
.
contentBox
}
>
{
this
.
state
.
content
}
</
div
>
</
div
>
);
}
}
export
default
RichTextDemo
;
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/demos/demo.less
deleted
100644 → 0
View file @
69baad94
.RichTextDemoContainer {
// height: 400px;
// padding: 0px 100px;
background-color: #fff;
}
.contentBox {
// height: 400px;
margin-top: 10px;
padding: 20px;
background-color: #fff;
}
.RichTextDemo {
height: 100%;
overflow-y: scroll;
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/fileListItem.js
deleted
100644 → 0
View file @
69baad94
/*
* @Title:
* @Author: hongmye
* @Date: 2022-03-21 14:44:49
*/
import
React
,
{
useState
,
useEffect
,
useRef
,
useImperativeHandle
,
forwardRef
}
from
'react'
;
import
{
FileTwoTone
,
DeleteOutlined
,
FileImageTwoTone
,
DownloadOutlined
,
PictureOutlined
}
from
'@ant-design/icons'
;
import
{
Button
}
from
'antd'
;
import
iconFile
from
'./icon_file.png'
;
function
fileListItem
(
props
)
{
const
[
fileList
,
setFileList
]
=
useState
([]);
const
imgType
=
[
'image/png'
,
'image/jpg'
,
'image/jpeg'
];
const
onPreview
=
item
=>
{
props
.
onPreview
(
item
);
};
const
onDownLoad
=
item
=>
{
const
a
=
document
.
createElement
(
'a'
);
a
.
setAttribute
(
'download'
,
item
.
name
);
a
.
setAttribute
(
'href'
,
item
.
path
);
document
.
documentElement
.
appendChild
(
a
);
a
.
target
=
'_black'
;
a
.
click
();
};
useEffect
(()
=>
{
setFileList
(
props
.
list
||
[]);
},
[
props
.
list
]);
return
(
<>
{
fileList
.
map
((
item
,
index
)
=>
{
return
(
<
div
key
=
{
index
}
className
=
{
'panda-civ-work-upload-list panda-civ-work-upload-list-picture'
}
>
<
div
className
=
{
'panda-civ-work-upload-list-picture-container'
}
>
<
div
className
=
{
'panda-civ-work-upload-list-item'
}
>
<
div
className
=
{
'panda-civ-work-upload-list-item-info'
}
>
<
span
className
=
{
'panda-civ-work-upload-span'
}
>
<
div
className
=
{
'panda-civ-work-upload-list-item-thumbnail panda-civ-work-upload-list-item-file'
}
>
{
/* {imgType.includes(item.type) ? <FileImageTwoTone /> : <FileTwoTone />} */
}
<
img
src
=
{
iconFile
}
/
>
<
/div
>
<
span
className
=
{
'panda-civ-work-upload-list-item-name'
}
title
=
{
item
.
name
}
style
=
{{
cursor
:
'pointer'
}}
>
{
item
.
name
}
<
/span
>
<
span
className
=
{
'panda-civ-work-upload-list-item-card-actions picture'
}
>
{
imgType
.
includes
(
item
.
type
)
&&
(
<
Button
title
=
"预览"
type
=
"text"
onClick
=
{
e
=>
{
e
&&
e
.
stopPropagation
();
onPreview
(
item
);
}}
style
=
{{
padding
:
'4px 8px'
}}
>
<
PictureOutlined
/>
<
/Button
>
)}
<
Button
title
=
"下载"
type
=
"text"
onClick
=
{
e
=>
{
e
&&
e
.
stopPropagation
();
onDownLoad
(
item
);
}}
style
=
{{
padding
:
'4px 8px'
}}
>
<
DownloadOutlined
/>
<
/Button
>
{
props
.
type
===
'edit'
&&
(
<
Button
title
=
"删除文件"
type
=
"text"
onClick
=
{
e
=>
{
e
&&
e
.
stopPropagation
();
props
.
onDel
(
item
);
}}
style
=
{{
padding
:
'4px 8px'
}}
>
<
DeleteOutlined
/>
<
/Button
>
)}
<
/span
>
<
/span
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
);
})}
<
/
>
);
}
export
default
fileListItem
;
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/icon_file.png
deleted
100644 → 0
View file @
69baad94
778 Bytes
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/index.js
deleted
100644 → 0
View file @
69baad94
/*
* @Title:富文本编辑器
* @Author: hongmye
* @Date: 2022-03-01 14:23:55
*/
/**
* 1.引入组件 import RichText from '@/components/RichText';
* 示例:<RichText
content={this.state.content}
personList={this.state.personList}
placeholder={'placeholder属性值'}
onChange={val => {
this.setState({ content: val });
}}
onChangeFile={arr => {
this.setState({ fileList: arr });
}}
fileList={this.state.fileList}
projectId={19}
ref={this.myRichText}
/>
*
* 2.传递方法 onChange 每次更改内容回调
*
* 3.传值接收 可选值 projectId 项目id,根据项目id获取项目参与人员,
* 可选值 personList 人员列表 示例:[{userId:1,userName:'xxx'}]
* 可选值 config 框架wangEditor的配置参数
*
* 4.注意事项 projectId和personList只用传一个,projectId优先级高于personList
* content内容如果不是初始有的,可调用setHtml设置内容
*
* 2022-03-21新增图片预览,附件上传功能
* 新增方法:onChangeFile 每次附件更改回调 若不传则不显示附件上传按钮
* fileList 附件列表 示例:[{name:'xxx.jpg',type:'image/jpg',size:8192,path:'xxxx'}]
* 其中name和path是必传的,type为图片可以预览,其它类型文件直接下载
*
* 2022-04-29 修改@人员列表逻辑
* personList 传任务相关人员列表(如 创建、负责、跟进人),同时传入projectId,personList
* 下拉列表默认显示为任务相关人员,加项目人员(做了去重,任务相关人员在最上面)
* @搜索时,搜索全部人员
*/
import
{
Image
,
message
,
Spin
}
from
'antd'
;
import
classNames
from
'classnames'
;
import
{
forwardRef
,
useEffect
,
useImperativeHandle
,
useRef
,
useState
}
from
'react'
;
// import { request } from '@wisdom-utils/utils';
import
request
from
'umi-request'
;
import
WangEditor
from
'./wangEditor.js'
;
// import { API } from '@/api/service/workflow';
const
API
=
{};
// import { appWork, projectManageService } from '@/api';
import
FileListItem
from
'./fileListItem'
;
import
styles
from
'./index.less'
;
let
editor
=
null
;
let
range
;
const
selection
=
window
.
getSelection
();
let
startOffset
;
let
tempList
=
[];
let
allPeople
=
[];
// 全部人员
let
selectPersonIndex
;
let
selectPerson
=
[];
const
RichText
=
forwardRef
((
props
,
ref
)
=>
{
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
zIndex
,
setZIndex
]
=
useState
(
500
);
// const [inputValue, setInputValue] = useState('');
const
[
selectIndex
,
setSelectIndex
]
=
useState
(
null
);
const
[
selectList
,
setSelectList
]
=
useState
([]);
const
[
selectSearchList
,
setSelectSearchList
]
=
useState
([]);
const
[
fileList
,
setFileList
]
=
useState
([]);
const
[
imgVisible
,
setImgVisible
]
=
useState
(
false
);
const
[
imgPreviewSrc
,
setImgPreviewSrc
]
=
useState
(
''
);
const
richTextRef
=
useRef
();
const
selectBoxRef
=
useRef
();
const
fileInputRef
=
useRef
();
const
getData
=
async
()
=>
{
// const { data } = await projectManageService.GetWorkHourUserList({ projectId: props.projectId });
// setSelectList(data);
};
// 获取全部人员信息
const
getAllPeople
=
async
()
=>
{
// const res = await appWork.GetAllPersonnels();
// allPeople = res?.data?.data || [];
};
// 图片上传
const
uploadImg
=
(
file
)
=>
{
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
setLoading
(
true
);
request
({
url
:
API
.
POST_UPLOADERFILES
,
method
:
'POST'
,
data
:
formData
,
})
.
then
((
res
)
=>
{
if
(
!
res
.
data
)
return
;
const
img
=
res
.
data
.
replace
(
/
[\\
\/
=
]
/g
,
'/'
);
const
imgHtml
=
`
<img contenteditable="false" style="display: block;" width="50%" src="
${
API
.
GET_DOWNLOADFILES
}
?filePath=
${
img
}
" >
`
;
// 已弃用(会出现插入图片后,光标消失的问题)
// const imgHtml = `
// <div class="RichText-image" contenteditable="false">
// <img class="RichText-image-img" src="${API.GET_DOWNLOADFILES}?filePath=${img}">
// <div class="RichText-image-mask" type="preview" >
// <div class="RichText-image-mask-info" type="preview">
// <span role="img" aria-label="eye" class="anticon anticon-eye">
// <svg viewBox="64 64 896 896" focusable="false" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true">
// <path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path>
// </svg>
// </span>
// 预览
// </div>
// </div>
// </div>`;
editor
.
cmd
.
do
(
'insertHTML'
,
imgHtml
);
setLoading
(
false
);
})
.
catch
((
err
)
=>
{
setLoading
(
false
);
});
};
const
init
=
()
=>
{
const
{
BtnMenu
}
=
WangEditor
;
editor
=
new
WangEditor
(
'#RichTextToolbar'
,
'#RichTextContainer'
);
// 自定义菜单
const
menuKey
=
'fileMenuKey'
;
if
(
props
.
onChangeFile
)
{
class
InsertABCMenu
extends
BtnMenu
{
constructor
(
editor
)
{
const
$elem
=
WangEditor
.
$
(
`<div class="w-e-menu">
<i class="w-e-icon-link">
</i>
</div>`
,
);
super
(
$elem
,
editor
);
}
// 菜单点击事件
clickHandler
()
{
// 触发选择文件
fileInputRef
.
current
.
click
();
}
// 菜单激活状态
tryChangeActive
()
{
// this.active(); // 菜单激活
}
}
editor
.
menus
.
extend
(
menuKey
,
InsertABCMenu
);
}
editor
.
config
=
Object
.
assign
(
{},
editor
.
config
,
{
placeholder
:
props
.
placeholder
??
''
,
focus
:
false
,
pasteFilterStyle
:
true
,
// 忽略粘贴样式
pasteIgnoreImg
:
true
,
// 忽略粘贴的图片
styleWithCSS
:
false
,
zIndex
:
500
,
menus
:
[
'bold'
,
'fontSize'
,
'italic'
,
'underline'
,
'strikeThrough'
,
'foreColor'
,
'backColor'
,
'list'
,
'justify'
,
'table'
,
menuKey
,
'undo'
,
'redo'
,
'image'
,
],
},
props
.
config
||
{},
);
setZIndex
(
Number
(
editor
.
config
.
zIndex
));
// 内容变更
editor
.
config
.
onchange
=
(
newHtml
,
e
)
=>
{
props
.
onChange
(
newHtml
);
};
// 粘贴前置处理
editor
.
config
.
pasteTextHandle
=
(
pasteStr
)
=>
pasteStr
;
editor
.
config
.
onblur
=
(
newHtml
)
=>
{
selectBoxRef
.
current
.
style
.
display
=
'none'
;
};
// 点击事件
editor
.
txt
.
eventHooks
.
clickEvents
.
push
((
e
)
=>
{
// 图片预览
// 已弃用
if
(
e
.
target
.
getAttribute
(
'type'
)
===
'preview'
)
{
const
imgSrc
=
e
.
target
?.
parentNode
?.
parentNode
?.
getElementsByTagName
(
'img'
)?.[
0
]
?.
getAttribute
(
'src'
);
setImgPreviewSrc
(
imgSrc
);
setImgVisible
(
true
);
}
// 关闭选人的下拉框
selectBoxRef
.
current
.
style
.
display
=
'none'
;
});
editor
.
txt
.
eventHooks
.
onPreviewEvents
.
push
((
link
)
=>
{
// 图片预览
if
(
link
)
{
setImgPreviewSrc
(
link
);
setImgVisible
(
true
);
}
});
editor
.
txt
.
eventHooks
.
imgClickEvents
.
push
((
e
)
=>
{
// 图片预览
// 已弃用
// let img = e?.selector?.getAttribute('src') || '';
// if (img) {
// setImgPreviewSrc(img);
// setImgVisible(true);
// }
});
// 粘贴图片上传
editor
.
txt
.
eventHooks
.
pasteEvents
.
push
((
e
)
=>
{
const
file
=
e
?.
clipboardData
?.
items
[
0
]?.
getAsFile
()
||
null
;
if
(
!
file
)
return
;
uploadImg
(
file
);
});
editor
.
create
();
editor
.
txt
.
html
(
props
.
content
||
''
);
richTextRef
.
current
.
onkeydown
=
keyDownEvent
;
richTextRef
.
current
.
addEventListener
(
'input'
,
(
e
)
=>
{
if
(
range
)
{
// 判断节点是否在选区及光标是否在@后面
const
type
=
selection
.
containsNode
(
selection
.
getRangeAt
(
0
).
commonAncestorContainer
,
false
);
if
(
!
type
||
startOffset
>
selection
.
focusOffset
)
{
closeList
();
return
;
}
range
.
setEnd
(
selection
.
getRangeAt
(
0
).
commonAncestorContainer
,
selection
.
focusOffset
);
// console.log('🚀 ~ range', range.toString(), tempList, selectList);
const
str
=
range
.
toString
()
||
''
;
moveListBox
();
handleChange
(
str
,
tempList
);
}
if
(
e
.
data
!==
'@'
)
return
;
if
(
range
)
{
closeList
();
}
range
=
document
.
createRange
();
startOffset
=
selection
.
focusOffset
;
range
.
setStart
(
selection
.
getRangeAt
(
0
).
commonAncestorContainer
,
selection
.
focusOffset
);
selection
.
addRange
(
range
);
moveListBox
();
// 清空搜索
handleChange
(
''
,
tempList
);
});
};
// 跟据光标位置移动下拉框
const
moveListBox
=
()
=>
{
// 获取光标位置
const
cursor
=
window
?.
getSelection
()?.
getRangeAt
(
0
)?.
getBoundingClientRect
()
||
null
;
const
containerRect
=
document
.
querySelector
(
'#RichText'
).
getBoundingClientRect
();
selectBoxRef
.
current
.
style
.
display
=
'block'
;
selectBoxRef
.
current
.
style
.
left
=
`
${
parseInt
(
cursor
.
x
-
containerRect
.
x
,
10
)
+
5
}
px`
;
selectBoxRef
.
current
.
style
.
top
=
`
${
parseInt
(
cursor
.
y
-
containerRect
.
y
,
10
)
+
25
}
px`
;
};
// 键盘事件
const
keyDownEvent
=
(
evet
)
=>
{
// 上下方向键
if
(
evet
.
key
===
'ArrowDown'
||
evet
.
key
===
'ArrowUp'
)
{
evet
.
preventDefault
();
if
(
selectBoxRef
.
current
?.
style
?.
display
===
'block'
)
{
const
max
=
selectBoxRef
.
current
.
querySelectorAll
(
'.selectItem'
)?.
length
||
1000
;
let
val
=
selectPersonIndex
;
if
(
evet
.
key
===
'ArrowDown'
)
{
if
(
!
val
&&
val
!=
0
)
{
val
=
0
;
}
else
{
val
+=
1
;
}
}
if
(
evet
.
key
===
'ArrowUp'
)
val
-=
1
;
if
(
isNaN
(
val
)
||
!
val
||
val
<
0
)
val
=
0
;
if
(
val
>
max
-
1
)
val
=
max
-
1
;
selectPersonIndex
=
val
;
setSelectIndex
(
selectPersonIndex
);
}
}
if
(
evet
.
key
===
'Enter'
)
{
// 解决无法回车换行的bug
if
(
selectBoxRef
.
current
.
style
.
display
===
'block'
&&
selectSearchList
.
length
)
{
evet
.
preventDefault
();
if
(
selectPerson
[
selectPersonIndex
])
{
onSelect
(
selectPerson
[
selectPersonIndex
]);
}
return
false
;
}
}
};
useEffect
(()
=>
{
richTextRef
.
current
&&
richTextRef
.
current
.
removeEventListener
(
'input'
,
(
e
)
=>
{});
init
();
getAllPeople
();
return
()
=>
{
richTextRef
.
current
&&
richTextRef
.
current
.
removeEventListener
(
'input'
,
(
e
)
=>
{});
editor
&&
editor
.
destroy
();
editor
=
null
;
};
},
[]);
useEffect
(()
=>
{
selectPersonIndex
=
null
;
setSelectIndex
(
null
);
selectPerson
=
selectSearchList
||
[];
},
[
selectSearchList
]);
useEffect
(()
=>
{
if
(
props
.
projectId
)
getData
();
},
[
props
.
projectId
]);
useEffect
(()
=>
{
const
keys
=
[];
const
arr
=
[];
if
(
props
.
personList
)
{
props
.
personList
.
forEach
((
i
)
=>
{
i
.
userId
=
Number
(
i
.
userId
);
if
(
!
keys
.
includes
(
i
.
userId
))
{
keys
.
push
(
i
.
userId
);
arr
.
push
(
i
);
}
});
}
if
(
selectList
)
{
selectList
.
forEach
((
i
)
=>
{
i
.
userId
=
Number
(
i
.
userId
);
if
(
!
keys
.
includes
(
i
.
userId
))
{
arr
.
push
(
i
);
keys
.
push
(
i
.
userId
);
}
});
}
tempList
=
arr
;
setSelectSearchList
(
arr
);
},
[
selectList
,
props
.
personList
]);
// useEffect(() => {
// if (!props.projectId) {
// setSelectList(props.personList || []);
// }
// }, [props.personList]);
useEffect
(()
=>
{
setFileList
(
props
.
fileList
);
},
[
props
.
fileList
]);
const
getHtml
=
(
val
)
=>
editor
.
txt
.
html
();
// 获取文本,不含标签
const
getText
=
(
val
)
=>
editor
.
txt
.
text
();
// 清除
const
onClear
=
()
=>
{
editor
.
txt
.
clear
();
};
// 设置内容
const
setHtml
=
(
val
)
=>
{
editor
.
txt
.
html
(
val
||
''
);
};
// 关闭人员下拉选框
const
closeList
=
()
=>
{
selectPersonIndex
=
null
;
setSelectIndex
(
null
);
selectBoxRef
.
current
.
style
.
display
=
'none'
;
if
(
range
)
{
selection
.
removeRange
(
range
);
range
=
null
;
}
};
// @某人
const
onSelect
=
(
item
)
=>
{
if
(
range
)
{
range
.
deleteContents
();
// 删除前一个@符号
editor
.
cmd
.
do
(
'delete'
);
const
_html
=
`<span><span data-userId="
${
item
.
userId
}
" data-type="person" >@
${
item
.
userName
}
</span><span> </span></span>`
;
editor
.
cmd
.
do
(
'insertElem'
,
_html
);
closeList
();
selection
.
collapseToEnd
();
}
};
// const onChange = val => {
// setInputValue(val.currentTarget.value);
// handleChange(val.currentTarget.value);
// };
let
timer
=
null
;
const
filterList
=
(
val
,
list
)
=>
{
if
(
!
val
)
{
if
(
list
.
length
===
0
)
{
selectBoxRef
.
current
.
style
.
display
=
'none'
;
}
setSelectSearchList
(
list
);
}
else
{
const
arr
=
getArrayByName
(
val
,
allPeople
);
if
(
arr
.
length
===
0
)
{
selectBoxRef
.
current
.
style
.
display
=
'none'
;
}
setSelectSearchList
(
arr
);
}
};
const
handleChange
=
(
val
,
list
)
=>
{
if
(
timer
)
{
clearTimeout
(
timer
);
}
timer
=
setTimeout
(()
=>
{
timer
=
null
;
filterList
(
val
,
list
);
},
200
);
// filterList(val, list);
};
/**
* 根据字符串模糊搜索返回符合条件的数据
* name 搜索字符串
* array 检索json数组
*/
const
getArrayByName
=
(
name
,
array
)
=>
{
const
result
=
[];
array
.
forEach
((
i
)
=>
{
if
(
i
.
name
.
indexOf
(
name
)
!=
-
1
)
result
.
push
({
userName
:
i
.
name
,
userId
:
i
.
id
,
port
:
i
.
port
});
});
return
result
;
};
const
addFile
=
(
e
)
=>
{
if
(
e
.
target
)
{
const
file
=
e
.
target
.
files
[
0
];
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
setLoading
(
true
);
request
({
url
:
API
.
POST_UPLOADERFILES
,
method
:
'POST'
,
data
:
formData
,
})
.
then
((
res
)
=>
{
if
(
res
.
data
)
{
const
arr
=
[...
fileList
];
const
url
=
res
.
data
.
replace
(
/
[\\
\/
=
]
/g
,
'/'
);
arr
.
unshift
({
name
:
file
.
name
,
type
:
file
.
type
?
file
.
type
.
toLowerCase
()
:
''
,
size
:
file
.
size
,
path
:
`
${
API
.
GET_DOWNLOADFILES
}
?filePath=
${
url
}
`
,
});
// setFileList(arr);
props
.
onChangeFile
(
arr
);
setLoading
(
false
);
}
else
{
message
.
error
(
res
.
msg
);
setLoading
(
false
);
}
})
.
catch
((
err
)
=>
{
setLoading
(
false
);
});
}
};
const
onDelFile
=
(
item
)
=>
{
const
arr
=
[];
fileList
.
forEach
((
i
)
=>
{
if
(
i
.
path
!==
item
.
path
)
{
arr
.
push
(
i
);
}
});
// setFileList(arr);
props
.
onChangeFile
(
arr
);
};
useImperativeHandle
(
ref
,
()
=>
({
setHtml
,
onClear
,
getHtml
,
getText
,
}));
return
(
<
div
className
=
{
styles
.
RichText
}
id
=
"RichText"
>
{
loading
?
(
<
div
className
=
{
styles
.
loadingWrap
}
style
=
{{
zIndex
:
zIndex
+
20
}}
>
<
Spin
spinning
=
{
loading
}
/
>
<
/div
>
)
:
null
}
<
div
id
=
"RichTextToolbar"
className
=
{
styles
.
RichTextToolbar
}
/
>
<
div
ref
=
{
richTextRef
}
id
=
"RichTextContainer"
className
=
{
styles
.
RichTextContainer
}
/
>
<
div
className
=
{
styles
.
RichTextFileList
}
>
<
FileListItem
list
=
{
fileList
}
onDel
=
{(
val
)
=>
{
onDelFile
(
val
);
}}
type
=
"edit"
onPreview
=
{(
val
)
=>
{
if
(
!
val
)
return
;
setImgPreviewSrc
(
val
.
path
);
setImgVisible
(
true
);
}}
/
>
<
/div
>
<
div
ref
=
{
selectBoxRef
}
className
=
{
styles
.
selectBox
}
style
=
{{
maxWidth
:
'300px'
,
minWidth
:
'150px'
,
zIndex
:
zIndex
+
10
}}
>
{
selectSearchList
.
length
?
(
<
div
className
=
{
styles
.
selectList
}
>
{
selectSearchList
.
map
((
item
,
index
)
=>
(
<
div
key
=
{
item
.
userId
}
onClick
=
{()
=>
{
onSelect
(
item
);
}}
className
=
{
classNames
(
'selectItem'
,
styles
.
selectItem
,
selectIndex
===
index
?
styles
.
selectActiveItem
:
''
,
)}
>
{
item
.
userName
}
<
/div
>
))}
<
/div
>
)
:
null
}
<
/div
>
<
input
style
=
{{
display
:
'none'
}}
type
=
"file"
ref
=
{
fileInputRef
}
onChange
=
{(
e
)
=>
{
addFile
(
e
);
}}
name
=
"file"
/>
<
Image
width
=
{
200
}
style
=
{{
display
:
'none'
}}
src
=
{
imgPreviewSrc
}
preview
=
{{
visible
:
imgVisible
,
src
:
imgPreviewSrc
,
onVisibleChange
:
(
value
)
=>
{
setImgVisible
(
value
);
if
(
!
value
)
setImgPreviewSrc
(
''
);
},
}}
/
>
<
/div
>
);
});
export
default
RichText
;
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/index.less
deleted
100644 → 0
View file @
69baad94
@import '~antd/es/style/themes/default.less';
// @import '~antd/es/image/style/index.less';
.RichText {
width: 100%;
height: auto;
min-height: 200px;
position: relative;
display: flex;
flex-direction: column;
border: 1px solid #d9d9d9;
border-radius: 2px;
.loadingWrap {
width: 100%;
height: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.8);
}
.selectBox {
position: absolute;
top: 0;
left: 0;
background: #fff;
max-height: 250px;
overflow-y: scroll;
display: none;
}
.selectList{
border: 1px solid #efefef;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.16), 0 0;
}
.selectList .selectItem:hover {
background: #1685FF;
color: #fff;
cursor: pointer;
}
.selectList .selectActiveItem {
background: #1685FF;
color: #fff;
}
.selectItem {
padding: 5px 10px;
}
ol li {
list-style: decimal !important;
}
ul li {
list-style: disc !important;
}
}
.RichTextFileList {
padding: 20px;
:global {
.@{ant-prefix}-upload-list-item {
height: 44px;
padding: 8px 16px;
.@{ant-prefix}-upload-list-item-thumbnail,
.@{ant-prefix}-upload-list-item-file {
width: 20px;
height: 22px;
>img {
width: 100%;
height: 100%;
}
}
.@{ant-prefix}-upload-list-item-name {
line-height: normal;
}
}
}
}
.RichTextContainer {
background-color: #fff;
color: #000000d9;
position: relative;
overflow-y: scroll;
flex: 1;
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
}
.RichTextToolbar {
border-bottom: 1px solid #d9d9d9;
// height: 0;
// overflow: hidden;
}
.RichTextShow img {
cursor: pointer;
}
.RichTextShow span[data-type='person'] {
font-weight: bold;
color: #44acb6 !important;
}
:global {
#RichTextContainer span[data-type='person'] {
font-weight: bold;
color: #44acb6 !important;
}
.w-e-menu[data-title="图片"] {
display: none;
}
.RichText-image {
position: relative;
display: inline-block;
}
#RichTextContainer .RichText-image-img {
max-width: calc(100% - 20px);
display: inline-block;
width: auto;
height: auto;
}
.RichText-image-mask {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
opacity: 0;
transition: opacity 0.3s;
padding: 0;
margin: 0;
box-sizing: border-box;
}
.RichText-image-mask-info {
padding: 0;
margin: 0;
box-sizing: border-box;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
color: #fff;
font-size: 20px;
}
.RichText-image-mask-info .anticon {
margin-inline-end: 4px;
}
.anticon svg {
display: inline-block;
}
.RichText-image-mask:hover {
opacity: 1;
}
.r-t-add-file {
color: #999;
font-family: 'w-e-icon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
padding: 0;
margin: 0;
box-sizing: border-box;
}
.r-t-add-file:before {
content: "\e9cb";
}
.@{ant-prefix}-image-error {
display: block;
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/rich.md
deleted
100644 → 0
View file @
69baad94
---
title
:
RichText - 富文本编辑器
nav
:
title
:
基础组件
path
:
/components
group
:
path
:
/
---
# RichText 富文本编辑器
## 代码演示
### 常规使用
<code
src=
"./demos/demo.jsx"
>
### 合计
<!-- <code src="./demos/Summary.tsx">
-->
## API
api 参考 Antd Table 组件 https://www.wangeditor.com/v4/
This diff is collapsed.
Click to expand it.
packages/base-components/rich/src/wangEditor.js
deleted
100644 → 0
View file @
69baad94
This source diff could not be displayed because it is too large. You can
view the blob
instead.
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment