Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
易术家
Awesome-Markdown-Editor
提交
6cd70f38
Awesome-Markdown-Editor
项目概览
易术家
/
Awesome-Markdown-Editor
与 Fork 源项目一致
Fork自
gitcode_dev / Awesome-Markdown-Editor
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Awesome-Markdown-Editor
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
6cd70f38
编写于
7月 30, 2021
作者:
璃白.
🌻
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix:优化@用户逻辑
上级
a6571f9f
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
263 addition
and
193 deletion
+263
-193
dist/index.html
dist/index.html
+4
-3
dist/markdown-editor.js
dist/markdown-editor.js
+1
-1
src/App.vue
src/App.vue
+4
-0
src/assets/js/utils.js
src/assets/js/utils.js
+8
-30
src/assets/style/card.less
src/assets/style/card.less
+20
-11
src/assets/style/font/iconfont.ttf
src/assets/style/font/iconfont.ttf
+0
-0
src/assets/style/iconfont.less
src/assets/style/iconfont.less
+1
-1
src/components/content/components/user-select.vue
src/components/content/components/user-select.vue
+28
-11
src/components/content/md-textarea.vue
src/components/content/md-textarea.vue
+33
-136
src/components/content/mixins/render-mixins.js
src/components/content/mixins/render-mixins.js
+75
-0
src/components/content/mixins/select-user-mixins.js
src/components/content/mixins/select-user-mixins.js
+89
-0
未找到文件。
dist/index.html
浏览文件 @
6cd70f38
...
...
@@ -145,7 +145,7 @@ void main()
new
Promise
((
res
,
rej
)
=>
{
setTimeout
(()
=>
{
res
(
file
);
},
2
000
);
},
1
000
);
}).
then
(
res
=>
{
var
reader
=
new
FileReader
();
reader
.
readAsDataURL
(
res
);
...
...
@@ -156,6 +156,7 @@ void main()
},
renderLinks
:
function
(
val
,
callback
)
{
const
newLinks
=
val
.
map
(
item
=>
{
item
.
csdn
=
true
;
item
.
title
=
"
接口返回的标题接口返回的标题接口返回的标题接口返回的标题接口返回的标题接口返回的标题接口返回的标题接口返回的标题接口返回的标题
"
;
item
.
img
=
...
...
@@ -166,8 +167,8 @@ void main()
});
setTimeout
(()
=>
{
callback
(
newLinks
);
},
2
000
);
}
,
},
1
000
);
}
// queryUserList: function(val, callback) {
// const list = [
// {
...
...
dist/markdown-editor.js
浏览文件 @
6cd70f38
此差异已折叠。
点击以展开。
src/App.vue
浏览文件 @
6cd70f38
...
...
@@ -396,8 +396,12 @@ export default {
console
.
log
(
"
返回的列表
"
,
res
);
res
.
forEach
(
item
=>
{
const
linkEl
=
vDom
.
querySelector
(
"
#
"
+
item
.
id
);
const
url
=
item
.
csdn
?
"
https://link.csdn.net/?target=
"
+
item
.
url
:
item
.
url
;
linkEl
.
className
=
"
md_link_card
"
;
linkEl
.
setAttribute
(
"
target
"
,
"
_blank
"
);
linkEl
.
setAttribute
(
"
href
"
,
url
);
const
title
=
getLinkTitle
(
linkEl
);
linkEl
.
innerHTML
=
`
<span class="md_link_title">
${
title
||
item
.
title
}
</span>
...
...
src/assets/js/utils.js
浏览文件 @
6cd70f38
...
...
@@ -29,7 +29,7 @@ export const throttle = function(fn, wait) {
}
};
};
// 获取光标的位置
export
const
getPosition
=
function
(
selectorId
)
{
const
element
=
document
.
getElementById
(
selectorId
);
if
(
!
element
)
return
0
;
...
...
@@ -336,33 +336,11 @@ export function getLinkTitle(linkEl) {
return
/^http/
.
test
(
title
)
?
""
:
title
;
}
export
function
rerender
()
{
const
renderer
=
{
image
(
href
,
title
,
text
)
{
if
(
href
===
null
)
{
return
text
;
}
// ![file](...)渲染文件,只可以下载
if
(
text
===
"
file
"
)
{
return
`<a href="
${
href
}
" class="md_file_card md_flex_card" download target="_blank">
<span class="md_file_img icon iconfont icon-doc"></span>
<span class="flex-1">
<span class="md_file_title">
${
title
}
</span>
<span class="md_file_desc">16.6KB</span>
</span>
<span class="md_file_controls">
<span class="md_file_download icon iconfont icon-xiazai"></span>
</span>
</a>`
;
}
// ![img](...)渲染图片
let
out
=
'
<img src="
'
+
href
+
'
" alt="
'
+
text
+
'
"
'
;
if
(
title
)
{
out
+=
'
title="
'
+
title
+
'
"
'
;
}
out
+=
"
/>
"
;
return
out
;
}
};
marked
.
use
({
renderer
});
export
function
preventDefault
(
id
)
{
const
textEl
=
document
.
getElementById
(
id
);
textEl
.
blur
();
setTimeout
(()
=>
{
textEl
.
focus
();
},
0
);
return
;
}
src/assets/style/card.less
浏览文件 @
6cd70f38
...
...
@@ -6,9 +6,11 @@
border: 1px solid var(--md-editor-border-color);
background: #f5f7fa;
transition: border 0.3s;
max-width: 800px;
&:hover {
border: 1px solid var(--md-editor-border-color-active);
max-width: 600px;
@media (any-hover: hover) {
&:hover {
border: 1px solid var(--md-editor-border-color-active);
}
}
span {
color: var(--md-editor-text-color-active);
...
...
@@ -55,28 +57,35 @@
border: 1px solid var(--md-editor-border-color);
background: #f5f7fa;
transition: border 0.3s;
max-width: 600px;
&:hover {
border: 1px solid var(--md-editor-border-color-active);
max-width: 400px;
margin: 4px 0;
@media (any-hover: hover) {
&:hover {
border: 1px solid var(--md-editor-border-color-active);
}
}
span {
color: var(--md-editor-text-color-active);
}
.md_file_img {
font-size: 3
6
px;
font-size: 3
4
px;
margin-right: 16px;
color: var(--md-editor-
text-color
);
color: var(--md-editor-
border-color-active
);
}
.md_file_download {
font-size: 1
6
px;
font-size: 1
4
px;
padding: 8px;
box-sizing: border-box;
border: 1px solid var(--md-editor-border-color);
border-radius: 50%;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: var(--md-editor-border-color-active);
line-height: 1 !important;
color: var(--md-editor-border-color);
@media (any-hover: hover) {
&:hover {
color: var(--md-editor-border-color-active);
}
}
}
.md_file_title {
...
...
src/assets/style/font/iconfont.ttf
浏览文件 @
6cd70f38
无法预览此类型文件
src/assets/style/iconfont.less
浏览文件 @
6cd70f38
...
...
@@ -112,7 +112,7 @@
}
.icon-doc:before {
content: "\e6
42
";
content: "\e6
89
";
}
.icon-xiazai:before {
...
...
src/components/content/components/user-select.vue
浏览文件 @
6cd70f38
...
...
@@ -3,11 +3,12 @@
class=
"md_select_container"
:style=
"
{ left: this.left + 'px', top: this.top + 'px' }"
>
<ul
v-show=
"
userL
ist.length"
class=
"md_select_user"
>
<ul
v-show=
"
l
ist.length"
class=
"md_select_user"
>
<li
@
click=
"selectUser(item)"
v-for=
"(item, index) in
userL
ist"
v-for=
"(item, index) in
l
ist"
:key=
"index"
:class=
"[
{ active: isActive(index) }]"
>
<img
class=
"md_select_user_avatar"
:src=
"item.avatar"
/>
<div
class=
"md_select_user_info"
>
...
...
@@ -16,8 +17,8 @@
</div>
</li>
</ul>
<div
v-show=
"
userL
ist.length"
class=
"after"
></div>
<div
v-show=
"!
userL
ist.length"
class=
"md_select_no_data"
>
<div
v-show=
"
l
ist.length"
class=
"after"
></div>
<div
v-show=
"!
l
ist.length"
class=
"md_select_no_data"
>
轻敲空格完成输入
</div>
</div>
...
...
@@ -37,6 +38,24 @@ export default {
userList
:
{
type
:
Array
,
default
:
()
=>
[]
},
activeUserIndex
:
{
type
:
Number
,
default
:
0
}
},
computed
:
{
list
()
{
const
list
=
this
.
userList
;
if
(
!
list
.
length
)
return
[];
return
list
.
map
((
item
,
index
)
=>
{
if
(
index
===
0
)
{
item
.
active
=
true
;
}
else
{
item
.
active
=
false
;
}
return
item
;
});
}
},
watch
:
{
...
...
@@ -57,6 +76,9 @@ export default {
methods
:
{
selectUser
(
user
)
{
this
.
$emit
(
"
selectUser
"
,
user
);
},
isActive
(
index
)
{
return
index
===
this
.
activeUserIndex
;
}
}
};
...
...
@@ -86,12 +108,6 @@ export default {
.md_select_user {
max-height: 214px;
width: 180px;
// background: #fff;
// box-shadow: 0 1px 6px rgb(0 0 0 / 10%);
// border: 1px solid var(--md-editor-border-color);
// border-radius: 4px;
// z-index: var(--md-editor-fullScrren-zIndex);
// margin: 0;
padding: 6px 0;
box-sizing: border-box;
overflow-y: auto;
...
...
@@ -115,7 +131,8 @@ export default {
box-sizing: border-box;
padding: 6px 8px;
cursor: pointer;
&:hover {
&:hover,
&.active {
background: #f5f7fa;
}
// & + li {
...
...
src/components/content/md-textarea.vue
浏览文件 @
6cd70f38
...
...
@@ -8,7 +8,9 @@
@
focus=
"setFocus(true)"
@
blur=
"setFocus(false)"
@
paste=
"pasteFile"
@
keydown.stop.50=
"keyup"
@
keydown.stop.50=
"handleCallUser"
@
keydown.stop.up.prevent=
"changeActiveUserIndex('up')"
@
keydown.stop.down.prevent=
"changeActiveUserIndex('down')"
@
keydown.enter=
"handleEnter"
@
keydown.meta.enter.exact=
"submit"
@
keydown.ctrl.enter.exact=
"submit"
...
...
@@ -39,9 +41,10 @@
<transition
name=
"slideup-fade"
>
<selectUser
:userList=
"userList"
:activeUserIndex.sync=
"activeUserIndex"
v-show=
"showSelectUser"
:position=
"selectUserPosition"
@
selectUser=
"
s
electUser"
@
selectUser=
"
handleS
electUser"
/>
</transition>
</div>
...
...
@@ -50,19 +53,16 @@
import
{
getSelectionInfo
,
getPosition
,
getFilteredTags
,
getLinkTags
,
formatText
,
rerender
,
addLanguageClass
,
preventDefault
,
throttle
as
throttleFn
}
from
"
@/assets/js/utils
"
;
import
marked
from
"
marked
"
;
import
selectUser
from
"
./components/user-select
"
;
import
helpDoc
from
"
./components/help-doc
"
;
import
DOMPurify
from
"
dompurify
"
;
import
renderMix
from
"
./mixins/render-mixins
"
;
import
selectUserMix
from
"
./mixins/select-user-mixins
"
;
export
default
{
components
:
{
helpDoc
,
selectUser
},
mixins
:
[
renderMix
,
selectUserMix
],
props
:
{
id
:
{
type
:
String
,
...
...
@@ -143,6 +143,7 @@ export default {
endPosition
:
""
,
keyWord
:
""
},
activeUserIndex
:
0
,
selectUserPosition
:
{
left
:
0
,
top
:
0
}
};
},
...
...
@@ -158,7 +159,9 @@ export default {
if
(
val
)
{
this
.
resetPreviewMinHeight
();
}
else
{
this
.
showSelectUser
=
false
;
setTimeout
(()
=>
{
// this.showSelectUser = false;
},
200
);
}
}
},
...
...
@@ -214,6 +217,22 @@ export default {
}
},
methods
:
{
changeActiveUserIndex
(
type
)
{
if
(
this
.
showSelectUser
)
{
const
max
=
this
.
userList
.
length
;
if
(
type
===
"
down
"
)
{
this
.
activeUserIndex
++
;
if
(
this
.
activeUserIndex
>=
max
)
{
this
.
activeUserIndex
=
0
;
}
}
else
{
this
.
activeUserIndex
--
;
if
(
this
.
activeUserIndex
<
0
)
{
this
.
activeUserIndex
=
max
-
1
;
}
}
}
},
resetPreviewMinHeight
()
{
setTimeout
(()
=>
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
...
...
@@ -229,130 +248,11 @@ export default {
keyWord
:
""
};
},
transferMarkdown
(
val
)
{
rerender
();
marked
.
setOptions
({
breaks
:
true
,
gfm
:
true
,
langPrefix
:
"
language-
"
,
highlight
:
function
(
code
,
lang
,
callback
)
{
let
html
=
require
(
"
highlight.js
"
).
highlightAuto
(
code
).
value
;
return
html
;
}
});
const
str
=
val
+
""
;
const
html
=
marked
(
str
);
// 解析markdown
const
virtualDom
=
addLanguageClass
(
html
);
// 如果没指定语言,添加默认语言
const
cleanHtml
=
DOMPurify
.
sanitize
(
virtualDom
.
innerHTML
,
{
FORBID_TAGS
:
[
"
style
"
,
"
script
"
,
"
select
"
,
"
option
"
,
"
input
"
,
"
textarea
"
,
"
form
"
,
"
button
"
]
});
// 去除标签
const
filteredTags
=
getFilteredTags
(
html
,
cleanHtml
);
// 计算是否有标签被过滤
// 链接转换为卡片
const
{
vDom
,
links
}
=
getLinkTags
(
this
.
id
,
cleanHtml
);
this
.
$emit
(
"
getFilteredTags
"
,
filteredTags
);
this
.
$emit
(
"
update:html
"
,
cleanHtml
);
if
(
links
.
length
)
this
.
$emit
(
"
renderLinksHtml
"
,
{
vDom
,
links
});
},
input
()
{
if
(
this
.
showSelectUser
)
this
.
handleQueryUser
();
this
.
$emit
(
"
update:textLength
"
,
this
.
textContent
.
length
);
this
.
emitText
();
},
selectUser
(
user
)
{
const
originalText
=
this
.
textContent
;
const
queryInfo
=
this
.
queryInfo
;
const
cursorPosition
=
getPosition
(
this
.
id
);
const
username
=
user
.
name
+
"
"
;
const
newText
=
originalText
.
slice
(
0
,
queryInfo
.
startPosition
)
+
username
+
originalText
.
slice
(
queryInfo
.
endPosition
);
this
.
textContent
=
newText
;
this
.
emitText
();
this
.
showSelectUser
=
false
;
this
.
$nextTick
(()
=>
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
textEl
.
setSelectionRange
(
cursorPosition
+
username
.
length
,
cursorPosition
+
username
.
length
);
textEl
.
focus
();
});
},
handleQueryUser
()
{
const
endPosition
=
getPosition
(
this
.
id
);
const
startPosition
=
this
.
queryInfo
.
startPosition
;
const
keyWord
=
this
.
textContent
.
slice
(
startPosition
,
endPosition
);
this
.
queryInfo
.
endPosition
=
endPosition
;
if
(
endPosition
<
startPosition
||
keyWord
.
slice
(
-
1
)
===
"
"
)
{
this
.
showSelectUser
=
false
;
return
;
}
this
.
queryInfo
.
keyWord
=
keyWord
;
this
.
$emit
(
"
queryUserList
"
,
keyWord
);
},
keyup
(
e
)
{
if
(
e
.
key
===
"
@
"
)
{
this
.
createSelectUserDialog
();
}
},
createSelectUserDialog
()
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
if
(
!
textEl
)
return
;
const
height
=
getComputedStyle
(
textEl
).
getPropertyValue
(
"
height
"
);
const
width
=
getComputedStyle
(
textEl
).
getPropertyValue
(
"
width
"
);
const
scrollTop
=
textEl
.
scrollTop
;
const
originalText
=
this
.
textContent
;
const
cursorPoint
=
getPosition
(
this
.
id
);
const
selectionInfo
=
{
selectionStart
:
cursorPoint
,
selectionEnd
:
cursorPoint
};
const
newText
=
formatText
(
originalText
,
selectionInfo
,
"
<span id='call_position'>
"
,
"
</span>
"
);
const
hideEl
=
this
.
createHideEl
(
"
clac_position_El_
"
);
hideEl
.
style
.
position
=
"
absolute
"
;
hideEl
.
style
.
width
=
width
;
hideEl
.
style
.
height
=
height
;
hideEl
.
style
.
overflowY
=
"
auto
"
;
hideEl
.
style
.
wordBreak
=
"
break-all
"
;
hideEl
.
style
.
top
=
"
14px
"
;
hideEl
.
style
.
left
=
0
;
hideEl
.
style
.
whiteSpace
=
"
pre-wrap
"
;
hideEl
.
innerHTML
=
newText
;
this
.
$nextTick
(()
=>
{
hideEl
.
scrollTop
=
scrollTop
;
const
pEl
=
document
.
getElementById
(
"
call_position
"
);
this
.
selectUserPosition
=
{
left
:
pEl
.
offsetLeft
,
top
:
pEl
.
offsetTop
-
textEl
.
scrollTop
// left: pEl.getBoundingClientRect().left,
// top: pEl.getBoundingClientRect().top
};
textEl
.
parentNode
.
removeChild
(
hideEl
);
this
.
showSelectUser
=
true
;
this
.
queryInfo
.
startPosition
=
getPosition
(
this
.
id
)
+
1
;
this
.
queryInfo
.
endPosition
=
getPosition
(
this
.
id
)
+
1
;
this
.
$emit
(
"
queryUserList
"
,
this
.
queryInfo
.
keyWord
);
});
},
createHideEl
(
type
)
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
if
(
!
textEl
)
return
;
...
...
@@ -394,14 +294,11 @@ export default {
this
.
autoSize
&&
!
this
.
fullScreen
&&
!
this
.
height
?
"
hidden
"
:
"
auto
"
;
textEl
.
parentNode
.
removeChild
(
hideEl
);
},
handleEnter
()
{
handleEnter
(
e
)
{
if
(
this
.
showSelectUser
)
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
textEl
.
blur
();
setTimeout
(()
=>
{
textEl
.
focus
();
// this.showSelectUser = false;
},
0
);
const
activeUser
=
this
.
userList
[
this
.
activeUserIndex
];
this
.
handleSelectUser
(
activeUser
);
e
.
preventDefault
();
return
;
}
this
.
$emit
(
"
enter
"
);
...
...
src/components/content/mixins/render-mixins.js
0 → 100644
浏览文件 @
6cd70f38
import
{
getFilteredTags
,
getLinkTags
,
addLanguageClass
}
from
"
@/assets/js/utils
"
;
import
marked
from
"
marked
"
;
import
DOMPurify
from
"
dompurify
"
;
export
default
{
methods
:
{
transferMarkdown
(
val
)
{
this
.
rerender
();
marked
.
setOptions
({
breaks
:
true
,
gfm
:
true
,
langPrefix
:
"
language-
"
,
highlight
:
function
(
code
,
lang
,
callback
)
{
let
html
=
require
(
"
highlight.js
"
).
highlightAuto
(
code
).
value
;
return
html
;
}
});
const
str
=
val
+
""
;
const
html
=
marked
(
str
);
// 解析markdown
const
virtualDom
=
addLanguageClass
(
html
);
// 如果没指定语言,添加默认语言
const
cleanHtml
=
DOMPurify
.
sanitize
(
virtualDom
.
innerHTML
,
{
FORBID_TAGS
:
[
"
style
"
,
"
script
"
,
"
select
"
,
"
option
"
,
"
input
"
,
"
textarea
"
,
"
form
"
,
"
button
"
]
});
// 去除标签
const
filteredTags
=
getFilteredTags
(
html
,
cleanHtml
);
// 计算是否有标签被过滤
// 链接转换为卡片
const
{
vDom
,
links
}
=
getLinkTags
(
this
.
id
,
cleanHtml
);
this
.
$emit
(
"
getFilteredTags
"
,
filteredTags
);
this
.
$emit
(
"
update:html
"
,
cleanHtml
);
if
(
links
.
length
)
this
.
$emit
(
"
renderLinksHtml
"
,
{
vDom
,
links
});
},
rerender
()
{
const
renderer
=
{
image
(
href
,
title
,
text
)
{
if
(
href
===
null
)
{
return
text
;
}
// ![file](...)渲染文件,只可以下载
if
(
text
===
"
file
"
)
{
return
`<div class="md_file_card md_flex_card">
<span class="md_file_img icon iconfont icon-doc"></span>
<span class="flex-1">
<span class="md_file_title">
${
title
}
</span>
<span class="md_file_desc">16.6KB</span>
</span>
<span class="md_file_controls">
<a href="
${
href
}
" download target="_blank" class="md_file_download icon iconfont icon-xiazai"></a>
</span>
</div>`
;
}
// ![img](...)渲染图片
let
out
=
'
<img src="
'
+
href
+
'
" alt="
'
+
text
+
'
"
'
;
if
(
title
)
{
out
+=
'
title="
'
+
title
+
'
"
'
;
}
out
+=
"
/>
"
;
return
out
;
}
};
marked
.
use
({
renderer
});
}
}
};
src/components/content/mixins/select-user-mixins.js
0 → 100644
浏览文件 @
6cd70f38
import
{
getPosition
,
formatText
}
from
"
@/assets/js/utils
"
;
export
default
{
methods
:
{
handleSelectUser
(
user
)
{
const
originalText
=
this
.
textContent
;
const
queryInfo
=
this
.
queryInfo
;
const
cursorPosition
=
getPosition
(
this
.
id
);
const
username
=
user
.
name
+
"
"
;
const
newText
=
originalText
.
slice
(
0
,
queryInfo
.
startPosition
)
+
username
+
originalText
.
slice
(
queryInfo
.
endPosition
);
this
.
textContent
=
newText
;
this
.
emitText
();
this
.
showSelectUser
=
false
;
this
.
$nextTick
(()
=>
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
textEl
.
setSelectionRange
(
cursorPosition
+
username
.
length
,
cursorPosition
+
username
.
length
);
textEl
.
focus
();
});
},
handleQueryUser
()
{
const
endPosition
=
getPosition
(
this
.
id
);
const
startPosition
=
this
.
queryInfo
.
startPosition
;
const
keyWord
=
this
.
textContent
.
slice
(
startPosition
,
endPosition
);
this
.
queryInfo
.
endPosition
=
endPosition
;
if
(
endPosition
<
startPosition
||
keyWord
.
slice
(
-
1
)
===
"
"
)
{
this
.
showSelectUser
=
false
;
return
;
}
this
.
queryInfo
.
keyWord
=
keyWord
;
this
.
$emit
(
"
queryUserList
"
,
keyWord
);
},
handleCallUser
(
e
)
{
if
(
e
.
key
===
"
@
"
)
{
this
.
createSelectUserDialog
();
}
},
createSelectUserDialog
()
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
if
(
!
textEl
)
return
;
const
height
=
getComputedStyle
(
textEl
).
getPropertyValue
(
"
height
"
);
const
width
=
getComputedStyle
(
textEl
).
getPropertyValue
(
"
width
"
);
const
scrollTop
=
textEl
.
scrollTop
;
const
originalText
=
this
.
textContent
;
const
cursorPoint
=
getPosition
(
this
.
id
);
const
selectionInfo
=
{
selectionStart
:
cursorPoint
,
selectionEnd
:
cursorPoint
};
const
newText
=
formatText
(
originalText
,
selectionInfo
,
"
<span id='call_position'>
"
,
"
</span>
"
);
const
hideEl
=
this
.
createHideEl
(
"
clac_position_El_
"
);
hideEl
.
style
.
position
=
"
absolute
"
;
hideEl
.
style
.
width
=
width
;
hideEl
.
style
.
height
=
height
;
hideEl
.
style
.
overflowY
=
"
auto
"
;
hideEl
.
style
.
wordBreak
=
"
break-all
"
;
hideEl
.
style
.
top
=
"
14px
"
;
hideEl
.
style
.
left
=
0
;
hideEl
.
style
.
whiteSpace
=
"
pre-wrap
"
;
hideEl
.
innerHTML
=
newText
;
this
.
$nextTick
(()
=>
{
hideEl
.
scrollTop
=
scrollTop
;
const
pEl
=
document
.
getElementById
(
"
call_position
"
);
this
.
selectUserPosition
=
{
left
:
pEl
.
offsetLeft
,
top
:
pEl
.
offsetTop
-
textEl
.
scrollTop
// left: pEl.getBoundingClientRect().left,
// top: pEl.getBoundingClientRect().top
};
textEl
.
parentNode
.
removeChild
(
hideEl
);
this
.
showSelectUser
=
true
;
this
.
queryInfo
.
startPosition
=
getPosition
(
this
.
id
)
+
1
;
this
.
queryInfo
.
endPosition
=
getPosition
(
this
.
id
)
+
1
;
this
.
$emit
(
"
queryUserList
"
,
this
.
queryInfo
.
keyWord
);
});
}
}
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录